Skip to content

Commit 122c89b

Browse files
Alpha-10000JDevlieghere
authored andcommitted
[dsymutil] Add support for mergeable libraries
This adds support in dsymutil for mergeable libraries [1]. dsymutil reads a new stab emitted by ld, allowing it to operate on dynamic libraries instead of object files. It also now loads the DWARF files associated to the libraries, and build the debug map for each binary from the list of symbols exported by the library. For each Debug Map Object, there is a new associated Relocation Map which is serialized from the information retrieved in the original debug_info (or debug_addr) section of the .o file. The final DWARF file has multiple compile units, so the offsets information of the relocations are adjusted relatively to the compile unit they will end up belonging to, inside the final linked DWARF file. [1] https://developer.apple.com/documentation/xcode/configuring-your-project-to-use-mergeable-libraries Differential revision: https://reviews.llvm.org/D158124
1 parent 4c28e66 commit 122c89b

File tree

34 files changed

+1217
-198
lines changed

34 files changed

+1217
-198
lines changed

llvm/docs/CommandGuide/dsymutil.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,26 @@ OPTIONS
3232
architectures will be linked by default and any architectures that can't be
3333
properly linked will cause :program:`dsymutil` to return an error.
3434

35+
.. option:: --build-variant-suffix <suffix=buildvariant>
36+
37+
Specify the build variant suffix used to build the executabe file.
38+
There can be multiple variants for the binary of a product, each built
39+
slightly differently. The most common build variants are 'debug' and
40+
'profile'. Setting the DYLD_IMAGE_SUFFIX environment variable will
41+
cause dyld to load the specified variant at runtime.
42+
3543
.. option:: --dump-debug-map
3644

3745
Dump the *executable*'s debug-map (the list of the object files containing the
3846
debug information) in YAML format and exit. No DWARF link will take place.
3947

48+
.. option:: -D <path>
49+
50+
Specify a directory that contain dSYM files to search for.
51+
This is used for mergeable libraries, so dsymutil knows where to look
52+
for dSYM files with debug information about symbols present in those
53+
libraries.
54+
4055
.. option:: --fat64
4156

4257
Use a 64-bit header when emitting universal binaries.

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ HANDLE_DW_AT(0x3fec, APPLE_objc_complete_type, 0, APPLE)
629629
HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE)
630630
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
631631
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
632+
HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
632633

633634
// Attribute form encodings.
634635
HANDLE_DW_FORM(0x01, addr, 2, DWARF)

llvm/include/llvm/BinaryFormat/MachO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ enum StabType {
373373
N_SSYM = 0x60u,
374374
N_SO = 0x64u,
375375
N_OSO = 0x66u,
376+
N_LIB = 0x68u,
376377
N_LSYM = 0x80u,
377378
N_BINCL = 0x82u,
378379
N_SOL = 0x84u,

llvm/include/llvm/DWARFLinker/DWARFLinker.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,33 @@ class AddressesMap {
6262
virtual std::optional<int64_t>
6363
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
6464

65+
/// Returns the file name associated to the AddessesMap
66+
virtual std::optional<StringRef> getLibraryInstallName() = 0;
67+
6568
/// Apply the valid relocations to the buffer \p Data, taking into
6669
/// account that Data is at \p BaseOffset in the .debug_info section.
6770
///
6871
/// \returns true whether any reloc has been applied.
6972
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
7073
bool IsLittleEndian) = 0;
7174

75+
/// Check if the linker needs to gather and save relocation info.
76+
virtual bool needToSaveValidRelocs() = 0;
77+
78+
/// Update and save original relocations located in between StartOffset and
79+
/// EndOffset. LinkedOffset is the value which should be added to the original
80+
/// relocation offset to get new relocation offset in linked binary.
81+
virtual void updateAndSaveValidRelocs(bool IsDWARF5,
82+
uint64_t OriginalUnitOffset,
83+
int64_t LinkedOffset,
84+
uint64_t StartOffset,
85+
uint64_t EndOffset) = 0;
86+
87+
/// Update the valid relocations that used OriginalUnitOffset as the compile
88+
/// unit offset, and update their values to reflect OutputUnitOffset.
89+
virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
90+
uint64_t OutputUnitOffset) = 0;
91+
7292
/// Erases all data.
7393
virtual void clear() = 0;
7494
};
@@ -752,6 +772,9 @@ class DWARFLinker {
752772
/// Is there a DW_AT_str_offsets_base in the CU?
753773
bool AttrStrOffsetBaseSeen = false;
754774

775+
/// Is there a DW_AT_APPLE_origin in the CU?
776+
bool HasAppleOrigin = false;
777+
755778
AttributesInfo() = default;
756779
};
757780

llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,31 @@ class AddressesMap {
5555
virtual std::optional<int64_t>
5656
getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
5757

58+
// Returns the library install name associated to the AddessesMap.
59+
virtual std::optional<StringRef> getLibraryInstallName() = 0;
60+
5861
/// Apply the valid relocations to the buffer \p Data, taking into
5962
/// account that Data is at \p BaseOffset in the .debug_info section.
6063
///
6164
/// \returns true whether any reloc has been applied.
6265
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
6366
bool IsLittleEndian) = 0;
6467

68+
/// Check if the linker needs to gather and save relocation info.
69+
virtual bool needToSaveValidRelocs() = 0;
70+
71+
/// Update and save relocation values to be serialized
72+
virtual void updateAndSaveValidRelocs(bool IsDWARF5,
73+
uint64_t OriginalUnitOffset,
74+
int64_t LinkedOffset,
75+
uint64_t StartOffset,
76+
uint64_t EndOffset) = 0;
77+
78+
/// Update the valid relocations that used OriginalUnitOffset as the compile
79+
/// unit offset, and update their values to reflect OutputUnitOffset.
80+
virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
81+
uint64_t OutputUnitOffset) = 0;
82+
6583
/// Erases all data.
6684
virtual void clear() = 0;
6785

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,9 +418,6 @@ class Triple {
418418
/// Get the architecture (first) component of the triple.
419419
StringRef getArchName() const;
420420

421-
/// Get the architecture name based on Kind and SubArch.
422-
StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch) const;
423-
424421
/// Get the vendor (second) component of the triple.
425422
StringRef getVendorName() const;
426423

@@ -1118,6 +1115,9 @@ class Triple {
11181115
/// Get the canonical name for the \p Kind architecture.
11191116
static StringRef getArchTypeName(ArchType Kind);
11201117

1118+
/// Get the architecture name based on \p Kind and \p SubArch.
1119+
static StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch);
1120+
11211121
/// Get the "prefix" canonical name for the \p Kind architecture. This is the
11221122
/// prefix used by the architecture specific builtins, and is suitable for
11231123
/// passing to \see Intrinsic::getIntrinsicForClangBuiltin().

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,15 @@ unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
10261026
StringEntry = DebugLineStrPool.getEntry(*String);
10271027
} else {
10281028
StringEntry = DebugStrPool.getEntry(*String);
1029+
1030+
if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
1031+
Info.HasAppleOrigin = true;
1032+
if (std::optional<StringRef> FileName =
1033+
ObjFile.Addresses->getLibraryInstallName()) {
1034+
StringEntry = DebugStrPool.getEntry(*FileName);
1035+
}
1036+
}
1037+
10291038
// Update attributes info.
10301039
if (AttrSpec.Attr == dwarf::DW_AT_name)
10311040
Info.Name = StringEntry;
@@ -1637,6 +1646,12 @@ shouldSkipAttribute(bool Update,
16371646
}
16381647
}
16391648

