mirror of
https://github.com/intel/llvm.git
synced 2026-02-03 02:26:27 +08:00
Reland [dsymutil] Add support for mergeable libraries (#70256)
Reland https://reviews.llvm.org/D158124 Fixed `-fpermissive` error reported by gcc only.
This commit is contained in:
@@ -32,11 +32,26 @@ OPTIONS
|
|||||||
architectures will be linked by default and any architectures that can't be
|
architectures will be linked by default and any architectures that can't be
|
||||||
properly linked will cause :program:`dsymutil` to return an error.
|
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 differently. 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
|
.. option:: --dump-debug-map
|
||||||
|
|
||||||
Dump the *executable*'s debug-map (the list of the object files containing the
|
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.
|
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
|
.. option:: --fat64
|
||||||
|
|
||||||
Use a 64-bit header when emitting universal binaries.
|
Use a 64-bit header when emitting universal binaries.
|
||||||
|
|||||||
@@ -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(0x3fed, APPLE_property, 0, APPLE)
|
||||||
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
|
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
|
||||||
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
|
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
|
||||||
|
HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
|
||||||
|
|
||||||
// Attribute form encodings.
|
// Attribute form encodings.
|
||||||
HANDLE_DW_FORM(0x01, addr, 2, DWARF)
|
HANDLE_DW_FORM(0x01, addr, 2, DWARF)
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ enum StabType {
|
|||||||
N_SSYM = 0x60u,
|
N_SSYM = 0x60u,
|
||||||
N_SO = 0x64u,
|
N_SO = 0x64u,
|
||||||
N_OSO = 0x66u,
|
N_OSO = 0x66u,
|
||||||
|
N_LIB = 0x68u,
|
||||||
N_LSYM = 0x80u,
|
N_LSYM = 0x80u,
|
||||||
N_BINCL = 0x82u,
|
N_BINCL = 0x82u,
|
||||||
N_SOL = 0x84u,
|
N_SOL = 0x84u,
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ public:
|
|||||||
virtual std::optional<int64_t>
|
virtual std::optional<int64_t>
|
||||||
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
|
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
|
/// Apply the valid relocations to the buffer \p Data, taking into
|
||||||
/// account that Data is at \p BaseOffset in the .debug_info section.
|
/// account that Data is at \p BaseOffset in the .debug_info section.
|
||||||
///
|
///
|
||||||
@@ -69,6 +72,23 @@ public:
|
|||||||
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
||||||
bool IsLittleEndian) = 0;
|
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.
|
/// Erases all data.
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
};
|
};
|
||||||
@@ -751,6 +771,9 @@ private:
|
|||||||
/// Is there a DW_AT_str_offsets_base in the CU?
|
/// Is there a DW_AT_str_offsets_base in the CU?
|
||||||
bool AttrStrOffsetBaseSeen = false;
|
bool AttrStrOffsetBaseSeen = false;
|
||||||
|
|
||||||
|
/// Is there a DW_AT_APPLE_origin in the CU?
|
||||||
|
bool HasAppleOrigin = false;
|
||||||
|
|
||||||
AttributesInfo() = default;
|
AttributesInfo() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ public:
|
|||||||
virtual std::optional<int64_t>
|
virtual std::optional<int64_t>
|
||||||
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
|
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
|
/// Apply the valid relocations to the buffer \p Data, taking into
|
||||||
/// account that Data is at \p BaseOffset in the .debug_info section.
|
/// account that Data is at \p BaseOffset in the .debug_info section.
|
||||||
///
|
///
|
||||||
@@ -62,6 +65,21 @@ public:
|
|||||||
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
||||||
bool IsLittleEndian) = 0;
|
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.
|
/// Erases all data.
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -418,9 +418,6 @@ public:
|
|||||||
/// Get the architecture (first) component of the triple.
|
/// Get the architecture (first) component of the triple.
|
||||||
StringRef getArchName() const;
|
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.
|
/// Get the vendor (second) component of the triple.
|
||||||
StringRef getVendorName() const;
|
StringRef getVendorName() const;
|
||||||
|
|
||||||
@@ -1118,6 +1115,9 @@ public:
|
|||||||
/// Get the canonical name for the \p Kind architecture.
|
/// Get the canonical name for the \p Kind architecture.
|
||||||
static StringRef getArchTypeName(ArchType Kind);
|
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
|
/// Get the "prefix" canonical name for the \p Kind architecture. This is the
|
||||||
/// prefix used by the architecture specific builtins, and is suitable for
|
/// prefix used by the architecture specific builtins, and is suitable for
|
||||||
/// passing to \see Intrinsic::getIntrinsicForClangBuiltin().
|
/// passing to \see Intrinsic::getIntrinsicForClangBuiltin().
|
||||||
|
|||||||
@@ -1026,6 +1026,15 @@ unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
|
|||||||
StringEntry = DebugLineStrPool.getEntry(*String);
|
StringEntry = DebugLineStrPool.getEntry(*String);
|
||||||
} else {
|
} else {
|
||||||
StringEntry = DebugStrPool.getEntry(*String);
|
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.
|
// Update attributes info.
|
||||||
if (AttrSpec.Attr == dwarf::DW_AT_name)
|
if (AttrSpec.Attr == dwarf::DW_AT_name)
|
||||||
Info.Name = StringEntry;
|
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,
|
DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
|
||||||
const DWARFFile &File, CompileUnit &Unit,
|
const DWARFFile &File, CompileUnit &Unit,
|
||||||
int64_t PCOffset, uint32_t OutOffset,
|
int64_t PCOffset, uint32_t OutOffset,
|
||||||
@@ -1720,6 +1735,9 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
|
|||||||
Flags |= TF_SkipPC;
|
Flags |= TF_SkipPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<StringRef> LibraryInstallName =
|
||||||
|
ObjFile.Addresses->getLibraryInstallName();
|
||||||
|
SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
|
||||||
for (const auto &AttrSpec : Abbrev->attributes()) {
|
for (const auto &AttrSpec : Abbrev->attributes()) {
|
||||||
if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) {
|
if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) {
|
||||||
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
|
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
|
||||||
@@ -1727,17 +1745,41 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttributeLinkedOffsetFixup CurAttrFixup;
|
||||||
|
CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;
|
||||||
|
CurAttrFixup.LinkedOffsetFixupVal =
|
||||||
|
Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
|
||||||
|
|
||||||
DWARFFormValue Val = AttrSpec.getFormValue();
|
DWARFFormValue Val = AttrSpec.getFormValue();
|
||||||
uint64_t AttrSize = Offset;
|
uint64_t AttrSize = Offset;
|
||||||
Val.extractValue(Data, &Offset, U.getFormParams(), &U);
|
Val.extractValue(Data, &Offset, U.getFormParams(), &U);
|
||||||
|
CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;
|
||||||
AttrSize = Offset - AttrSize;
|
AttrSize = Offset - AttrSize;
|
||||||
|
|
||||||
OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec,
|
uint64_t FinalAttrSize =
|
||||||
AttrSize, AttrInfo, IsLittleEndian);
|
cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
|
||||||
|
AttrInfo, IsLittleEndian);
|
||||||
|
if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
|
||||||
|
AttributesFixups.push_back(CurAttrFixup);
|
||||||
|
|
||||||
|
OutOffset += FinalAttrSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
// Look for accelerator entries.
|
||||||
uint16_t Tag = InputDIE.getTag();
|
|
||||||
// FIXME: This is slightly wrong. An inline_subroutine without a
|
// FIXME: This is slightly wrong. An inline_subroutine without a
|
||||||
// low_pc, but with AT_ranges might be interesting to get into the
|
// low_pc, but with AT_ranges might be interesting to get into the
|
||||||
// accelerator tables too. For now stick with dsymutil's behavior.
|
// accelerator tables too. For now stick with dsymutil's behavior.
|
||||||
@@ -1806,8 +1848,19 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
|
|||||||
Linker.assignAbbrev(NewAbbrev);
|
Linker.assignAbbrev(NewAbbrev);
|
||||||
Die->setAbbrevNumber(NewAbbrev.getNumber());
|
Die->setAbbrevNumber(NewAbbrev.getNumber());
|
||||||
|
|
||||||
|
uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber());
|
||||||
|
|
||||||
// Add the size of the abbreviation number to the output offset.
|
// 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) {
|
if (!HasChildren) {
|
||||||
// Update our size.
|
// Update our size.
|
||||||
|
|||||||
@@ -90,6 +90,36 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
|
|||||||
llvm_unreachable("Invalid ArchType!");
|
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) {
|
StringRef Triple::getArchTypePrefix(ArchType Kind) {
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
default:
|
default:
|
||||||
@@ -1143,34 +1173,6 @@ StringRef Triple::getArchName() const {
|
|||||||
return StringRef(Data).split('-').first; // Isolate first component
|
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 Triple::getVendorName() const {
|
||||||
StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
|
StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
|
||||||
return Tmp.split('-').first; // Isolate second component
|
return Tmp.split('-').first; // Isolate second component
|
||||||
|
|||||||
@@ -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>
|
||||||
Binary file not shown.
@@ -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 }
|
||||||
|
...
|
||||||
@@ -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>
|
||||||
Binary file not shown.
@@ -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 }
|
||||||
|
...
|
||||||
BIN
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
Normal file
BIN
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
Normal file
Binary file not shown.
BIN
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
Normal file
BIN
llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
Normal file
Binary file not shown.
@@ -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>
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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 }
|
||||||
|
...
|
||||||
@@ -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>
|
||||||
Binary file not shown.
@@ -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 }
|
||||||
|
...
|
||||||
@@ -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>
|
||||||
Binary file not shown.
@@ -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 }
|
||||||
|
...
|
||||||
Binary file not shown.
BIN
llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
Normal file
BIN
llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
Normal file
Binary file not shown.
@@ -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-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-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 %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.
|
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: Keeping subprogram DIE:
|
||||||
CHECK-ARCHIVE-NEXT: DW_TAG_subprogram
|
CHECK-ARCHIVE-NEXT: DW_TAG_subprogram
|
||||||
CHECK-ARCHIVE-NEXT: DW_AT_name {{.*}}"inc")
|
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
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ HELP-NOT: -reverse-iterate
|
|||||||
HELP: Dsymutil Options:
|
HELP: Dsymutil Options:
|
||||||
CHECK: -accelerator
|
CHECK: -accelerator
|
||||||
CHECK: -arch <arch>
|
CHECK: -arch <arch>
|
||||||
|
CHECK: -build-variant-suffix <suffix=buildvariant>
|
||||||
CHECK: -dump-debug-map
|
CHECK: -dump-debug-map
|
||||||
|
CHECK: -D <path>
|
||||||
CHECK: -fat64
|
CHECK: -fat64
|
||||||
CHECK: -flat
|
CHECK: -flat
|
||||||
CHECK: -gen-reproducer
|
CHECK: -gen-reproducer
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ add_llvm_tool(dsymutil
|
|||||||
MachODebugMapParser.cpp
|
MachODebugMapParser.cpp
|
||||||
MachOUtils.cpp
|
MachOUtils.cpp
|
||||||
Reproducer.cpp
|
Reproducer.cpp
|
||||||
|
RelocationMap.cpp
|
||||||
SymbolMap.cpp
|
SymbolMap.cpp
|
||||||
|
|
||||||
DEPENDS
|
DEPENDS
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ DebugMapObject::DebugMapObject(StringRef ObjectFilename,
|
|||||||
bool DebugMapObject::addSymbol(StringRef Name,
|
bool DebugMapObject::addSymbol(StringRef Name,
|
||||||
std::optional<uint64_t> ObjectAddress,
|
std::optional<uint64_t> ObjectAddress,
|
||||||
uint64_t LinkedAddress, uint32_t Size) {
|
uint64_t LinkedAddress, uint32_t Size) {
|
||||||
|
if (Symbols.count(Name)) {
|
||||||
|
// Symbol was previously added.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto InsertResult = Symbols.insert(
|
auto InsertResult = Symbols.insert(
|
||||||
std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
|
std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
|
||||||
|
|
||||||
@@ -53,6 +58,12 @@ bool DebugMapObject::addSymbol(StringRef Name,
|
|||||||
return InsertResult.second;
|
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 {
|
void DebugMapObject::print(raw_ostream &OS) const {
|
||||||
OS << getObjectFilename() << ":\n";
|
OS << getObjectFilename() << ":\n";
|
||||||
// Sort the symbols in alphabetical order, like llvm-nm (and to get
|
// 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;
|
std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
|
void MappingTraits<std::pair<std::string, SymbolMapping>>::mapping(
|
||||||
mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
|
IO &io, std::pair<std::string, SymbolMapping> &s) {
|
||||||
io.mapRequired("sym", s.first);
|
io.mapRequired("sym", s.first);
|
||||||
io.mapOptional("objAddr", s.second.ObjectAddress);
|
io.mapOptional("objAddr", s.second.ObjectAddress);
|
||||||
io.mapRequired("binAddr", s.second.BinaryAddress);
|
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) {
|
for (auto &Entry : Entries) {
|
||||||
auto &Mapping = Entry.second;
|
auto &Mapping = Entry.second;
|
||||||
std::optional<uint64_t> ObjAddress;
|
std::optional<uint64_t> ObjAddress;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
||||||
#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
||||||
|
|
||||||
|
#include "RelocationMap.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
@@ -134,22 +135,6 @@ public:
|
|||||||
/// linked binary for all the linked atoms in this object file.
|
/// linked binary for all the linked atoms in this object file.
|
||||||
class DebugMapObject {
|
class DebugMapObject {
|
||||||
public:
|
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 YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
|
||||||
using DebugMapEntry = StringMapEntry<SymbolMapping>;
|
using DebugMapEntry = StringMapEntry<SymbolMapping>;
|
||||||
|
|
||||||
@@ -182,6 +167,16 @@ public:
|
|||||||
}
|
}
|
||||||
const std::vector<std::string> &getWarnings() const { return Warnings; }
|
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;
|
void print(raw_ostream &OS) const;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void dump() const;
|
void dump() const;
|
||||||
@@ -196,10 +191,13 @@ private:
|
|||||||
|
|
||||||
std::string Filename;
|
std::string Filename;
|
||||||
sys::TimePoint<std::chrono::seconds> Timestamp;
|
sys::TimePoint<std::chrono::seconds> Timestamp;
|
||||||
StringMap<SymbolMapping> Symbols;
|
StringMap<struct SymbolMapping> Symbols;
|
||||||
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
|
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
|
||||||
uint8_t Type;
|
uint8_t Type;
|
||||||
|
|
||||||
|
std::optional<RelocationMap> RelocMap;
|
||||||
|
std::optional<std::string> InstallName;
|
||||||
|
|
||||||
std::vector<std::string> Warnings;
|
std::vector<std::string> Warnings;
|
||||||
|
|
||||||
/// For YAMLIO support.
|
/// For YAMLIO support.
|
||||||
@@ -225,10 +223,8 @@ namespace yaml {
|
|||||||
|
|
||||||
using namespace llvm::dsymutil;
|
using namespace llvm::dsymutil;
|
||||||
|
|
||||||
template <>
|
template <> struct MappingTraits<std::pair<std::string, SymbolMapping>> {
|
||||||
struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
|
static void mapping(IO &io, std::pair<std::string, SymbolMapping> &s);
|
||||||
static void mapping(IO &io,
|
|
||||||
std::pair<std::string, DebugMapObject::SymbolMapping> &s);
|
|
||||||
static const bool flow = true;
|
static const bool flow = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,12 +233,6 @@ template <> struct MappingTraits<dsymutil::DebugMapObject> {
|
|||||||
static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
|
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 <>
|
template <>
|
||||||
struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
|
struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
|
||||||
static size_t
|
static size_t
|
||||||
|
|||||||
@@ -189,6 +189,44 @@ static Error remarksErrorHandler(const DebugMapObject &DMO,
|
|||||||
|
|
||||||
return createFileError(FE->getFileName(), std::move(NewE));
|
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,
|
static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
|
||||||
StringRef ArchName, const remarks::RemarkLinker &RL) {
|
StringRef ArchName, const remarks::RemarkLinker &RL) {
|
||||||
@@ -229,30 +267,31 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutDWARFFile, typename AddressesMap>
|
template <typename OutDWARFFile, typename AddressesMap>
|
||||||
ErrorOr<std::unique_ptr<OutDWARFFile>>
|
ErrorOr<std::unique_ptr<OutDWARFFile>> DwarfLinkerForBinary::loadObject(
|
||||||
DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
|
const DebugMapObject &Obj, const DebugMap &DebugMap,
|
||||||
const DebugMap &DebugMap,
|
remarks::RemarkLinker &RL,
|
||||||
remarks::RemarkLinker &RL) {
|
std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {
|
||||||
auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
|
auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
|
||||||
std::unique_ptr<OutDWARFFile> Res;
|
std::unique_ptr<OutDWARFFile> Res;
|
||||||
|
|
||||||
if (ErrorOrObj) {
|
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>(
|
Res = std::make_unique<OutDWARFFile>(
|
||||||
Obj.getObjectFilename(),
|
Obj.getObjectFilename(), std::move(Context),
|
||||||
DWARFContext::create(
|
std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj, DLBRM),
|
||||||
*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),
|
|
||||||
[&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
|
[&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
|
||||||
|
|
||||||
Error E = RL.link(*ErrorOrObj);
|
Error E = RL.link(*ErrorOrObj);
|
||||||
@@ -614,7 +653,7 @@ template <typename Linker, typename OutDwarfFile, typename AddressMap>
|
|||||||
bool DwarfLinkerForBinary::linkImpl(
|
bool DwarfLinkerForBinary::linkImpl(
|
||||||
const DebugMap &Map, typename Linker::OutputFileType ObjectType) {
|
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());
|
DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
|
||||||
|
|
||||||
@@ -668,10 +707,12 @@ bool DwarfLinkerForBinary::linkImpl(
|
|||||||
auto &Obj = DebugMap.addDebugMapObject(
|
auto &Obj = DebugMap.addDebugMapObject(
|
||||||
Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
|
Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
|
||||||
|
|
||||||
|
auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
|
||||||
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
|
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
|
||||||
loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL)) {
|
loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL,
|
||||||
ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
|
DLBRelocMap)) {
|
||||||
return *ObjectsForLinking.back();
|
ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
|
||||||
|
return *ObjectsForLinking.back().Object;
|
||||||
} else {
|
} else {
|
||||||
// Try and emit more helpful warnings by applying some heuristics.
|
// Try and emit more helpful warnings by applying some heuristics.
|
||||||
StringRef ObjFile = ContainerName;
|
StringRef ObjFile = ContainerName;
|
||||||
@@ -782,15 +823,18 @@ bool DwarfLinkerForBinary::linkImpl(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
|
||||||
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
|
if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
|
||||||
loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL)) {
|
loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL, DLBRelocMap)) {
|
||||||
ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
|
ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
|
||||||
GeneralLinker->addObjectFile(*ObjectsForLinking.back(), Loader,
|
GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,
|
||||||
OnCUDieLoaded);
|
OnCUDieLoaded);
|
||||||
} else {
|
} else {
|
||||||
ObjectsForLinking.push_back(std::make_unique<OutDwarfFile>(
|
ObjectsForLinking.push_back(
|
||||||
Obj->getObjectFilename(), nullptr, nullptr));
|
{std::make_unique<OutDwarfFile>(Obj->getObjectFilename(), nullptr,
|
||||||
GeneralLinker->addObjectFile(*ObjectsForLinking.back());
|
nullptr),
|
||||||
|
DLBRelocMap});
|
||||||
|
GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,6 +859,10 @@ bool DwarfLinkerForBinary::linkImpl(
|
|||||||
if (Options.NoOutput)
|
if (Options.NoOutput)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (Error E =
|
||||||
|
emitRelocations<OutDwarfFile, AddressMap>(Map, ObjectsForLinking))
|
||||||
|
return error(toString(std::move(E)));
|
||||||
|
|
||||||
if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
|
if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
|
||||||
StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
|
StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
|
||||||
if (auto E = copySwiftInterfaces(ArchName))
|
if (auto E = copySwiftInterfaces(ArchName))
|
||||||
@@ -903,12 +951,14 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
|
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)) {
|
} else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
|
||||||
// Do not store the addend. The addend was the address of the symbol in
|
// 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
|
// the object file, the address in the binary that is stored in the debug
|
||||||
// map doesn't need to be offset.
|
// 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>
|
template <typename AddressesMapBase>
|
||||||
std::vector<
|
std::vector<ValidReloc>
|
||||||
typename DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
|
|
||||||
DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
|
DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
|
||||||
const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
|
const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
|
||||||
std::vector<
|
std::vector<ValidReloc> Res;
|
||||||
DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
|
|
||||||
Res;
|
|
||||||
|
|
||||||
auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
|
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 &&
|
while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
|
||||||
CurReloc->Offset < EndPos) {
|
(uint64_t)CurReloc->Offset < EndPos) {
|
||||||
Res.push_back(*CurReloc);
|
Res.push_back(*CurReloc);
|
||||||
CurReloc++;
|
CurReloc++;
|
||||||
}
|
}
|
||||||
@@ -990,12 +1037,12 @@ DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
|
|||||||
template <typename AddressesMapBase>
|
template <typename AddressesMapBase>
|
||||||
void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
|
void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
|
||||||
const ValidReloc &Reloc) {
|
const ValidReloc &Reloc) {
|
||||||
const auto &Mapping = Reloc.Mapping->getValue();
|
const auto &Mapping = Reloc.SymbolMapping;
|
||||||
const uint64_t ObjectAddress = Mapping.ObjectAddress
|
const uint64_t ObjectAddress = Mapping.ObjectAddress
|
||||||
? uint64_t(*Mapping.ObjectAddress)
|
? uint64_t(*Mapping.ObjectAddress)
|
||||||
: std::numeric_limits<uint64_t>::max();
|
: 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,
|
<< format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
|
||||||
uint64_t(Mapping.BinaryAddress));
|
uint64_t(Mapping.BinaryAddress));
|
||||||
}
|
}
|
||||||
@@ -1004,8 +1051,8 @@ template <typename AddressesMapBase>
|
|||||||
int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
|
int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
|
||||||
const ValidReloc &Reloc) {
|
const ValidReloc &Reloc) {
|
||||||
int64_t AddrAdjust = relocate(Reloc);
|
int64_t AddrAdjust = relocate(Reloc);
|
||||||
if (Reloc.Mapping->getValue().ObjectAddress)
|
if (Reloc.SymbolMapping.ObjectAddress)
|
||||||
AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
|
AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);
|
||||||
return AddrAdjust;
|
return AddrAdjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,11 +1164,39 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AddressesMapBase>
|
template <typename AddressesMapBase>
|
||||||
uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
|
std::optional<StringRef> DwarfLinkerForBinary::AddressManager<
|
||||||
const ValidReloc &Reloc) const {
|
AddressesMapBase>::getLibraryInstallName() {
|
||||||
return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
|
return LibInstallName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename AddressesMapBase>
|
||||||
|
uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
|
||||||
|
const ValidReloc &Reloc) const {
|
||||||
|
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
|
/// Apply the valid relocations found by findValidRelocs() to
|
||||||
/// the buffer \p Data, taking into account that Data is at \p BaseOffset
|
/// the buffer \p Data, taking into account that Data is at \p BaseOffset
|
||||||
/// in the debug_info section.
|
/// in the debug_info section.
|
||||||
@@ -1133,6 +1208,7 @@ uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
|
|||||||
template <typename AddressesMapBase>
|
template <typename AddressesMapBase>
|
||||||
bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
|
bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
|
||||||
MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
|
MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
|
||||||
|
|
||||||
std::vector<ValidReloc> Relocs = getRelocations(
|
std::vector<ValidReloc> Relocs = getRelocations(
|
||||||
ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
|
ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
|
||||||
|
|
||||||
@@ -1148,9 +1224,47 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
|
|||||||
assert(CurReloc.Size <= sizeof(Buf));
|
assert(CurReloc.Size <= sizeof(Buf));
|
||||||
memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
|
memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Relocs.size() > 0;
|
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 dsymutil
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "DebugMap.h"
|
#include "DebugMap.h"
|
||||||
#include "LinkUtils.h"
|
#include "LinkUtils.h"
|
||||||
#include "MachOUtils.h"
|
#include "MachOUtils.h"
|
||||||
|
#include "RelocationMap.h"
|
||||||
#include "llvm/DWARFLinker/DWARFLinker.h"
|
#include "llvm/DWARFLinker/DWARFLinker.h"
|
||||||
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
|
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
|
||||||
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
|
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
|
||||||
@@ -21,10 +22,48 @@
|
|||||||
#include "llvm/Remarks/RemarkFormat.h"
|
#include "llvm/Remarks/RemarkFormat.h"
|
||||||
#include "llvm/Remarks/RemarkLinker.h"
|
#include "llvm/Remarks/RemarkLinker.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace dsymutil {
|
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 core of the Dsymutil Dwarf linking logic.
|
||||||
///
|
///
|
||||||
/// The link of the dwarf information from the object files will be
|
/// The link of the dwarf information from the object files will be
|
||||||
@@ -67,26 +106,11 @@ private:
|
|||||||
/// Keeps track of relocations.
|
/// Keeps track of relocations.
|
||||||
template <typename AddressesMapBase>
|
template <typename AddressesMapBase>
|
||||||
class AddressManager : public 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;
|
const DwarfLinkerForBinary &Linker;
|
||||||
|
|
||||||
/// The valid relocations for the current DebugMapObject.
|
/// 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> ValidDebugInfoRelocs;
|
||||||
std::vector<ValidReloc> ValidDebugAddrRelocs;
|
std::vector<ValidReloc> ValidDebugAddrRelocs;
|
||||||
@@ -94,6 +118,12 @@ private:
|
|||||||
|
|
||||||
StringRef SrcFileName;
|
StringRef SrcFileName;
|
||||||
|
|
||||||
|
uint8_t DebugMapObjectType;
|
||||||
|
|
||||||
|
std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;
|
||||||
|
|
||||||
|
std::optional<std::string> LibInstallName;
|
||||||
|
|
||||||
/// Returns list of valid relocations from \p Relocs,
|
/// Returns list of valid relocations from \p Relocs,
|
||||||
/// between \p StartOffset and \p NextOffset.
|
/// between \p StartOffset and \p NextOffset.
|
||||||
///
|
///
|
||||||
@@ -115,9 +145,29 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
|
AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
|
||||||
const DebugMapObject &DMO)
|
const DebugMapObject &DMO,
|
||||||
: Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
|
std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)
|
||||||
findValidRelocsInDebugSections(Obj, DMO);
|
: 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(); }
|
~AddressManager() override { clear(); }
|
||||||
|
|
||||||
@@ -158,9 +208,20 @@ private:
|
|||||||
std::optional<int64_t>
|
std::optional<int64_t>
|
||||||
getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
|
getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
|
||||||
|
|
||||||
|
std::optional<StringRef> getLibraryInstallName() override;
|
||||||
|
|
||||||
bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
|
||||||
bool IsLittleEndian) override;
|
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 {
|
void clear() override {
|
||||||
ValidDebugInfoRelocs.clear();
|
ValidDebugInfoRelocs.clear();
|
||||||
ValidDebugAddrRelocs.clear();
|
ValidDebugAddrRelocs.clear();
|
||||||
@@ -180,11 +241,11 @@ private:
|
|||||||
/// Attempt to load a debug object from disk.
|
/// Attempt to load a debug object from disk.
|
||||||
ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
|
ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
|
||||||
const Triple &triple);
|
const Triple &triple);
|
||||||
|
|
||||||
template <typename OutDWARFFile, typename AddressesMap>
|
template <typename OutDWARFFile, typename AddressesMap>
|
||||||
ErrorOr<std::unique_ptr<OutDWARFFile>> loadObject(const DebugMapObject &Obj,
|
ErrorOr<std::unique_ptr<OutDWARFFile>>
|
||||||
const DebugMap &DebugMap,
|
loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
|
||||||
remarks::RemarkLinker &RL);
|
remarks::RemarkLinker &RL,
|
||||||
|
std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
|
||||||
|
|
||||||
void collectRelocationsToApplyToSwiftReflectionSections(
|
void collectRelocationsToApplyToSwiftReflectionSections(
|
||||||
const object::SectionRef &Section, StringRef &Contents,
|
const object::SectionRef &Section, StringRef &Contents,
|
||||||
@@ -207,6 +268,11 @@ private:
|
|||||||
bool linkImpl(const DebugMap &Map,
|
bool linkImpl(const DebugMap &Map,
|
||||||
typename Linker::OutputFileType ObjectType);
|
typename Linker::OutputFileType ObjectType);
|
||||||
|
|
||||||
|
template <typename OutDwarfFile, typename AddressMap>
|
||||||
|
Error emitRelocations(
|
||||||
|
const DebugMap &DM,
|
||||||
|
std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking);
|
||||||
|
|
||||||
raw_fd_ostream &OutFile;
|
raw_fd_ostream &OutFile;
|
||||||
BinaryHolder &BinHolder;
|
BinaryHolder &BinHolder;
|
||||||
LinkOptions Options;
|
LinkOptions Options;
|
||||||
|
|||||||
@@ -93,6 +93,12 @@ struct LinkOptions {
|
|||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
||||||
vfs::getRealFileSystem();
|
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.
|
/// Fields used for linking and placing remarks into the .dSYM bundle.
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "BinaryHolder.h"
|
#include "BinaryHolder.h"
|
||||||
#include "DebugMap.h"
|
#include "DebugMap.h"
|
||||||
#include "MachOUtils.h"
|
#include "MachOUtils.h"
|
||||||
|
#include "RelocationMap.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallSet.h"
|
||||||
#include "llvm/Object/MachO.h"
|
#include "llvm/Object/MachO.h"
|
||||||
@@ -28,9 +29,13 @@ class MachODebugMapParser {
|
|||||||
public:
|
public:
|
||||||
MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
||||||
StringRef BinaryPath, ArrayRef<std::string> Archs,
|
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()),
|
: 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) {}
|
CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
|
||||||
|
|
||||||
/// Parses and returns the DebugMaps of the input binary. The binary contains
|
/// Parses and returns the DebugMaps of the input binary. The binary contains
|
||||||
@@ -47,7 +52,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string BinaryPath;
|
std::string BinaryPath;
|
||||||
SmallVector<StringRef, 1> Archs;
|
SmallVector<StringRef, 1> Archs;
|
||||||
|
SmallVector<StringRef, 1> DSYMSearchPaths;
|
||||||
std::string PathPrefix;
|
std::string PathPrefix;
|
||||||
|
std::string VariantSuffix;
|
||||||
|
|
||||||
/// Owns the MemoryBuffer for the main binary.
|
/// Owns the MemoryBuffer for the main binary.
|
||||||
BinaryHolder BinHolder;
|
BinaryHolder BinHolder;
|
||||||
@@ -87,6 +94,9 @@ private:
|
|||||||
void
|
void
|
||||||
switchToNewDebugMapObject(StringRef Filename,
|
switchToNewDebugMapObject(StringRef Filename,
|
||||||
sys::TimePoint<std::chrono::seconds> Timestamp);
|
sys::TimePoint<std::chrono::seconds> Timestamp);
|
||||||
|
void
|
||||||
|
switchToNewLibDebugMapObject(StringRef Filename,
|
||||||
|
sys::TimePoint<std::chrono::seconds> Timestamp);
|
||||||
void resetParserState();
|
void resetParserState();
|
||||||
uint64_t getMainBinarySymbolAddress(StringRef Name);
|
uint64_t getMainBinarySymbolAddress(StringRef Name);
|
||||||
std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
|
std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
|
||||||
@@ -176,8 +186,6 @@ void MachODebugMapParser::addCommonSymbols() {
|
|||||||
/// everything up to add symbols to the new one.
|
/// everything up to add symbols to the new one.
|
||||||
void MachODebugMapParser::switchToNewDebugMapObject(
|
void MachODebugMapParser::switchToNewDebugMapObject(
|
||||||
StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
|
StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
|
||||||
addCommonSymbols();
|
|
||||||
resetParserState();
|
|
||||||
|
|
||||||
SmallString<80> Path(PathPrefix);
|
SmallString<80> Path(PathPrefix);
|
||||||
sys::path::append(Path, Filename);
|
sys::path::append(Path, Filename);
|
||||||
@@ -198,11 +206,138 @@ void MachODebugMapParser::switchToNewDebugMapObject(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCommonSymbols();
|
||||||
|
resetParserState();
|
||||||
|
|
||||||
CurrentDebugMapObject =
|
CurrentDebugMapObject =
|
||||||
&Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
|
&Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
|
||||||
|
|
||||||
loadCurrentObjectFileSymbols(*Object);
|
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) {
|
static std::string getArchName(const object::MachOObjectFile &Obj) {
|
||||||
Triple T = Obj.getArchTriple();
|
Triple T = Obj.getArchTriple();
|
||||||
return std::string(T.getArchName());
|
return std::string(T.getArchName());
|
||||||
@@ -275,23 +410,39 @@ struct DarwinStabName {
|
|||||||
const char *Name;
|
const char *Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct DarwinStabName DarwinStabNames[] = {
|
const struct DarwinStabName DarwinStabNames[] = {{MachO::N_GSYM, "N_GSYM"},
|
||||||
{MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
|
{MachO::N_FNAME, "N_FNAME"},
|
||||||
{MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
|
{MachO::N_FUN, "N_FUN"},
|
||||||
{MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
|
{MachO::N_STSYM, "N_STSYM"},
|
||||||
{MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
|
{MachO::N_LCSYM, "N_LCSYM"},
|
||||||
{MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
|
{MachO::N_BNSYM, "N_BNSYM"},
|
||||||
{MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
|
{MachO::N_PC, "N_PC"},
|
||||||
{MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
|
{MachO::N_AST, "N_AST"},
|
||||||
{MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
|
{MachO::N_OPT, "N_OPT"},
|
||||||
{MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
|
{MachO::N_RSYM, "N_RSYM"},
|
||||||
{MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
|
{MachO::N_SLINE, "N_SLINE"},
|
||||||
{MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
|
{MachO::N_ENSYM, "N_ENSYM"},
|
||||||
{MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
|
{MachO::N_SSYM, "N_SSYM"},
|
||||||
{MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
|
{MachO::N_SO, "N_SO"},
|
||||||
{MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
|
{MachO::N_OSO, "N_OSO"},
|
||||||
{MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
|
{MachO::N_LIB, "N_LIB"},
|
||||||
{MachO::N_LENG, "N_LENG"}, {0, nullptr}};
|
{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) {
|
static const char *getDarwinStabString(uint8_t NType) {
|
||||||
for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
|
for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
|
||||||
@@ -477,13 +628,25 @@ void MachODebugMapParser::handleStabSymbolTableEntry(
|
|||||||
|
|
||||||
const char *Name = &MainBinaryStrings.data()[StringIndex];
|
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.
|
// 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 (Type == MachO::N_OSO) {
|
||||||
if (Duplicates.count(OSO(Name, Value))) {
|
if (!CurrentDebugMapObject ||
|
||||||
SkipDebugMapObject = true;
|
CurrentDebugMapObject->getType() != MachO::N_LIB) {
|
||||||
return;
|
if (Duplicates.count(OSO(Name, Value))) {
|
||||||
|
SkipDebugMapObject = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
|
||||||
}
|
}
|
||||||
return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SkipDebugMapObject)
|
if (SkipDebugMapObject)
|
||||||
@@ -694,18 +857,23 @@ namespace dsymutil {
|
|||||||
llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||||
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
||||||
StringRef InputFile, ArrayRef<std::string> Archs,
|
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)
|
if (InputIsYAML)
|
||||||
return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
|
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();
|
return Parser.parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
||||||
StringRef InputFile, ArrayRef<std::string> Archs,
|
StringRef InputFile, ArrayRef<std::string> Archs,
|
||||||
StringRef PrependPath) {
|
ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
|
||||||
MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
|
StringRef VariantSuffix) {
|
||||||
|
MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
|
||||||
|
PrependPath, VariantSuffix, false);
|
||||||
return Parser.dumpStab();
|
return Parser.dumpStab();
|
||||||
}
|
}
|
||||||
} // namespace dsymutil
|
} // namespace dsymutil
|
||||||
|
|||||||
@@ -201,3 +201,14 @@ def linker: Separate<["--", "-"], "linker">,
|
|||||||
HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">,
|
HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">,
|
||||||
Group<grp_general>;
|
Group<grp_general>;
|
||||||
def: Joined<["--", "-"], "linker=">, Alias<linker>;
|
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>;
|
||||||
|
|||||||
92
llvm/tools/dsymutil/RelocationMap.cpp
Normal file
92
llvm/tools/dsymutil/RelocationMap.cpp
Normal file
@@ -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
|
||||||
160
llvm/tools/dsymutil/RelocationMap.h
Normal file
160
llvm/tools/dsymutil/RelocationMap.h
Normal file
@@ -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
|
||||||
@@ -398,6 +398,12 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
|
|||||||
Options.LinkOpts.RemarksKeepAll =
|
Options.LinkOpts.RemarksKeepAll =
|
||||||
!Args.hasArg(OPT_remarks_drop_without_debug);
|
!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))
|
if (Error E = verifyOptions(Options))
|
||||||
return std::move(E);
|
return std::move(E);
|
||||||
return Options;
|
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
|
// Dump the symbol table for each input file and requested arch
|
||||||
if (Options.DumpStab) {
|
if (Options.DumpStab) {
|
||||||
if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
|
if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
|
||||||
Options.LinkOpts.PrependPath))
|
Options.LinkOpts.DSYMSearchPaths,
|
||||||
|
Options.LinkOpts.PrependPath,
|
||||||
|
Options.LinkOpts.BuildVariantSuffix))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DebugMapPtrsOrErr =
|
auto DebugMapPtrsOrErr = parseDebugMap(
|
||||||
parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
|
Options.LinkOpts.VFS, InputFile, Options.Archs,
|
||||||
Options.LinkOpts.PrependPath, Options.LinkOpts.Verbose,
|
Options.LinkOpts.DSYMSearchPaths, Options.LinkOpts.PrependPath,
|
||||||
Options.InputIsYAMLDebugMap);
|
Options.LinkOpts.BuildVariantSuffix, Options.LinkOpts.Verbose,
|
||||||
|
Options.InputIsYAMLDebugMap);
|
||||||
|
|
||||||
if (auto EC = DebugMapPtrsOrErr.getError()) {
|
if (auto EC = DebugMapPtrsOrErr.getError()) {
|
||||||
WithColor::error() << "cannot parse the debug map for '" << InputFile
|
WithColor::error() << "cannot parse the debug map for '" << InputFile
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ namespace dsymutil {
|
|||||||
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||||
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
||||||
StringRef InputFile, ArrayRef<std::string> Archs,
|
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.
|
/// Dump the symbol table.
|
||||||
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
|
||||||
StringRef InputFile, ArrayRef<std::string> Archs,
|
StringRef InputFile, ArrayRef<std::string> Archs,
|
||||||
StringRef PrependPath = "");
|
ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath = "",
|
||||||
|
StringRef VariantSuffix = "");
|
||||||
|
|
||||||
} // end namespace dsymutil
|
} // end namespace dsymutil
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|||||||
@@ -132,11 +132,23 @@ public:
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<StringRef> getLibraryInstallName() override {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
|
bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
|
||||||
// no need to apply relocations to the linked binary.
|
// no need to apply relocations to the linked binary.
|
||||||
return false;
|
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 {}
|
void clear() override {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -561,37 +561,22 @@ struct DarwinStabName {
|
|||||||
const char *Name;
|
const char *Name;
|
||||||
};
|
};
|
||||||
const struct DarwinStabName DarwinStabNames[] = {
|
const struct DarwinStabName DarwinStabNames[] = {
|
||||||
{MachO::N_GSYM, "GSYM"},
|
{MachO::N_GSYM, "GSYM"}, {MachO::N_FNAME, "FNAME"},
|
||||||
{MachO::N_FNAME, "FNAME"},
|
{MachO::N_FUN, "FUN"}, {MachO::N_STSYM, "STSYM"},
|
||||||
{MachO::N_FUN, "FUN"},
|
{MachO::N_LCSYM, "LCSYM"}, {MachO::N_BNSYM, "BNSYM"},
|
||||||
{MachO::N_STSYM, "STSYM"},
|
{MachO::N_PC, "PC"}, {MachO::N_AST, "AST"},
|
||||||
{MachO::N_LCSYM, "LCSYM"},
|
{MachO::N_OPT, "OPT"}, {MachO::N_RSYM, "RSYM"},
|
||||||
{MachO::N_BNSYM, "BNSYM"},
|
{MachO::N_SLINE, "SLINE"}, {MachO::N_ENSYM, "ENSYM"},
|
||||||
{MachO::N_PC, "PC"},
|
{MachO::N_SSYM, "SSYM"}, {MachO::N_SO, "SO"},
|
||||||
{MachO::N_AST, "AST"},
|
{MachO::N_OSO, "OSO"}, {MachO::N_LIB, "LIB"},
|
||||||
{MachO::N_OPT, "OPT"},
|
{MachO::N_LSYM, "LSYM"}, {MachO::N_BINCL, "BINCL"},
|
||||||
{MachO::N_RSYM, "RSYM"},
|
{MachO::N_SOL, "SOL"}, {MachO::N_PARAMS, "PARAM"},
|
||||||
{MachO::N_SLINE, "SLINE"},
|
{MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
|
||||||
{MachO::N_ENSYM, "ENSYM"},
|
{MachO::N_PSYM, "PSYM"}, {MachO::N_EINCL, "EINCL"},
|
||||||
{MachO::N_SSYM, "SSYM"},
|
{MachO::N_ENTRY, "ENTRY"}, {MachO::N_LBRAC, "LBRAC"},
|
||||||
{MachO::N_SO, "SO"},
|
{MachO::N_EXCL, "EXCL"}, {MachO::N_RBRAC, "RBRAC"},
|
||||||
{MachO::N_OSO, "OSO"},
|
{MachO::N_BCOMM, "BCOMM"}, {MachO::N_ECOMM, "ECOMM"},
|
||||||
{MachO::N_LSYM, "LSYM"},
|
{MachO::N_ECOML, "ECOML"}, {MachO::N_LENG, "LENG"},
|
||||||
{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) {
|
static const char *getDarwinStabString(uint8_t NType) {
|
||||||
|
|||||||
Reference in New Issue
Block a user