[llvm] 88d00a6 - Reland [dsymutil] Add support for mergeable libraries (#70256)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 26 10:45:11 PDT 2023
Author: Alpha Abdoulaye
Date: 2023-10-26T10:45:08-07:00
New Revision: 88d00a6897d71fded96a4f806ce5ebc46fd2a0de
URL: https://github.com/llvm/llvm-project/commit/88d00a6897d71fded96a4f806ce5ebc46fd2a0de
DIFF: https://github.com/llvm/llvm-project/commit/88d00a6897d71fded96a4f806ce5ebc46fd2a0de.diff
LOG: Reland [dsymutil] Add support for mergeable libraries (#70256)
Reland https://reviews.llvm.org/D158124
Fixed `-fpermissive` error reported by gcc only.
Added:
llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib
llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib
llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib
llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib
llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib
llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib
llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib
llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
llvm/tools/dsymutil/RelocationMap.cpp
llvm/tools/dsymutil/RelocationMap.h
Modified:
llvm/docs/CommandGuide/dsymutil.rst
llvm/include/llvm/BinaryFormat/Dwarf.def
llvm/include/llvm/BinaryFormat/MachO.h
llvm/include/llvm/DWARFLinker/DWARFLinker.h
llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
llvm/include/llvm/TargetParser/Triple.h
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/lib/TargetParser/Triple.cpp
llvm/test/tools/dsymutil/basic-linking.test
llvm/test/tools/dsymutil/cmdline.test
llvm/tools/dsymutil/CMakeLists.txt
llvm/tools/dsymutil/DebugMap.cpp
llvm/tools/dsymutil/DebugMap.h
llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
llvm/tools/dsymutil/DwarfLinkerForBinary.h
llvm/tools/dsymutil/LinkUtils.h
llvm/tools/dsymutil/MachODebugMapParser.cpp
llvm/tools/dsymutil/Options.td
llvm/tools/dsymutil/dsymutil.cpp
llvm/tools/dsymutil/dsymutil.h
llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
llvm/tools/llvm-nm/llvm-nm.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 02243e227a24d4a..df621a429bb5c38 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -32,11 +32,26 @@ OPTIONS
architectures will be linked by default and any architectures that can't be
properly linked will cause :program:`dsymutil` to return an error.
+.. option:: --build-variant-suffix <suffix=buildvariant>
+
+ Specify the build variant suffix used to build the executabe file.
+ There can be multiple variants for the binary of a product, each built
+ slightly
diff erently. The most common build variants are 'debug' and
+ 'profile'. Setting the DYLD_IMAGE_SUFFIX environment variable will
+ cause dyld to load the specified variant at runtime.
+
.. option:: --dump-debug-map
Dump the *executable*'s debug-map (the list of the object files containing the
debug information) in YAML format and exit. No DWARF link will take place.
+ .. option:: -D <path>
+
+ Specify a directory that contain dSYM files to search for.
+ This is used for mergeable libraries, so dsymutil knows where to look
+ for dSYM files with debug information about symbols present in those
+ libraries.
+
.. option:: --fat64
Use a 64-bit header when emitting universal binaries.
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index fb328a025773252..d1abb1f361d3edf 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -629,6 +629,7 @@ HANDLE_DW_AT(0x3fec, APPLE_objc_complete_type, 0, APPLE)
HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE)
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
+HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
// Attribute form encodings.
HANDLE_DW_FORM(0x01, addr, 2, DWARF)
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index 49991ebe7bfaf27..bef70f869520b78 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -373,6 +373,7 @@ enum StabType {
N_SSYM = 0x60u,
N_SO = 0x64u,
N_OSO = 0x66u,
+ N_LIB = 0x68u,
N_LSYM = 0x80u,
N_BINCL = 0x82u,
N_SOL = 0x84u,
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 6887e441ce8ff62..2bd85e30d3b13b0 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -62,6 +62,9 @@ class AddressesMap {
virtual std::optional<int64_t>
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
+ /// Returns the file name associated to the AddessesMap
+ virtual std::optional<StringRef> getLibraryInstallName() = 0;
+
/// Apply the valid relocations to the buffer \p Data, taking into
/// account that Data is at \p BaseOffset in the .debug_info section.
///
@@ -69,6 +72,23 @@ class AddressesMap {
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
bool IsLittleEndian) = 0;
+ /// Check if the linker needs to gather and save relocation info.
+ virtual bool needToSaveValidRelocs() = 0;
+
+ /// Update and save original relocations located in between StartOffset and
+ /// EndOffset. LinkedOffset is the value which should be added to the original
+ /// relocation offset to get new relocation offset in linked binary.
+ virtual void updateAndSaveValidRelocs(bool IsDWARF5,
+ uint64_t OriginalUnitOffset,
+ int64_t LinkedOffset,
+ uint64_t StartOffset,
+ uint64_t EndOffset) = 0;
+
+ /// Update the valid relocations that used OriginalUnitOffset as the compile
+ /// unit offset, and update their values to reflect OutputUnitOffset.
+ virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset) = 0;
+
/// Erases all data.
virtual void clear() = 0;
};
@@ -751,6 +771,9 @@ class DWARFLinker {
/// Is there a DW_AT_str_offsets_base in the CU?
bool AttrStrOffsetBaseSeen = false;
+ /// Is there a DW_AT_APPLE_origin in the CU?
+ bool HasAppleOrigin = false;
+
AttributesInfo() = default;
};
diff --git a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
index 22fbec20d7d3766..b451fee4e0b723a 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
+++ b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
@@ -55,6 +55,9 @@ class AddressesMap {
virtual std::optional<int64_t>
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
+ // Returns the library install name associated to the AddessesMap.
+ virtual std::optional<StringRef> getLibraryInstallName() = 0;
+
/// Apply the valid relocations to the buffer \p Data, taking into
/// account that Data is at \p BaseOffset in the .debug_info section.
///
@@ -62,6 +65,21 @@ class AddressesMap {
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
bool IsLittleEndian) = 0;
+ /// Check if the linker needs to gather and save relocation info.
+ virtual bool needToSaveValidRelocs() = 0;
+
+ /// Update and save relocation values to be serialized
+ virtual void updateAndSaveValidRelocs(bool IsDWARF5,
+ uint64_t OriginalUnitOffset,
+ int64_t LinkedOffset,
+ uint64_t StartOffset,
+ uint64_t EndOffset) = 0;
+
+ /// Update the valid relocations that used OriginalUnitOffset as the compile
+ /// unit offset, and update their values to reflect OutputUnitOffset.
+ virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset) = 0;
+
/// Erases all data.
virtual void clear() = 0;
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 53cef0abbe0e139..0f56ac68c851f67 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -418,9 +418,6 @@ class Triple {
/// Get the architecture (first) component of the triple.
StringRef getArchName() const;
- /// Get the architecture name based on Kind and SubArch.
- StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch) const;
-
/// Get the vendor (second) component of the triple.
StringRef getVendorName() const;
@@ -1118,6 +1115,9 @@ class Triple {
/// Get the canonical name for the \p Kind architecture.
static StringRef getArchTypeName(ArchType Kind);
+ /// Get the architecture name based on \p Kind and \p SubArch.
+ static StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch);
+
/// Get the "prefix" canonical name for the \p Kind architecture. This is the
/// prefix used by the architecture specific builtins, and is suitable for
/// passing to \see Intrinsic::getIntrinsicForClangBuiltin().
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 2d8360f100c1172..80a4e2adefa6cb6 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1026,6 +1026,15 @@ unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
StringEntry = DebugLineStrPool.getEntry(*String);
} else {
StringEntry = DebugStrPool.getEntry(*String);
+
+ if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
+ Info.HasAppleOrigin = true;
+ if (std::optional<StringRef> FileName =
+ ObjFile.Addresses->getLibraryInstallName()) {
+ StringEntry = DebugStrPool.getEntry(*FileName);
+ }
+ }
+
// Update attributes info.
if (AttrSpec.Attr == dwarf::DW_AT_name)
Info.Name = StringEntry;
@@ -1637,6 +1646,12 @@ shouldSkipAttribute(bool Update,
}
}
+struct AttributeLinkedOffsetFixup {
+ int64_t LinkedOffsetFixupVal;
+ uint64_t InputAttrStartOffset;
+ uint64_t InputAttrEndOffset;
+};
+
DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
const DWARFFile &File, CompileUnit &Unit,
int64_t PCOffset, uint32_t OutOffset,
@@ -1720,6 +1735,9 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
Flags |= TF_SkipPC;
}
+ std::optional<StringRef> LibraryInstallName =
+ ObjFile.Addresses->getLibraryInstallName();
+ SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
for (const auto &AttrSpec : Abbrev->attributes()) {
if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) {
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
@@ -1727,17 +1745,41 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
continue;
}
+ AttributeLinkedOffsetFixup CurAttrFixup;
+ CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;
+ CurAttrFixup.LinkedOffsetFixupVal =
+ Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
+
DWARFFormValue Val = AttrSpec.getFormValue();
uint64_t AttrSize = Offset;
Val.extractValue(Data, &Offset, U.getFormParams(), &U);
+ CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;
AttrSize = Offset - AttrSize;
- OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec,
- AttrSize, AttrInfo, IsLittleEndian);
+ uint64_t FinalAttrSize =
+ cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
+ AttrInfo, IsLittleEndian);
+ if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
+ AttributesFixups.push_back(CurAttrFixup);
+
+ OutOffset += FinalAttrSize;
}
- // Look for accelerator entries.
uint16_t Tag = InputDIE.getTag();
+ // Add the DW_AT_APPLE_origin attribute to Compile Unit die if we have
+ // an install name and the DWARF doesn't have the attribute yet.
+ const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) &&
+ LibraryInstallName.has_value() &&
+ !AttrInfo.HasAppleOrigin;
+ if (NeedsAppleOrigin) {
+ auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
+ Die->addValue(DIEAlloc, dwarf::Attribute(dwarf::DW_AT_APPLE_origin),
+ dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset()));
+ AttrInfo.Name = StringEntry;
+ OutOffset += 4;
+ }
+
+ // Look for accelerator entries.
// FIXME: This is slightly wrong. An inline_subroutine without a
// low_pc, but with AT_ranges might be interesting to get into the
// accelerator tables too. For now stick with dsymutil's behavior.
@@ -1806,8 +1848,19 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
Linker.assignAbbrev(NewAbbrev);
Die->setAbbrevNumber(NewAbbrev.getNumber());
+ uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber());
+
// Add the size of the abbreviation number to the output offset.
- OutOffset += getULEB128Size(Die->getAbbrevNumber());
+ OutOffset += AbbrevNumberSize;
+
+ // Update fixups with the size of the abbreviation number
+ for (AttributeLinkedOffsetFixup &F : AttributesFixups)
+ F.LinkedOffsetFixupVal += AbbrevNumberSize;
+
+ for (AttributeLinkedOffsetFixup &F : AttributesFixups)
+ ObjFile.Addresses->updateAndSaveValidRelocs(
+ Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
+ F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset);
if (!HasChildren) {
// Update our size.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index b9fab469f747607..5d4eb79675f8916 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -90,6 +90,36 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
llvm_unreachable("Invalid ArchType!");
}
+StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) {
+ switch (Kind) {
+ case Triple::mips:
+ if (SubArch == MipsSubArch_r6)
+ return "mipsisa32r6";
+ break;
+ case Triple::mipsel:
+ if (SubArch == MipsSubArch_r6)
+ return "mipsisa32r6el";
+ break;
+ case Triple::mips64:
+ if (SubArch == MipsSubArch_r6)
+ return "mipsisa64r6";
+ break;
+ case Triple::mips64el:
+ if (SubArch == MipsSubArch_r6)
+ return "mipsisa64r6el";
+ break;
+ case Triple::aarch64:
+ if (SubArch == AArch64SubArch_arm64ec)
+ return "arm64ec";
+ if (SubArch == AArch64SubArch_arm64e)
+ return "arm64e";
+ break;
+ default:
+ break;
+ }
+ return getArchTypeName(Kind);
+}
+
StringRef Triple::getArchTypePrefix(ArchType Kind) {
switch (Kind) {
default:
@@ -1143,34 +1173,6 @@ StringRef Triple::getArchName() const {
return StringRef(Data).split('-').first; // Isolate first component
}
-StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) const {
- switch (Kind) {
- case Triple::mips:
- if (SubArch == MipsSubArch_r6)
- return "mipsisa32r6";
- break;
- case Triple::mipsel:
- if (SubArch == MipsSubArch_r6)
- return "mipsisa32r6el";
- break;
- case Triple::mips64:
- if (SubArch == MipsSubArch_r6)
- return "mipsisa64r6";
- break;
- case Triple::mips64el:
- if (SubArch == MipsSubArch_r6)
- return "mipsisa64r6el";
- break;
- case Triple::aarch64:
- if (SubArch == AArch64SubArch_arm64ec)
- return "arm64ec";
- break;
- default:
- break;
- }
- return getArchTypeName(Kind);
-}
-
StringRef Triple::getVendorName() const {
StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
return Tmp.split('-').first; // Isolate second component
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..14d6272d3f8d97f
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.bar-relink-variant.dylib</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib
new file mode 100644
index 000000000000000..ec2e06a231f8894
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
new file mode 100644
index 000000000000000..68fd250cdf2a8a7
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
@@ -0,0 +1,8 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: bar-relink-variant.dylib
+relocations:
+ - { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+ - { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
+ - { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..37c2a8aebe4c6ff
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.bar-relink.dylib</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib
new file mode 100644
index 000000000000000..9ebd56ecb00a482
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
new file mode 100644
index 000000000000000..d47e5f9e2e8d276
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
@@ -0,0 +1,8 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: bar-relink.dylib
+relocations:
+ - { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+ - { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
+ - { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
new file mode 100644
index 000000000000000..a813562d59671ca
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
new file mode 100644
index 000000000000000..b1b517d11172fd2
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..7e84e95bd3f48cc
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.foo-relink-variant.dylib</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib
new file mode 100644
index 000000000000000..523f85712de567a
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib
new file mode 100644
index 000000000000000..523f85712de567a
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
new file mode 100644
index 000000000000000..0bc06e9a9e857ac
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
@@ -0,0 +1,9 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: foo-relink-variant.dylib
+relocations:
+ - { offset: 0x26, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F64, symSize: 0x20 }
+ - { offset: 0x33, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F64, symSize: 0x20 }
+ - { offset: 0x88, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F84, symSize: 0x24 }
+ - { offset: 0x95, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F84, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..e91926013155858
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.foo-relink.dylib</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib
new file mode 100644
index 000000000000000..94480df788f119b
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
new file mode 100644
index 000000000000000..0db1b30e9d126ee
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
@@ -0,0 +1,10 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: foo-relink.dylib
+relocations:
+ - { offset: 0x26, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F54, symSize: 0x20 }
+ - { offset: 0x33, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F54, symSize: 0x20 }
+ - { offset: 0x5B, size: 0x8, addend: 0x0, symName: _foo_unused, symObjAddr: 0x20, symBinAddr: 0x3F74, symSize: 0x8 }
+ - { offset: 0xA1, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F7C, symSize: 0x24 }
+ - { offset: 0xAE, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F7C, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..425df2f6c841d8a
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.proxy-relink.dylib</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib
new file mode 100644
index 000000000000000..c79d8f7825b58cc
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
new file mode 100644
index 000000000000000..44dd0a2342da84b
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
@@ -0,0 +1,14 @@
+---
+triple: 'arm64-apple-darwin'
+binary-path: proxy-relink.dylib
+relocations:
+ - { offset: 0x26, size: 0x8, addend: 0x0, symName: _display, symObjAddr: 0x0, symBinAddr: 0x3F1C, symSize: 0x1C }
+ - { offset: 0x41, size: 0x8, addend: 0x0, symName: _display, symObjAddr: 0x0, symBinAddr: 0x3F1C, symSize: 0x1C }
+ - { offset: 0x7C, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x3FA0, symBinAddr: 0x3F38, symSize: 0x8 }
+ - { offset: 0x99, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x4000, symBinAddr: 0x8000, symSize: 0x0 }
+ - { offset: 0xA9, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x3FA0, symBinAddr: 0x3F38, symSize: 0x8 }
+ - { offset: 0xE8, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x3F60, symBinAddr: 0x3F40, symSize: 0x24 }
+ - { offset: 0xF9, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x3F60, symBinAddr: 0x3F40, symSize: 0x24 }
+ - { offset: 0x14E, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x3F84, symBinAddr: 0x3F64, symSize: 0x24 }
+ - { offset: 0x15F, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x3F84, symBinAddr: 0x3F64, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib
new file mode 100644
index 000000000000000..333ac9f5d904ce2
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
new file mode 100644
index 000000000000000..3c434096f7dc973
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
diff er
diff --git a/llvm/test/tools/dsymutil/basic-linking.test b/llvm/test/tools/dsymutil/basic-linking.test
index cc521430b0c8715..88cd3293efa2427 100644
--- a/llvm/test/tools/dsymutil/basic-linking.test
+++ b/llvm/test/tools/dsymutil/basic-linking.test
@@ -2,6 +2,9 @@ RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic.macho.x86
RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic-lto.macho.x86_64 | FileCheck %s --check-prefix=CHECK-LTO
RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefix=CHECK-ARCHIVE
RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic.macho.x86_64 %p/Inputs/basic-lto.macho.x86_64 %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefixes=CHECK,CHECK-LTO,CHECK-ARCHIVE
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -D %p/Inputs %p/Inputs/basic-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -D %p/Inputs %p/Inputs/two-level-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK-TWO
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -build-variant-suffix=_debug -D WrongPath -D %p/Inputs %p/Inputs/variant-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK-VARIANT
This test check the basic Dwarf linking process through the debug dumps.
@@ -175,3 +178,122 @@ CHECK-ARCHIVE: Found valid debug map entry: _inc 0x0000000000000070 => 0x0000000
CHECK-ARCHIVE-NEXT: Keeping subprogram DIE:
CHECK-ARCHIVE-NEXT: DW_TAG_subprogram
CHECK-ARCHIVE-NEXT: DW_AT_name {{.*}}"inc")
+
+
+================================= Simple relink ================================
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}basic-relink.macho.arm64.o
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}basic-relink.macho.arm64.c
+
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}foo-relink.dylib
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}foo-relink.c
+
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}altfoo-relink.c
+
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}bar-relink.dylib
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}bar-relink.c
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _display 0x0000000000000000 => 0x0000000000003f10
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK: DW_AT_name{{.*}}"display"
+
+CHECK-RELINK: Found valid debug map entry: _foo 0x0000000000003f54 => 0x0000000000003f2c
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK: DW_AT_name {{.*}}"foo"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _foo_unused 0x0000000000003f74 => 0x0000000000003f4c
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK: DW_AT_name {{.*}}"foo_unused"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _altfoo 0x0000000000003f7c => 0x0000000000003f54
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK: DW_AT_name {{.*}}"altfoo"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _baz 0x0000000000004000 => 0x0000000000008000
+CHECK-RELINK-NEXT: Keeping variable DIE:
+CHECK-RELINK-NEXT: DW_TAG_variable
+CHECK-RELINK-NEXT: DW_AT_name {{.*}}"baz"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _bar 0x0000000000003fa0 => 0x0000000000003f78
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK: DW_AT_name {{.*}}"bar"
+
+================================= Two level relink ================================
+CHECK-RELINK-TWO: DEBUG MAP OBJECT: {{.*}}proxy-relink.dylib
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}two-level-relink.macho.arm64.c
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}bar-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/bar-relink.dylib
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}foo-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/foo-relink.dylib
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}altfoo-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/foo-relink.dylib
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _display 0x0000000000003f1c => 0x0000000000003f1c
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO: DW_AT_name{{.*}}"display"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _baz 0x0000000000008000 => 0x0000000000008000
+CHECK-RELINK-TWO-NEXT: Keeping variable DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_variable
+CHECK-RELINK-TWO-NEXT: DW_AT_name {{.*}}"baz"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _bar 0x0000000000003f38 => 0x0000000000003f38
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO: DW_AT_name {{.*}}"bar"
+
+CHECK-RELINK-TWO: Found valid debug map entry: _foo 0x0000000000003f40 => 0x0000000000003f40
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO: DW_AT_name {{.*}}"foo"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _altfoo 0x0000000000003f64 => 0x0000000000003f64
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO: DW_AT_name {{.*}}"altfoo"
+
+================================= Build variants relink ================================
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}basic-relink.macho.arm64.o
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}foo-relink-variant_debug.dylib
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}bar-relink-variant.dylib
diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 2317852f3c489e2..36cf3f542695ca4 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -7,7 +7,9 @@ HELP-NOT: -reverse-iterate
HELP: Dsymutil Options:
CHECK: -accelerator
CHECK: -arch <arch>
+CHECK: -build-variant-suffix <suffix=buildvariant>
CHECK: -dump-debug-map
+CHECK: -D <path>
CHECK: -fat64
CHECK: -flat
CHECK: -gen-reproducer
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index 3cb7594d2fd920d..c612bfd9150c47f 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_tool(dsymutil
MachODebugMapParser.cpp
MachOUtils.cpp
Reproducer.cpp
+ RelocationMap.cpp
SymbolMap.cpp
DEPENDS
diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp
index d4e2c2b2cfac7d2..dcdecdfe8210b11 100644
--- a/llvm/tools/dsymutil/DebugMap.cpp
+++ b/llvm/tools/dsymutil/DebugMap.cpp
@@ -45,6 +45,11 @@ DebugMapObject::DebugMapObject(StringRef ObjectFilename,
bool DebugMapObject::addSymbol(StringRef Name,
std::optional<uint64_t> ObjectAddress,
uint64_t LinkedAddress, uint32_t Size) {
+ if (Symbols.count(Name)) {
+ // Symbol was previously added.
+ return true;
+ }
+
auto InsertResult = Symbols.insert(
std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
@@ -53,6 +58,12 @@ bool DebugMapObject::addSymbol(StringRef Name,
return InsertResult.second;
}
+void DebugMapObject::setRelocationMap(dsymutil::RelocationMap &RM) {
+ RelocMap.emplace(RM);
+}
+
+void DebugMapObject::setInstallName(StringRef IN) { InstallName.emplace(IN); }
+
void DebugMapObject::print(raw_ostream &OS) const {
OS << getObjectFilename() << ":\n";
// Sort the symbols in alphabetical order, like llvm-nm (and to get
@@ -158,8 +169,8 @@ struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
};
-void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
- mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
+void MappingTraits<std::pair<std::string, SymbolMapping>>::mapping(
+ IO &io, std::pair<std::string, SymbolMapping> &s) {
io.mapRequired("sym", s.first);
io.mapOptional("objAddr", s.second.ObjectAddress);
io.mapRequired("binAddr", s.second.BinaryAddress);
@@ -275,7 +286,13 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
}
}
- dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
+ uint8_t Type = MachO::N_OSO;
+ if (Path.endswith(".dylib")) {
+ // FIXME: find a more resilient way
+ Type = MachO::N_LIB;
+ }
+ dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), Type);
+
for (auto &Entry : Entries) {
auto &Mapping = Entry.second;
std::optional<uint64_t> ObjAddress;
diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h
index 86cb88d32492d3d..9c3a698fa1191d0 100644
--- a/llvm/tools/dsymutil/DebugMap.h
+++ b/llvm/tools/dsymutil/DebugMap.h
@@ -21,6 +21,7 @@
#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
+#include "RelocationMap.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -134,22 +135,6 @@ class DebugMap {
/// linked binary for all the linked atoms in this object file.
class DebugMapObject {
public:
- struct SymbolMapping {
- std::optional<yaml::Hex64> ObjectAddress;
- yaml::Hex64 BinaryAddress;
- yaml::Hex32 Size;
-
- SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
- uint32_t Size)
- : BinaryAddress(BinaryAddress), Size(Size) {
- if (ObjectAddr)
- ObjectAddress = *ObjectAddr;
- }
-
- /// For YAML IO support
- SymbolMapping() = default;
- };
-
using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
using DebugMapEntry = StringMapEntry<SymbolMapping>;
@@ -182,6 +167,16 @@ class DebugMapObject {
}
const std::vector<std::string> &getWarnings() const { return Warnings; }
+ const std::optional<RelocationMap> &getRelocationMap() const {
+ return RelocMap;
+ }
+ void setRelocationMap(dsymutil::RelocationMap &RM);
+
+ const std::optional<std::string> &getInstallName() const {
+ return InstallName;
+ }
+ void setInstallName(StringRef IN);
+
void print(raw_ostream &OS) const;
#ifndef NDEBUG
void dump() const;
@@ -196,10 +191,13 @@ class DebugMapObject {
std::string Filename;
sys::TimePoint<std::chrono::seconds> Timestamp;
- StringMap<SymbolMapping> Symbols;
+ StringMap<struct SymbolMapping> Symbols;
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
uint8_t Type;
+ std::optional<RelocationMap> RelocMap;
+ std::optional<std::string> InstallName;
+
std::vector<std::string> Warnings;
/// For YAMLIO support.
@@ -225,10 +223,8 @@ namespace yaml {
using namespace llvm::dsymutil;
-template <>
-struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
- static void mapping(IO &io,
- std::pair<std::string, DebugMapObject::SymbolMapping> &s);
+template <> struct MappingTraits<std::pair<std::string, SymbolMapping>> {
+ static void mapping(IO &io, std::pair<std::string, SymbolMapping> &s);
static const bool flow = true;
};
@@ -237,12 +233,6 @@ template <> struct MappingTraits<dsymutil::DebugMapObject> {
static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
};
-template <> struct ScalarTraits<Triple> {
- static void output(const Triple &val, void *, raw_ostream &out);
- static StringRef input(StringRef scalar, void *, Triple &value);
- static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
-};
-
template <>
struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
static size_t
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 39776ae5a92000b..a8fea1e2712271d 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -189,6 +189,44 @@ static Error remarksErrorHandler(const DebugMapObject &DMO,
return createFileError(FE->getFileName(), std::move(NewE));
}
+template <typename OutDwarfFile, typename AddressMap>
+Error DwarfLinkerForBinary::emitRelocations(
+ const DebugMap &DM,
+ std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking) {
+ // Return early if the "Resources" directory is not being written to.
+ if (!Options.ResourceDir)
+ return Error::success();
+
+ RelocationMap RM(DM.getTriple(), DM.getBinaryPath());
+ for (auto &Obj : ObjectsForLinking) {
+ if (!Obj.OutRelocs->isInitialized())
+ continue;
+ Obj.OutRelocs->addValidRelocs(RM);
+ }
+
+ SmallString<128> InputPath;
+ SmallString<128> Path;
+ // Create the "Relocations" directory in the "Resources" directory, and
+ // create an architecture-specific directory in the "Relocations" directory.
+ StringRef ArchName = Triple::getArchName(RM.getTriple().getArch(),
+ RM.getTriple().getSubArch());
+ sys::path::append(Path, *Options.ResourceDir, "Relocations", ArchName);
+ if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
+ sys::fs::perms::all_all))
+ return errorCodeToError(EC);
+
+ // Append the file name.
+ sys::path::append(Path, sys::path::filename(DM.getBinaryPath()));
+ Path.append(".yml");
+
+ std::error_code EC;
+ raw_fd_ostream OS(Path.str(), EC, sys::fs::OF_Text);
+ if (EC)
+ return errorCodeToError(EC);
+
+ RM.print(OS);
+ return Error::success();
+}
static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
StringRef ArchName, const remarks::RemarkLinker &RL) {
@@ -229,30 +267,31 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
}
template <typename OutDWARFFile, typename AddressesMap>
-ErrorOr<std::unique_ptr<OutDWARFFile>>
-DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
- const DebugMap &DebugMap,
- remarks::RemarkLinker &RL) {
+ErrorOr<std::unique_ptr<OutDWARFFile>> DwarfLinkerForBinary::loadObject(
+ const DebugMapObject &Obj, const DebugMap &DebugMap,
+ remarks::RemarkLinker &RL,
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {
auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
std::unique_ptr<OutDWARFFile> Res;
if (ErrorOrObj) {
+ auto Context = DWARFContext::create(
+ *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process, nullptr,
+ "",
+ [&](Error Err) {
+ handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
+ reportError(Info.message());
+ });
+ },
+ [&](Error Warning) {
+ handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
+ reportWarning(Info.message());
+ });
+ });
+ DLBRM->init(*Context);
Res = std::make_unique<OutDWARFFile>(
- Obj.getObjectFilename(),
- DWARFContext::create(
- *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process,
- nullptr, "",
- [&](Error Err) {
- handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
- reportError(Info.message());
- });
- },
- [&](Error Warning) {
- handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
- reportWarning(Info.message());
- });
- }),
- std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj),
+ Obj.getObjectFilename(), std::move(Context),
+ std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj, DLBRM),
[&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
Error E = RL.link(*ErrorOrObj);
@@ -614,7 +653,7 @@ template <typename Linker, typename OutDwarfFile, typename AddressMap>
bool DwarfLinkerForBinary::linkImpl(
const DebugMap &Map, typename Linker::OutputFileType ObjectType) {
- std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking;
+ std::vector<ObjectWithRelocMap<OutDwarfFile>> ObjectsForLinking;
DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
@@ -668,10 +707,12 @@ bool DwarfLinkerForBinary::linkImpl(
auto &Obj = DebugMap.addDebugMapObject(
Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
+ auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
- loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL)) {
- ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
- return *ObjectsForLinking.back();
+ loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL,
+ DLBRelocMap)) {
+ ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+ return *ObjectsForLinking.back().Object;
} else {
// Try and emit more helpful warnings by applying some heuristics.
StringRef ObjFile = ContainerName;
@@ -782,15 +823,18 @@ bool DwarfLinkerForBinary::linkImpl(
continue;
}
+ auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
- loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL)) {
- ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
- GeneralLinker->addObjectFile(*ObjectsForLinking.back(), Loader,
+ loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL, DLBRelocMap)) {
+ ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+ GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,
OnCUDieLoaded);
} else {
- ObjectsForLinking.push_back(std::make_unique<OutDwarfFile>(
- Obj->getObjectFilename(), nullptr, nullptr));
- GeneralLinker->addObjectFile(*ObjectsForLinking.back());
+ ObjectsForLinking.push_back(
+ {std::make_unique<OutDwarfFile>(Obj->getObjectFilename(), nullptr,
+ nullptr),
+ DLBRelocMap});
+ GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);
}
}
@@ -815,6 +859,10 @@ bool DwarfLinkerForBinary::linkImpl(
if (Options.NoOutput)
return true;
+ if (Error E =
+ emitRelocations<OutDwarfFile, AddressMap>(Map, ObjectsForLinking))
+ return error(toString(std::move(E)));
+
if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
if (auto E = copySwiftInterfaces(ArchName))
@@ -903,12 +951,14 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
continue;
}
if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
- ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
+ ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping->getKey(),
+ Mapping->getValue());
} else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
// Do not store the addend. The addend was the address of the symbol in
// the object file, the address in the binary that is stored in the debug
// map doesn't need to be offset.
- ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
+ ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset,
+ Mapping->getKey(), Mapping->getValue());
}
}
}
@@ -966,20 +1016,17 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
}
template <typename AddressesMapBase>
-std::vector<
- typename DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
+std::vector<ValidReloc>
DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
- std::vector<
- DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
- Res;
+ std::vector<ValidReloc> Res;
auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
- return Reloc.Offset < StartPos;
+ return (uint64_t)Reloc.Offset < StartPos;
});
while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
- CurReloc->Offset < EndPos) {
+ (uint64_t)CurReloc->Offset < EndPos) {
Res.push_back(*CurReloc);
CurReloc++;
}
@@ -990,12 +1037,12 @@ DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
template <typename AddressesMapBase>
void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
const ValidReloc &Reloc) {
- const auto &Mapping = Reloc.Mapping->getValue();
+ const auto &Mapping = Reloc.SymbolMapping;
const uint64_t ObjectAddress = Mapping.ObjectAddress
? uint64_t(*Mapping.ObjectAddress)
: std::numeric_limits<uint64_t>::max();
- outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
+ outs() << "Found valid debug map entry: " << Reloc.SymbolName << "\t"
<< format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
uint64_t(Mapping.BinaryAddress));
}
@@ -1004,8 +1051,8 @@ template <typename AddressesMapBase>
int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
const ValidReloc &Reloc) {
int64_t AddrAdjust = relocate(Reloc);
- if (Reloc.Mapping->getValue().ObjectAddress)
- AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
+ if (Reloc.SymbolMapping.ObjectAddress)
+ AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);
return AddrAdjust;
}
@@ -1116,12 +1163,40 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
}
}
+template <typename AddressesMapBase>
+std::optional<StringRef> DwarfLinkerForBinary::AddressManager<
+ AddressesMapBase>::getLibraryInstallName() {
+ return LibInstallName;
+}
+
template <typename AddressesMapBase>
uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
const ValidReloc &Reloc) const {
- return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
+ return Reloc.SymbolMapping.BinaryAddress + Reloc.Addend;
+}
+
+template <typename AddressesMapBase>
+void DwarfLinkerForBinary::AddressManager<
+ AddressesMapBase>::updateAndSaveValidRelocs(bool IsDWARF5,
+ uint64_t OriginalUnitOffset,
+ int64_t LinkedOffset,
+ uint64_t StartOffset,
+ uint64_t EndOffset) {
+ std::vector<ValidReloc> InRelocs =
+ getRelocations(ValidDebugInfoRelocs, StartOffset, EndOffset);
+ if (IsDWARF5)
+ InRelocs = getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
+ DwarfLinkerRelocMap->updateAndSaveValidRelocs(
+ IsDWARF5, InRelocs, OriginalUnitOffset, LinkedOffset);
}
+template <typename AddressesMapBase>
+void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
+ updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset) {
+ DwarfLinkerRelocMap->updateRelocationsWithUnitOffset(OriginalUnitOffset,
+ OutputUnitOffset);
+}
/// Apply the valid relocations found by findValidRelocs() to
/// the buffer \p Data, taking into account that Data is at \p BaseOffset
/// in the debug_info section.
@@ -1133,6 +1208,7 @@ uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
template <typename AddressesMapBase>
bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
+
std::vector<ValidReloc> Relocs = getRelocations(
ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
@@ -1148,9 +1224,47 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
assert(CurReloc.Size <= sizeof(Buf));
memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
}
-
return Relocs.size() > 0;
}
+void DwarfLinkerForBinaryRelocationMap::init(DWARFContext &Context) {
+ for (const std::unique_ptr<DWARFUnit> &CU : Context.compile_units())
+ StoredValidDebugInfoRelocsMap.insert(
+ std::make_pair(CU->getOffset(), std::vector<ValidReloc>()));
+ // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::addValidRelocs(RelocationMap &RM) {
+ for (const auto &DebugInfoRelocs : StoredValidDebugInfoRelocsMap) {
+ for (const auto &InfoReloc : DebugInfoRelocs.second)
+ RM.addRelocationMapEntry(InfoReloc);
+ }
+ // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateRelocationsWithUnitOffset(
+ uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {
+ std::vector<ValidReloc> &StoredValidDebugInfoRelocs =
+ StoredValidDebugInfoRelocsMap[OriginalUnitOffset];
+ for (ValidReloc &R : StoredValidDebugInfoRelocs) {
+ R.Offset = (uint64_t)R.Offset + OutputUnitOffset;
+ }
+ // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateAndSaveValidRelocs(
+ bool IsDWARF5, std::vector<ValidReloc> &InRelocs, uint64_t UnitOffset,
+ int64_t LinkedOffset) {
+ std::vector<ValidReloc> &OutRelocs =
+ StoredValidDebugInfoRelocsMap[UnitOffset];
+ if (IsDWARF5)
+ OutRelocs = StoredValidDebugAddrRelocsMap[UnitOffset];
+
+ for (ValidReloc &R : InRelocs) {
+ OutRelocs.emplace_back(R.Offset + LinkedOffset, R.Size, R.Addend,
+ R.SymbolName, R.SymbolMapping);
+ }
+}
+
} // namespace dsymutil
} // namespace llvm
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index 230f569a6988c32..328cd9197d0d170 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -13,6 +13,7 @@
#include "DebugMap.h"
#include "LinkUtils.h"
#include "MachOUtils.h"
+#include "RelocationMap.h"
#include "llvm/DWARFLinker/DWARFLinker.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
@@ -21,10 +22,48 @@
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Remarks/RemarkLinker.h"
#include <mutex>
+#include <optional>
namespace llvm {
namespace dsymutil {
+/// DwarfLinkerForBinaryRelocationMap contains the logic to handle the
+/// relocations and to store them inside an associated RelocationMap.
+class DwarfLinkerForBinaryRelocationMap {
+public:
+ void init(DWARFContext &Context);
+
+ bool isInitialized() {
+ return StoredValidDebugInfoRelocsMap.getMemorySize() != 0;
+ }
+
+ void addValidRelocs(RelocationMap &RM);
+
+ void updateAndSaveValidRelocs(bool IsDWARF5,
+ std::vector<ValidReloc> &InRelocs,
+ uint64_t UnitOffset, int64_t LinkedOffset);
+
+ void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset);
+
+ /// Map compilation unit offset to the valid relocations to store
+ /// @{
+ DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugInfoRelocsMap;
+ DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugAddrRelocsMap;
+ /// @}
+
+ DwarfLinkerForBinaryRelocationMap() = default;
+};
+
+template <typename OutDwarfFile> struct ObjectWithRelocMap {
+ ObjectWithRelocMap(
+ std::unique_ptr<OutDwarfFile> Object,
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs)
+ : Object(std::move(Object)), OutRelocs(OutRelocs) {}
+ std::unique_ptr<OutDwarfFile> Object;
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs;
+};
+
/// The core of the Dsymutil Dwarf linking logic.
///
/// The link of the dwarf information from the object files will be
@@ -67,26 +106,11 @@ class DwarfLinkerForBinary {
/// Keeps track of relocations.
template <typename AddressesMapBase>
class AddressManager : public AddressesMapBase {
- struct ValidReloc {
- uint64_t Offset;
- uint32_t Size;
- uint64_t Addend;
- const DebugMapObject::DebugMapEntry *Mapping;
-
- ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
- const DebugMapObject::DebugMapEntry *Mapping)
- : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
-
- bool operator<(const ValidReloc &RHS) const {
- return Offset < RHS.Offset;
- }
- bool operator<(uint64_t RHS) const { return Offset < RHS; }
- };
const DwarfLinkerForBinary &Linker;
/// The valid relocations for the current DebugMapObject.
- /// This vector is sorted by relocation offset.
+ /// These vectors are sorted by relocation offset.
/// {
std::vector<ValidReloc> ValidDebugInfoRelocs;
std::vector<ValidReloc> ValidDebugAddrRelocs;
@@ -94,6 +118,12 @@ class DwarfLinkerForBinary {
StringRef SrcFileName;
+ uint8_t DebugMapObjectType;
+
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;
+
+ std::optional<std::string> LibInstallName;
+
/// Returns list of valid relocations from \p Relocs,
/// between \p StartOffset and \p NextOffset.
///
@@ -115,9 +145,29 @@ class DwarfLinkerForBinary {
public:
AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
- const DebugMapObject &DMO)
- : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
- findValidRelocsInDebugSections(Obj, DMO);
+ const DebugMapObject &DMO,
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)
+ : Linker(Linker), SrcFileName(DMO.getObjectFilename()),
+ DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) {
+ if (DMO.getRelocationMap().has_value()) {
+ DebugMapObjectType = MachO::N_LIB;
+ LibInstallName.emplace(DMO.getInstallName().value());
+ const RelocationMap &RM = DMO.getRelocationMap().value();
+ for (const auto &Reloc : RM.relocations()) {
+ const auto *DebugMapEntry = DMO.lookupSymbol(Reloc.SymbolName);
+ if (!DebugMapEntry)
+ continue;
+ std::optional<uint64_t> ObjAddress;
+ ObjAddress.emplace(DebugMapEntry->getValue().ObjectAddress.value());
+ ValidDebugInfoRelocs.emplace_back(
+ Reloc.Offset, Reloc.Size, Reloc.Addend, Reloc.SymbolName,
+ SymbolMapping(ObjAddress, DebugMapEntry->getValue().BinaryAddress,
+ DebugMapEntry->getValue().Size));
+ // FIXME: Support relocations debug_addr.
+ }
+ } else {
+ findValidRelocsInDebugSections(Obj, DMO);
+ }
}
~AddressManager() override { clear(); }
@@ -158,9 +208,20 @@ class DwarfLinkerForBinary {
std::optional<int64_t>
getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
+ std::optional<StringRef> getLibraryInstallName() override;
+
bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
bool IsLittleEndian) override;
+ bool needToSaveValidRelocs() override { return true; }
+
+ void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset,
+ int64_t LinkedOffset, uint64_t StartOffset,
+ uint64_t EndOffset) override;
+
+ void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset) override;
+
void clear() override {
ValidDebugInfoRelocs.clear();
ValidDebugAddrRelocs.clear();
@@ -180,11 +241,11 @@ class DwarfLinkerForBinary {
/// Attempt to load a debug object from disk.
ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
const Triple &triple);
-
template <typename OutDWARFFile, typename AddressesMap>
- ErrorOr<std::unique_ptr<OutDWARFFile>> loadObject(const DebugMapObject &Obj,
- const DebugMap &DebugMap,
- remarks::RemarkLinker &RL);
+ ErrorOr<std::unique_ptr<OutDWARFFile>>
+ loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
+ remarks::RemarkLinker &RL,
+ std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
void collectRelocationsToApplyToSwiftReflectionSections(
const object::SectionRef &Section, StringRef &Contents,
@@ -207,6 +268,11 @@ class DwarfLinkerForBinary {
bool linkImpl(const DebugMap &Map,
typename Linker::OutputFileType ObjectType);
+ template <typename OutDwarfFile, typename AddressMap>
+ Error emitRelocations(
+ const DebugMap &DM,
+ std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking);
+
raw_fd_ostream &OutFile;
BinaryHolder &BinHolder;
LinkOptions Options;
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index 88c17d503689951..0bf6d9aac1a3f3b 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -93,6 +93,12 @@ struct LinkOptions {
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
vfs::getRealFileSystem();
+ /// -build-variant-suffix.
+ std::string BuildVariantSuffix;
+
+ /// Paths where to search for the .dSYM files of merged libraries.
+ std::vector<std::string> DSYMSearchPaths;
+
/// Fields used for linking and placing remarks into the .dSYM bundle.
/// @{
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index d9bf2301e21e55f..9623b71714582d5 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -9,6 +9,7 @@
#include "BinaryHolder.h"
#include "DebugMap.h"
#include "MachOUtils.h"
+#include "RelocationMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Object/MachO.h"
@@ -28,9 +29,13 @@ class MachODebugMapParser {
public:
MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
StringRef BinaryPath, ArrayRef<std::string> Archs,
- StringRef PathPrefix = "", bool Verbose = false)
+ ArrayRef<std::string> DSYMSearchPaths,
+ StringRef PathPrefix = "", StringRef VariantSuffix = "",
+ bool Verbose = false)
: BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
- PathPrefix(std::string(PathPrefix)), BinHolder(VFS, Verbose),
+ DSYMSearchPaths(DSYMSearchPaths.begin(), DSYMSearchPaths.end()),
+ PathPrefix(std::string(PathPrefix)),
+ VariantSuffix(std::string(VariantSuffix)), BinHolder(VFS, Verbose),
CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
/// Parses and returns the DebugMaps of the input binary. The binary contains
@@ -47,7 +52,9 @@ class MachODebugMapParser {
private:
std::string BinaryPath;
SmallVector<StringRef, 1> Archs;
+ SmallVector<StringRef, 1> DSYMSearchPaths;
std::string PathPrefix;
+ std::string VariantSuffix;
/// Owns the MemoryBuffer for the main binary.
BinaryHolder BinHolder;
@@ -87,6 +94,9 @@ class MachODebugMapParser {
void
switchToNewDebugMapObject(StringRef Filename,
sys::TimePoint<std::chrono::seconds> Timestamp);
+ void
+ switchToNewLibDebugMapObject(StringRef Filename,
+ sys::TimePoint<std::chrono::seconds> Timestamp);
void resetParserState();
uint64_t getMainBinarySymbolAddress(StringRef Name);
std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
@@ -176,8 +186,6 @@ void MachODebugMapParser::addCommonSymbols() {
/// everything up to add symbols to the new one.
void MachODebugMapParser::switchToNewDebugMapObject(
StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
- addCommonSymbols();
- resetParserState();
SmallString<80> Path(PathPrefix);
sys::path::append(Path, Filename);
@@ -198,11 +206,138 @@ void MachODebugMapParser::switchToNewDebugMapObject(
return;
}
+ addCommonSymbols();
+ resetParserState();
+
CurrentDebugMapObject =
&Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
+
loadCurrentObjectFileSymbols(*Object);
}
+/// Create a new DebugMapObject of type MachO::N_LIB.
+/// This function resets the state of the parser that was
+/// referring to the last object file and sets everything
+/// up to add symbols to the new one.
+void MachODebugMapParser::switchToNewLibDebugMapObject(
+ StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
+
+ if (DSYMSearchPaths.empty()) {
+ Warning("no dSYM search path was specified");
+ return;
+ }
+
+ StringRef LeafName = sys::path::filename(Filename);
+ SmallString<128> VariantLeafName;
+ SmallString<128> ProductName(LeafName);
+
+ // For Framework.framework/Framework and -build-variant-suffix=_debug,
+ // look in the following order:
+ // 1) Framework.framework.dSYM/Contents/Resources/DWARF/Framework_debug
+ // 2) Framework.framework.dSYM/Contents/Resources/DWARF/Framework
+ //
+ // For libName.dylib and -build-variant-suffix=_debug,
+ // look in the following order:
+ // 1) libName.dylib.dSYM/Contents/Resources/DWARF/libName_debug.dylib
+ // 2) libName.dylib.dSYM/Contents/Resources/DWARF/libName.dylib
+
+ size_t libExt = LeafName.rfind(".dylib");
+ if (libExt != StringRef::npos) {
+ if (!VariantSuffix.empty()) {
+ VariantLeafName.append(LeafName.substr(0, libExt));
+ VariantLeafName.append(VariantSuffix);
+ VariantLeafName.append(".dylib");
+ }
+ } else {
+ // Expected to be a framework
+ ProductName.append(".framework");
+ if (!VariantSuffix.empty()) {
+ VariantLeafName.append(LeafName);
+ VariantLeafName.append(VariantSuffix);
+ }
+ }
+
+ for (auto DSYMSearchPath : DSYMSearchPaths) {
+ SmallString<256> Path(DSYMSearchPath);
+ SmallString<256> FallbackPath(Path);
+
+ SmallString<256> DSYMPath(ProductName);
+ DSYMPath.append(".dSYM");
+ sys::path::append(DSYMPath, "Contents", "Resources", "DWARF");
+
+ if (!VariantSuffix.empty()) {
+ sys::path::append(Path, DSYMPath, VariantLeafName);
+ sys::path::append(FallbackPath, DSYMPath, LeafName);
+ } else {
+ sys::path::append(Path, DSYMPath, LeafName);
+ }
+
+ auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ Warning("unable to open object file: " + toString(std::move(Err)),
+ Path.str());
+ if (!VariantSuffix.empty()) {
+ ObjectEntry = BinHolder.getObjectEntry(FallbackPath, Timestamp);
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ Warning("unable to open object file: " + toString(std::move(Err)),
+ FallbackPath.str());
+ continue;
+ }
+ Path.assign(FallbackPath);
+ } else {
+ continue;
+ }
+ }
+
+ auto Object =
+ ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
+ if (!Object) {
+ auto Err = Object.takeError();
+ Warning("unable to open object file: " + toString(std::move(Err)),
+ Path.str());
+ continue;
+ }
+
+ if (CurrentDebugMapObject &&
+ CurrentDebugMapObject->getType() == MachO::N_LIB &&
+ CurrentDebugMapObject->getObjectFilename().compare(Path.str()) == 0) {
+ return;
+ }
+
+ addCommonSymbols();
+ resetParserState();
+
+ CurrentDebugMapObject =
+ &Result->addDebugMapObject(Path, Timestamp, MachO::N_LIB);
+
+ CurrentDebugMapObject->setInstallName(Filename);
+
+ SmallString<256> RMPath(DSYMSearchPath);
+ sys::path::append(RMPath, ProductName);
+ RMPath.append(".dSYM");
+ StringRef ArchName = Triple::getArchName(Result->getTriple().getArch(),
+ Result->getTriple().getSubArch());
+ sys::path::append(RMPath, "Contents", "Resources", "Relocations", ArchName);
+ sys::path::append(RMPath, LeafName);
+ RMPath.append(".yml");
+ const auto &RelocMapPtrOrErr =
+ RelocationMap::parseYAMLRelocationMap(RMPath, PathPrefix);
+ if (auto EC = RelocMapPtrOrErr.getError()) {
+ Warning("cannot parse relocation map file: " + EC.message(),
+ RMPath.str());
+ return;
+ }
+ CurrentDebugMapObject->setRelocationMap(*RelocMapPtrOrErr->get());
+
+ loadCurrentObjectFileSymbols(*Object);
+
+ // Found and loaded new dSYM file
+ return;
+ }
+}
+
static std::string getArchName(const object::MachOObjectFile &Obj) {
Triple T = Obj.getArchTriple();
return std::string(T.getArchName());
@@ -275,23 +410,39 @@ struct DarwinStabName {
const char *Name;
};
-const struct DarwinStabName DarwinStabNames[] = {
- {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
- {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
- {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
- {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
- {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
- {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
- {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
- {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
- {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
- {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
- {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
- {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
- {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
- {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
- {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
- {MachO::N_LENG, "N_LENG"}, {0, nullptr}};
+const struct DarwinStabName DarwinStabNames[] = {{MachO::N_GSYM, "N_GSYM"},
+ {MachO::N_FNAME, "N_FNAME"},
+ {MachO::N_FUN, "N_FUN"},
+ {MachO::N_STSYM, "N_STSYM"},
+ {MachO::N_LCSYM, "N_LCSYM"},
+ {MachO::N_BNSYM, "N_BNSYM"},
+ {MachO::N_PC, "N_PC"},
+ {MachO::N_AST, "N_AST"},
+ {MachO::N_OPT, "N_OPT"},
+ {MachO::N_RSYM, "N_RSYM"},
+ {MachO::N_SLINE, "N_SLINE"},
+ {MachO::N_ENSYM, "N_ENSYM"},
+ {MachO::N_SSYM, "N_SSYM"},
+ {MachO::N_SO, "N_SO"},
+ {MachO::N_OSO, "N_OSO"},
+ {MachO::N_LIB, "N_LIB"},
+ {MachO::N_LSYM, "N_LSYM"},
+ {MachO::N_BINCL, "N_BINCL"},
+ {MachO::N_SOL, "N_SOL"},
+ {MachO::N_PARAMS, "N_PARAM"},
+ {MachO::N_VERSION, "N_VERS"},
+ {MachO::N_OLEVEL, "N_OLEV"},
+ {MachO::N_PSYM, "N_PSYM"},
+ {MachO::N_EINCL, "N_EINCL"},
+ {MachO::N_ENTRY, "N_ENTRY"},
+ {MachO::N_LBRAC, "N_LBRAC"},
+ {MachO::N_EXCL, "N_EXCL"},
+ {MachO::N_RBRAC, "N_RBRAC"},
+ {MachO::N_BCOMM, "N_BCOMM"},
+ {MachO::N_ECOMM, "N_ECOMM"},
+ {MachO::N_ECOML, "N_ECOML"},
+ {MachO::N_LENG, "N_LENG"},
+ {0, nullptr}};
static const char *getDarwinStabString(uint8_t NType) {
for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
@@ -477,13 +628,25 @@ void MachODebugMapParser::handleStabSymbolTableEntry(
const char *Name = &MainBinaryStrings.data()[StringIndex];
+ // An N_LIB entry represents the start of a new library file description.
+ if (Type == MachO::N_LIB) {
+ switchToNewLibDebugMapObject(Name, sys::toTimePoint(Value));
+ return;
+ }
+
// An N_OSO entry represents the start of a new object file description.
+ // If an N_LIB entry was present, this is parsed only if the library
+ // dSYM file could not be found.
if (Type == MachO::N_OSO) {
- if (Duplicates.count(OSO(Name, Value))) {
- SkipDebugMapObject = true;
- return;
+ if (!CurrentDebugMapObject ||
+ CurrentDebugMapObject->getType() != MachO::N_LIB) {
+ if (Duplicates.count(OSO(Name, Value))) {
+ SkipDebugMapObject = true;
+ return;
+ }
+ switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
}
- return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
+ return;
}
if (SkipDebugMapObject)
@@ -694,18 +857,23 @@ namespace dsymutil {
llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath, bool Verbose, bool InputIsYAML) {
+ ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+ StringRef VariantSuffix, bool Verbose, bool InputIsYAML) {
if (InputIsYAML)
return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
- MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, Verbose);
+ MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+ PrependPath, VariantSuffix, Verbose);
+
return Parser.parse();
}
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath) {
- MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
+ ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+ StringRef VariantSuffix) {
+ MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+ PrependPath, VariantSuffix, false);
return Parser.dumpStab();
}
} // namespace dsymutil
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 79f04fdfb036055..da071341cc01f21 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -201,3 +201,14 @@ def linker: Separate<["--", "-"], "linker">,
HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">,
Group<grp_general>;
def: Joined<["--", "-"], "linker=">, Alias<linker>;
+
+def build_variant_suffix: Separate<["--", "-"], "build-variant-suffix">,
+ MetaVarName<"<suffix=buildvariant>">,
+ HelpText<"Specify the build variant suffix used to build the executabe file.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "build-variant-suffix=">, Alias<build_variant_suffix>;
+
+def dsym_search_path: Separate<["-", "--"], "D">,
+ MetaVarName<"<path>">,
+ HelpText<"Specify a directory that contain dSYM files to search for.">,
+ Group<grp_general>;
diff --git a/llvm/tools/dsymutil/RelocationMap.cpp b/llvm/tools/dsymutil/RelocationMap.cpp
new file mode 100644
index 000000000000000..5921e7c9c249521
--- /dev/null
+++ b/llvm/tools/dsymutil/RelocationMap.cpp
@@ -0,0 +1,92 @@
+//===- tools/dsymutil/RelocationMap.cpp - Relocation map representation---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RelocationMap.h"
+
+namespace llvm {
+
+namespace dsymutil {
+
+void RelocationMap::print(raw_ostream &OS) const {
+ yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
+ yout << const_cast<RelocationMap &>(*this);
+}
+
+#ifndef NDEBUG
+void RelocationMap::dump() const { print(errs()); }
+#endif
+
+void RelocationMap::addRelocationMapEntry(const ValidReloc &Relocation) {
+ Relocations.push_back(Relocation);
+}
+
+namespace {
+
+struct YAMLContext {
+ StringRef PrependPath;
+ Triple BinaryTriple;
+};
+
+} // end anonymous namespace
+
+ErrorOr<std::unique_ptr<RelocationMap>>
+RelocationMap::parseYAMLRelocationMap(StringRef InputFile,
+ StringRef PrependPath) {
+ auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+ if (auto Err = ErrOrFile.getError())
+ return Err;
+
+ YAMLContext Ctxt;
+
+ Ctxt.PrependPath = PrependPath;
+
+ std::unique_ptr<RelocationMap> Result;
+ yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
+ yin >> Result;
+
+ if (auto EC = yin.error())
+ return EC;
+ return std::move(Result);
+}
+
+} // end namespace dsymutil
+
+namespace yaml {
+
+void MappingTraits<dsymutil::ValidReloc>::mapping(IO &io,
+ dsymutil::ValidReloc &VR) {
+ io.mapRequired("offset", VR.Offset);
+ io.mapRequired("size", VR.Size);
+ io.mapRequired("addend", VR.Addend);
+ io.mapRequired("symName", VR.SymbolName);
+ io.mapOptional("symObjAddr", VR.SymbolMapping.ObjectAddress);
+ io.mapRequired("symBinAddr", VR.SymbolMapping.BinaryAddress);
+ io.mapRequired("symSize", VR.SymbolMapping.Size);
+}
+
+void MappingTraits<dsymutil::RelocationMap>::mapping(
+ IO &io, dsymutil::RelocationMap &RM) {
+ io.mapRequired("triple", RM.BinaryTriple);
+ io.mapRequired("binary-path", RM.BinaryPath);
+ if (void *Ctxt = io.getContext())
+ reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM.BinaryTriple;
+ io.mapRequired("relocations", RM.Relocations);
+}
+
+void MappingTraits<std::unique_ptr<dsymutil::RelocationMap>>::mapping(
+ IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM) {
+ if (!RM)
+ RM.reset(new RelocationMap());
+ io.mapRequired("triple", RM->BinaryTriple);
+ io.mapRequired("binary-path", RM->BinaryPath);
+ if (void *Ctxt = io.getContext())
+ reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM->BinaryTriple;
+ io.mapRequired("relocations", RM->Relocations);
+}
+} // end namespace yaml
+} // end namespace llvm
diff --git a/llvm/tools/dsymutil/RelocationMap.h b/llvm/tools/dsymutil/RelocationMap.h
new file mode 100644
index 000000000000000..3d851acf2b89264
--- /dev/null
+++ b/llvm/tools/dsymutil/RelocationMap.h
@@ -0,0 +1,160 @@
+//===- tools/dsymutil/RelocationMap.h -------------------------- *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// This file contains the class declaration of the RelocationMap
+/// entity. RelocationMap lists all the relocations of all the
+/// atoms used in the object files linked together to
+/// produce an executable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+#define LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace dsymutil {
+
+struct SymbolMapping {
+ std::optional<yaml::Hex64> ObjectAddress;
+ yaml::Hex64 BinaryAddress;
+ yaml::Hex32 Size;
+
+ SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
+ uint32_t Size)
+ : BinaryAddress(BinaryAddress), Size(Size) {
+ if (ObjectAddr)
+ ObjectAddress = *ObjectAddr;
+ }
+
+ /// For YAML IO support
+ SymbolMapping() = default;
+};
+
+/// ValidReloc represents one relocation entry described by the RelocationMap.
+/// It contains a list of DWARF relocations to apply to a linked binary.
+class ValidReloc {
+public:
+ yaml::Hex64 Offset;
+ yaml::Hex32 Size;
+ yaml::Hex64 Addend;
+ std::string SymbolName;
+ struct SymbolMapping SymbolMapping;
+
+ struct SymbolMapping getSymbolMapping() const { return SymbolMapping; }
+
+ ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
+ StringRef SymbolName, struct SymbolMapping SymbolMapping)
+ : Offset(Offset), Size(Size), Addend(Addend), SymbolName(SymbolName),
+ SymbolMapping(SymbolMapping) {}
+
+ bool operator<(const ValidReloc &RHS) const { return Offset < RHS.Offset; }
+
+ /// For YAMLIO support.
+ ValidReloc() = default;
+};
+
+/// The RelocationMap object stores the list of relocation entries for a binary
+class RelocationMap {
+ Triple BinaryTriple;
+ std::string BinaryPath;
+ using RelocContainer = std::vector<ValidReloc>;
+
+ RelocContainer Relocations;
+
+ /// For YAML IO support.
+ ///@{
+ friend yaml::MappingTraits<std::unique_ptr<RelocationMap>>;
+ friend yaml::MappingTraits<RelocationMap>;
+
+ RelocationMap() = default;
+ ///@}
+
+public:
+ RelocationMap(const Triple &BinaryTriple, StringRef BinaryPath)
+ : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)) {}
+
+ using const_iterator = RelocContainer::const_iterator;
+
+ iterator_range<const_iterator> relocations() const {
+ return make_range(begin(), end());
+ }
+
+ const_iterator begin() const { return Relocations.begin(); }
+
+ const_iterator end() const { return Relocations.end(); }
+
+ size_t getNumberOfEntries() const { return Relocations.size(); }
+
+ /// This function adds a ValidReloc to the list owned by this
+ /// relocation map.
+ void addRelocationMapEntry(const ValidReloc &Relocation);
+
+ const Triple &getTriple() const { return BinaryTriple; }
+
+ StringRef getBinaryPath() const { return BinaryPath; }
+
+ void print(raw_ostream &OS) const;
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+ /// Read a relocation map from \a InputFile.
+ static ErrorOr<std::unique_ptr<RelocationMap>>
+ parseYAMLRelocationMap(StringRef InputFile, StringRef PrependPath);
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(dsymutil::ValidReloc)
+
+namespace llvm {
+namespace yaml {
+
+using namespace llvm::dsymutil;
+
+template <> struct MappingTraits<dsymutil::ValidReloc> {
+ static void mapping(IO &io, dsymutil::ValidReloc &VR);
+ static const bool flow = true;
+};
+
+template <> struct MappingTraits<dsymutil::RelocationMap> {
+ struct YamlRM;
+ static void mapping(IO &io, dsymutil::RelocationMap &RM);
+};
+
+template <> struct MappingTraits<std::unique_ptr<dsymutil::RelocationMap>> {
+ struct YamlRM;
+ static void mapping(IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM);
+};
+
+template <> struct ScalarTraits<Triple> {
+ static void output(const Triple &val, void *, raw_ostream &out);
+ static StringRef input(StringRef scalar, void *, Triple &value);
+ static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 104895b1a90bdaa..2dd123318e00bd0 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -398,6 +398,12 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
Options.LinkOpts.RemarksKeepAll =
!Args.hasArg(OPT_remarks_drop_without_debug);
+ if (opt::Arg *BuildVariantSuffix = Args.getLastArg(OPT_build_variant_suffix))
+ Options.LinkOpts.BuildVariantSuffix = BuildVariantSuffix->getValue();
+
+ for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
+ Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
+
if (Error E = verifyOptions(Options))
return std::move(E);
return Options;
@@ -670,15 +676,18 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
// Dump the symbol table for each input file and requested arch
if (Options.DumpStab) {
if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
- Options.LinkOpts.PrependPath))
+ Options.LinkOpts.DSYMSearchPaths,
+ Options.LinkOpts.PrependPath,
+ Options.LinkOpts.BuildVariantSuffix))
return EXIT_FAILURE;
continue;
}
- auto DebugMapPtrsOrErr =
- parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
- Options.LinkOpts.PrependPath, Options.LinkOpts.Verbose,
- Options.InputIsYAMLDebugMap);
+ auto DebugMapPtrsOrErr = parseDebugMap(
+ Options.LinkOpts.VFS, InputFile, Options.Archs,
+ Options.LinkOpts.DSYMSearchPaths, Options.LinkOpts.PrependPath,
+ Options.LinkOpts.BuildVariantSuffix, Options.LinkOpts.Verbose,
+ Options.InputIsYAMLDebugMap);
if (auto EC = DebugMapPtrsOrErr.getError()) {
WithColor::error() << "cannot parse the debug map for '" << InputFile
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index ddecd8a76c7fc96..5504dd57c7e558a 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -35,12 +35,14 @@ namespace dsymutil {
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath, bool Verbose, bool InputIsYAML);
+ ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+ StringRef VariantSuffix, bool Verbose, bool InputIsYAML);
/// Dump the symbol table.
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath = "");
+ ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath = "",
+ StringRef VariantSuffix = "");
} // end namespace dsymutil
} // end namespace llvm
diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index d97dd7392b0dfd8..02a94596ec7644d 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -132,11 +132,23 @@ class ObjFileAddressMap : public AddressMapBase {
return std::nullopt;
}
+ std::optional<StringRef> getLibraryInstallName() override {
+ return std::nullopt;
+ }
+
bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
// no need to apply relocations to the linked binary.
return false;
}
+ bool needToSaveValidRelocs() override { return false; }
+
+ void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t,
+ uint64_t) override {}
+
+ void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+ uint64_t OutputUnitOffset) override {}
+
void clear() override {}
protected:
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index e32aa8ab8f5bf50..fede89e9c1167df 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -561,37 +561,22 @@ struct DarwinStabName {
const char *Name;
};
const struct DarwinStabName DarwinStabNames[] = {
- {MachO::N_GSYM, "GSYM"},
- {MachO::N_FNAME, "FNAME"},
- {MachO::N_FUN, "FUN"},
- {MachO::N_STSYM, "STSYM"},
- {MachO::N_LCSYM, "LCSYM"},
- {MachO::N_BNSYM, "BNSYM"},
- {MachO::N_PC, "PC"},
- {MachO::N_AST, "AST"},
- {MachO::N_OPT, "OPT"},
- {MachO::N_RSYM, "RSYM"},
- {MachO::N_SLINE, "SLINE"},
- {MachO::N_ENSYM, "ENSYM"},
- {MachO::N_SSYM, "SSYM"},
- {MachO::N_SO, "SO"},
- {MachO::N_OSO, "OSO"},
- {MachO::N_LSYM, "LSYM"},
- {MachO::N_BINCL, "BINCL"},
- {MachO::N_SOL, "SOL"},
- {MachO::N_PARAMS, "PARAM"},
- {MachO::N_VERSION, "VERS"},
- {MachO::N_OLEVEL, "OLEV"},
- {MachO::N_PSYM, "PSYM"},
- {MachO::N_EINCL, "EINCL"},
- {MachO::N_ENTRY, "ENTRY"},
- {MachO::N_LBRAC, "LBRAC"},
- {MachO::N_EXCL, "EXCL"},
- {MachO::N_RBRAC, "RBRAC"},
- {MachO::N_BCOMM, "BCOMM"},
- {MachO::N_ECOMM, "ECOMM"},
- {MachO::N_ECOML, "ECOML"},
- {MachO::N_LENG, "LENG"},
+ {MachO::N_GSYM, "GSYM"}, {MachO::N_FNAME, "FNAME"},
+ {MachO::N_FUN, "FUN"}, {MachO::N_STSYM, "STSYM"},
+ {MachO::N_LCSYM, "LCSYM"}, {MachO::N_BNSYM, "BNSYM"},
+ {MachO::N_PC, "PC"}, {MachO::N_AST, "AST"},
+ {MachO::N_OPT, "OPT"}, {MachO::N_RSYM, "RSYM"},
+ {MachO::N_SLINE, "SLINE"}, {MachO::N_ENSYM, "ENSYM"},
+ {MachO::N_SSYM, "SSYM"}, {MachO::N_SO, "SO"},
+ {MachO::N_OSO, "OSO"}, {MachO::N_LIB, "LIB"},
+ {MachO::N_LSYM, "LSYM"}, {MachO::N_BINCL, "BINCL"},
+ {MachO::N_SOL, "SOL"}, {MachO::N_PARAMS, "PARAM"},
+ {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
+ {MachO::N_PSYM, "PSYM"}, {MachO::N_EINCL, "EINCL"},
+ {MachO::N_ENTRY, "ENTRY"}, {MachO::N_LBRAC, "LBRAC"},
+ {MachO::N_EXCL, "EXCL"}, {MachO::N_RBRAC, "RBRAC"},
+ {MachO::N_BCOMM, "BCOMM"}, {MachO::N_ECOMM, "ECOMM"},
+ {MachO::N_ECOML, "ECOML"}, {MachO::N_LENG, "LENG"},
};
static const char *getDarwinStabString(uint8_t NType) {
More information about the llvm-commits
mailing list