1649+
struct AttributeLinkedOffsetFixup {
1650+
int64_t LinkedOffsetFixupVal;
1651+
uint64_t InputAttrStartOffset;
1652+
uint64_t InputAttrEndOffset;
1653+
};
1654+
16401655
DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
16411656
const DWARFFile &File, CompileUnit &Unit,
16421657
int64_t PCOffset, uint32_t OutOffset,
@@ -1720,24 +1735,51 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
17201735
Flags |= TF_SkipPC;
17211736
}
17221737

1738+
std::optional<StringRef> LibraryInstallName =
1739+
ObjFile.Addresses->getLibraryInstallName();
1740+
SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
17231741
for (const auto &AttrSpec : Abbrev->attributes()) {
17241742
if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) {
17251743
DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
17261744
U.getFormParams());
17271745
continue;
17281746
}
17291747

1748+
AttributeLinkedOffsetFixup CurAttrFixup;
1749+
CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;
1750+
CurAttrFixup.LinkedOffsetFixupVal =
1751+
Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
1752+
17301753
DWARFFormValue Val = AttrSpec.getFormValue();
17311754
uint64_t AttrSize = Offset;
17321755
Val.extractValue(Data, &Offset, U.getFormParams(), &U);
1756+
CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;
17331757
AttrSize = Offset - AttrSize;
17341758

1735-
OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec,
1736-
AttrSize, AttrInfo, IsLittleEndian);
1759+
uint64_t FinalAttrSize =
1760+
cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
1761+
AttrInfo, IsLittleEndian);
1762+
if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
1763+
AttributesFixups.push_back(CurAttrFixup);
1764+
1765+
OutOffset += FinalAttrSize;
17371766
}
17381767

1739-
// Look for accelerator entries.
17401768
uint16_t Tag = InputDIE.getTag();
1769+
// Add the DW_AT_APPLE_origin attribute to Compile Unit die if we have
1770+
// an install name and the DWARF doesn't have the attribute yet.
1771+
const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) &&
1772+
LibraryInstallName.has_value() &&
1773+
!AttrInfo.HasAppleOrigin;
1774+
if (NeedsAppleOrigin) {
1775+
auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
1776+
Die->addValue(DIEAlloc, dwarf::Attribute(dwarf::DW_AT_APPLE_origin),
1777+
dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset()));
1778+
AttrInfo.Name = StringEntry;
1779+
OutOffset += 4;
1780+
}
1781+
1782+
// Look for accelerator entries.
17411783
// FIXME: This is slightly wrong. An inline_subroutine without a
17421784
// low_pc, but with AT_ranges might be interesting to get into the
17431785
// accelerator tables too. For now stick with dsymutil's behavior.
@@ -1806,8 +1848,19 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
18061848
Linker.assignAbbrev(NewAbbrev);
18071849
Die->setAbbrevNumber(NewAbbrev.getNumber());
18081850

1851+
uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber());
1852+
18091853
// Add the size of the abbreviation number to the output offset.
1810-
OutOffset += getULEB128Size(Die->getAbbrevNumber());
1854+
OutOffset += AbbrevNumberSize;
1855+
1856+
// Update fixups with the size of the abbreviation number
1857+
for (AttributeLinkedOffsetFixup &F : AttributesFixups)
1858+
F.LinkedOffsetFixupVal += AbbrevNumberSize;
1859+
1860+
for (AttributeLinkedOffsetFixup &F : AttributesFixups)
1861+
ObjFile.Addresses->updateAndSaveValidRelocs(
1862+
Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
1863+
F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset);
18111864

18121865
if (!HasChildren) {
18131866
// Update our size.

llvm/lib/TargetParser/Triple.cpp

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,36 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
9090
llvm_unreachable("Invalid ArchType!");
9191
}
9292

93+
StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) {
94+
switch (Kind) {
95+
case Triple::mips:
96+
if (SubArch == MipsSubArch_r6)
97+
return "mipsisa32r6";
98+
break;
99+
case Triple::mipsel:
100+
if (SubArch == MipsSubArch_r6)
101+
return "mipsisa32r6el";
102+
break;
103+
case Triple::mips64:
104+
if (SubArch == MipsSubArch_r6)
105+
return "mipsisa64r6";
106+
break;
107+
case Triple::mips64el:
108+
if (SubArch == MipsSubArch_r6)
109+
return "mipsisa64r6el";
110+
break;
111+
case Triple::aarch64:
112+
if (SubArch == AArch64SubArch_arm64ec)
113+
return "arm64ec";
114+
if (SubArch == AArch64SubArch_arm64e)
115+
return "arm64e";
116+
break;
117+
default:
118+
break;
119+
}
120+
return getArchTypeName(Kind);
121+
}
122+
93123
StringRef Triple::getArchTypePrefix(ArchType Kind) {
94124
switch (Kind) {
95125
default:
@@ -1143,34 +1173,6 @@ StringRef Triple::getArchName() const {
11431173
return StringRef(Data).split('-').first; // Isolate first component
11441174
}
11451175

1146-
StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) const {
1147-
switch (Kind) {
1148-
case Triple::mips:
1149-
if (SubArch == MipsSubArch_r6)
1150-
return "mipsisa32r6";
1151-
break;
1152-
case Triple::mipsel:
1153-
if (SubArch == MipsSubArch_r6)
1154-
return "mipsisa32r6el";
1155-
break;
1156-
case Triple::mips64:
1157-
if (SubArch == MipsSubArch_r6)
1158-
return "mipsisa64r6";
1159-
break;
1160-
case Triple::mips64el:
1161-
if (SubArch == MipsSubArch_r6)
1162-
return "mipsisa64r6el";
1163-
break;
1164-
case Triple::aarch64:
1165-
if (SubArch == AArch64SubArch_arm64ec)
1166-
return "arm64ec";
1167-
break;
1168-
default:
1169-
break;
1170-
}
1171-
return getArchTypeName(Kind);
1172-
}
1173-
11741176
StringRef Triple::getVendorName() const {
11751177
StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
11761178
return Tmp.split('-').first; // Isolate second component
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>English</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>com.apple.xcode.dsym.bar-relink-variant.dylib</string>
9+
<key>CFBundleInfoDictionaryVersion</key>
10+
<string>6.0</string>
11+
<key>CFBundlePackageType</key>
12+
<string>dSYM</string>
13+
<key>CFBundleSignature</key>
14+
<string>????</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>1.0</string>
17+
<key>CFBundleVersion</key>
18+
<string>1</string>
19+
</dict>
20+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
triple: 'arm64-apple-darwin'
3+
binary-path: bar-relink-variant.dylib
4+
relocations:
5+
- { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
6+
- { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
7+
- { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
8+
...
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>English</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>com.apple.xcode.dsym.bar-relink.dylib</string>
9+
<key>CFBundleInfoDictionaryVersion</key>
10+
<string>6.0</string>
11+
<key>CFBundlePackageType</key>
12+
<string>dSYM</string>
13+
<key>CFBundleSignature</key>
14+
<string>????</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>1.0</string>
17+
<key>CFBundleVersion</key>
18+
<string>1</string>
19+
</dict>
20+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
triple: 'arm64-apple-darwin'
3+
binary-path: bar-relink.dylib
4+
relocations:
5+
- { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
6+
- { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
7+
- { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
8+
...
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>English</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>com.apple.xcode.dsym.foo-relink-variant.dylib</string>
9+
<key>CFBundleInfoDictionaryVersion</key>
10+
<string>6.0</string>
11+
<key>CFBundlePackageType</key>
12+
<string>dSYM</string>
13+
<key>CFBundleSignature</key>
14+
<string>????</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>1.0</string>
17+
<key>CFBundleVersion</key>
18+
<string>1</string>
19+
</dict>
20+
</plist>

0 commit comments

Comments
 (0)