Skip to content

Commit 53d40b9

Browse files
Emit a .debug_str_offsets section with dsymutil to
support DW_FORM_strx in dsymutil. Differential Revision: https://reviews.llvm.org/D157036
1 parent 4f0bd8f commit 53d40b9

File tree

18 files changed

+569
-123
lines changed

18 files changed

+569
-123
lines changed

llvm/include/llvm/DWARFLinker/DWARFLinker.h

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,22 @@ class AddressesMap {
7575

7676
using Offset2UnitMap = DenseMap<uint64_t, CompileUnit *>;
7777

78-
struct DebugAddrPool {
79-
DenseMap<uint64_t, uint64_t> AddrIndexMap;
80-
SmallVector<uint64_t> Addrs;
81-
82-
uint64_t getAddrIndex(uint64_t Addr) {
83-
DenseMap<uint64_t, uint64_t>::iterator It = AddrIndexMap.find(Addr);
84-
if (It == AddrIndexMap.end()) {
85-
It = AddrIndexMap.insert(std::make_pair(Addr, Addrs.size())).first;
86-
Addrs.push_back(Addr);
78+
struct DebugDieValuePool {
79+
DenseMap<uint64_t, uint64_t> DieValueMap;
80+
SmallVector<uint64_t> DieValues;
81+
82+
uint64_t getValueIndex(uint64_t Value) {
83+
DenseMap<uint64_t, uint64_t>::iterator It = DieValueMap.find(Value);
84+
if (It == DieValueMap.end()) {
85+
It = DieValueMap.insert(std::make_pair(Value, DieValues.size())).first;
86+
DieValues.push_back(Value);
8787
}
8888
return It->second;
8989
}
9090

9191
void clear() {
92-
AddrIndexMap.clear();
93-
Addrs.clear();
92+
DieValueMap.clear();
93+
DieValues.clear();
9494
}
9595
};
9696

@@ -113,6 +113,11 @@ class DwarfEmitter {
113113
/// Emit the string table described by \p Pool into .debug_str table.
114114
virtual void emitStrings(const NonRelocatableStringpool &Pool) = 0;
115115

116+
/// Emit the debug string offset table described by \p StringOffsets into the
117+
/// .debug_str_offsets table.
118+
virtual void emitStringOffsets(const SmallVector<uint64_t> &StringOffsets,
119+
uint16_t TargetDWARFVersion) = 0;
120+
116121
/// Emit the string table described by \p Pool into .debug_line_str table.
117122
virtual void emitLineStrings(const NonRelocatableStringpool &Pool) = 0;
118123

@@ -142,7 +147,7 @@ class DwarfEmitter {
142147
/// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
143148
virtual void emitDwarfDebugRangeListFragment(
144149
const CompileUnit &Unit, const AddressRanges &LinkedRanges,
145-
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
150+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
146151

147152
/// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
148153
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -155,7 +160,7 @@ class DwarfEmitter {
155160
virtual void emitDwarfDebugLocListFragment(
156161
const CompileUnit &Unit,
157162
const DWARFLocationExpressionsVector &LinkedLocationExpression,
158-
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
163+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
159164

160165
/// Emit debug locations (.debug_loc, .debug_loclists) footer.
161166
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -607,6 +612,7 @@ class DWARFLinker {
607612
DeclContextTree &ODRContexts,
608613
OffsetsStringPool &DebugStrPool,
609614
OffsetsStringPool &DebugLineStrPool,
615+
DebugDieValuePool &StringOffsetPool,
610616
unsigned Indent = 0);
611617

612618
unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
@@ -654,7 +660,8 @@ class DWARFLinker {
654660
DWARFFile &ObjFile;
655661
OffsetsStringPool &DebugStrPool;
656662
OffsetsStringPool &DebugLineStrPool;
657-
DebugAddrPool AddrPool;
663+
DebugDieValuePool &StringOffsetPool;
664+
DebugDieValuePool AddrPool;
658665

659666
/// Allocator used for all the DIEValue objects.
660667
BumpPtrAllocator &DIEAlloc;
@@ -672,10 +679,12 @@ class DWARFLinker {
672679
BumpPtrAllocator &DIEAlloc,
673680
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
674681
bool Update, OffsetsStringPool &DebugStrPool,
675-
OffsetsStringPool &DebugLineStrPool)
682+
OffsetsStringPool &DebugLineStrPool,
683+
DebugDieValuePool &StringOffsetPool)
676684
: Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
677685
DebugStrPool(DebugStrPool), DebugLineStrPool(DebugLineStrPool),
678-
DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Update(Update) {}
686+
StringOffsetPool(StringOffsetPool), DIEAlloc(DIEAlloc),
687+
CompileUnits(CompileUnits), Update(Update) {}
679688

680689
/// Recursively clone \p InputDIE into an tree of DIE objects
681690
/// where useless (as decided by lookForDIEsToKeep()) bits have been
@@ -736,6 +745,9 @@ class DWARFLinker {
736745
/// Is this DIE only a declaration?
737746
bool IsDeclaration = false;
738747

748+
/// Is there a DW_AT_str_offsets_base in the CU?
749+
bool AttrStrOffsetBaseSeen = false;
750+
739751
AttributesInfo() = default;
740752
};
741753

@@ -825,7 +837,7 @@ class DWARFLinker {
825837
/// Compute and emit debug ranges(.debug_aranges, .debug_ranges,
826838
/// .debug_rnglists) for \p Unit, patch the attributes referencing it.
827839
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
828-
DebugAddrPool &AddrPool) const;
840+
DebugDieValuePool &AddrPool) const;
829841

830842
/// Emit the accelerator entries for \p Unit.
831843
void emitAcceleratorEntriesForUnit(CompileUnit &Unit);

llvm/include/llvm/DWARFLinker/DWARFStreamer.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ class DwarfStreamer : public DwarfEmitter {
8181
/// Emit the string table described by \p Pool into .debug_str table.
8282
void emitStrings(const NonRelocatableStringpool &Pool) override;
8383

84+
/// Emit the debug string offset table described by \p StringOffsets into the
85+
/// .debug_str_offsets table.
86+
void emitStringOffsets(const SmallVector<uint64_t> &StringOffset,
87+
uint16_t TargetDWARFVersion) override;
88+
8489
/// Emit the string table described by \p Pool into .debug_line_str table.
8590
void emitLineStrings(const NonRelocatableStringpool &Pool) override;
8691

@@ -99,7 +104,7 @@ class DwarfStreamer : public DwarfEmitter {
99104
void emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
100105
const AddressRanges &LinkedRanges,
101106
PatchLocation Patch,
102-
DebugAddrPool &AddrPool) override;
107+
DebugDieValuePool &AddrPool) override;
103108

104109
/// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
105110
void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -123,7 +128,7 @@ class DwarfStreamer : public DwarfEmitter {
123128
void emitDwarfDebugLocListFragment(
124129
const CompileUnit &Unit,
125130
const DWARFLocationExpressionsVector &LinkedLocationExpression,
126-
PatchLocation Patch, DebugAddrPool &AddrPool) override;
131+
PatchLocation Patch, DebugDieValuePool &AddrPool) override;
127132

128133
/// Emit debug ranges(.debug_loc, .debug_loclists) footer.
129134
void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -222,7 +227,7 @@ class DwarfStreamer : public DwarfEmitter {
222227
void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit,
223228
const AddressRanges &LinkedRanges,
224229
PatchLocation Patch,
225-
DebugAddrPool &AddrPool);
230+
DebugDieValuePool &AddrPool);
226231

227232
/// Emit piece of .debug_loc for \p LinkedRanges.
228233
void emitDwarfDebugLocTableFragment(
@@ -234,7 +239,7 @@ class DwarfStreamer : public DwarfEmitter {
234239
void emitDwarfDebugLocListsTableFragment(
235240
const CompileUnit &Unit,
236241
const DWARFLocationExpressionsVector &LinkedLocationExpression,
237-
PatchLocation Patch, DebugAddrPool &AddrPool);
242+
PatchLocation Patch, DebugDieValuePool &AddrPool);
238243

239244
/// \defgroup Line table emission
240245
/// @{
@@ -293,6 +298,7 @@ class DwarfStreamer : public DwarfEmitter {
293298
uint64_t MacInfoSectionSize = 0;
294299
uint64_t MacroSectionSize = 0;
295300
uint64_t AddrSectionSize = 0;
301+
uint64_t StrOffsetSectionSize = 0;
296302

297303
/// Keep track of emitted CUs and their Unique ID.
298304
struct EmittedUnit {

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,32 +1014,36 @@ void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
10141014
unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
10151015
AttributeSpec AttrSpec,
10161016
const DWARFFormValue &Val,
1017-
const DWARFUnit &,
1017+
const DWARFUnit &U,
10181018
AttributesInfo &Info) {
10191019
std::optional<const char *> String = dwarf::toString(Val);
10201020
if (!String)
10211021
return 0;
1022-
10231022
DwarfStringPoolEntryRef StringEntry;
10241023
if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
10251024
StringEntry = DebugLineStrPool.getEntry(*String);
10261025
} else {
10271026
StringEntry = DebugStrPool.getEntry(*String);
1028-
10291027
// Update attributes info.
10301028
if (AttrSpec.Attr == dwarf::DW_AT_name)
10311029
Info.Name = StringEntry;
10321030
else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
10331031
AttrSpec.Attr == dwarf::DW_AT_linkage_name)
10341032
Info.MangledName = StringEntry;
1035-
1033+
if (U.getVersion() >= 5) {
1034+
// Switch everything to DW_FORM_strx strings.
1035+
auto StringOffsetIndex =
1036+
StringOffsetPool.getValueIndex(StringEntry.getOffset());
1037+
return Die
1038+
.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
1039+
dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
1040+
->sizeOf(U.getFormParams());
1041+
}
10361042
// Switch everything to out of line strings.
10371043
AttrSpec.Form = dwarf::DW_FORM_strp;
10381044
}
1039-
10401045
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form,
10411046
DIEInteger(StringEntry.getOffset()));
1042-
10431047
return 4;
10441048
}
10451049

@@ -1359,7 +1363,7 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
13591363
return Unit.getOrigUnit().getAddressByteSize();
13601364
}
13611365

1362-
auto AddrIndex = AddrPool.getAddrIndex(*Addr);
1366+
auto AddrIndex = AddrPool.getValueIndex(*Addr);
13631367

13641368
return Die
13651369
.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
@@ -1391,6 +1395,17 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
13911395
}
13921396
}
13931397

1398+
if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
1399+
// DWARFLinker generates common .debug_str_offsets table used for all
1400+
// compile units. The offset to the common .debug_str_offsets table is 8 on
1401+
// DWARF32.
1402+
Info.AttrStrOffsetBaseSeen = true;
1403+
return Die
1404+
.addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1405+
dwarf::DW_FORM_sec_offset, DIEInteger(8))
1406+
->sizeOf(Unit.getOrigUnit().getFormParams());
1407+
}
1408+
13941409
if (LLVM_UNLIKELY(Linker.Options.Update)) {
13951410
if (auto OptionalValue = Val.getAsUnsignedConstant())
13961411
Value = *OptionalValue;
@@ -1634,9 +1649,6 @@ shouldSkipAttribute(bool Update,
16341649
// Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
16351650
// DW_AT_rnglists_base is removed.
16361651
return !Update;
1637-
case dwarf::DW_AT_str_offsets_base:
1638-
// FIXME: Use the string offset table with Dwarf 5.
1639-
return true;
16401652
case dwarf::DW_AT_loclists_base:
16411653
// In case !Update the .debug_addr table is not generated/preserved.
16421654
// Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
@@ -1803,6 +1815,14 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
18031815
}
18041816
}
18051817

1818+
if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
1819+
Die->getTag() == dwarf::DW_TAG_compile_unit) {
1820+
// No DW_AT_str_offsets_base seen, add it to the DIE.
1821+
Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1822+
dwarf::DW_FORM_sec_offset, DIEInteger(8));
1823+
OutOffset += 4;
1824+
}
1825+
18061826
DIEAbbrev NewAbbrev = Die->generateAbbrev();
18071827
if (HasChildren)
18081828
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
@@ -1839,7 +1859,7 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
18391859
/// entries and emit them in the output file. Update the relevant attributes
18401860
/// to point at the new entries.
18411861
void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
1842-
DebugAddrPool &AddrPool) const {
1862+
DebugDieValuePool &AddrPool) const {
18431863
if (LLVM_UNLIKELY(Options.Update))
18441864
return;
18451865

@@ -1981,13 +2001,14 @@ void DWARFLinker::DIECloner::emitDebugAddrSection(
19812001
if (DwarfVersion < 5)
19822002
return;
19832003

1984-
if (AddrPool.Addrs.empty())
2004+
if (AddrPool.DieValues.empty())
19852005
return;
19862006

19872007
MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);
19882008
patchAddrBase(*Unit.getOutputUnitDIE(),
19892009
DIEInteger(Emitter->getDebugAddrSectionSize()));
1990-
Emitter->emitDwarfDebugAddrs(AddrPool.Addrs, Unit.getOrigUnit().getAddressByteSize());
2010+
Emitter->emitDwarfDebugAddrs(AddrPool.DieValues,
2011+
Unit.getOrigUnit().getAddressByteSize());
19912012
Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
19922013
}
19932014

@@ -2701,6 +2722,7 @@ Error DWARFLinker::link() {
27012722
// reproducibility.
27022723
OffsetsStringPool DebugStrPool(StringsTranslator, true);
27032724
OffsetsStringPool DebugLineStrPool(StringsTranslator, false);
2725+
DebugDieValuePool StringOffsetPool;
27042726

27052727
// ODR Contexts for the optimize.
27062728
DeclContextTree ODRContexts;
@@ -2767,7 +2789,7 @@ Error DWARFLinker::link() {
27672789

27682790
for (auto &CU : OptContext.ModuleUnits) {
27692791
if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool,
2770-
DebugLineStrPool))
2792+
DebugLineStrPool, StringOffsetPool))
27712793
reportWarning(toString(std::move(Err)), CU.File);
27722794
}
27732795
}
@@ -2864,7 +2886,7 @@ Error DWARFLinker::link() {
28642886
SizeByObject[OptContext.File.FileName].Output =
28652887
DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc,
28662888
OptContext.CompileUnits, Options.Update, DebugStrPool,
2867-
DebugLineStrPool)
2889+
DebugLineStrPool, StringOffsetPool)
28682890
.cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
28692891
OptContext.File.Dwarf->isLittleEndian());
28702892
}
@@ -2881,6 +2903,8 @@ Error DWARFLinker::link() {
28812903
if (TheDwarfEmitter != nullptr) {
28822904
TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
28832905
TheDwarfEmitter->emitStrings(DebugStrPool);
2906+
TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues,
2907+
Options.TargetDWARFVersion);
28842908
TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
28852909
for (AccelTableKind TableKind : Options.AccelTables) {
28862910
switch (TableKind) {
@@ -2997,6 +3021,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
29973021
DeclContextTree &ODRContexts,
29983022
OffsetsStringPool &DebugStrPool,
29993023
OffsetsStringPool &DebugLineStrPool,
3024+
DebugDieValuePool &StringOffsetPool,
30003025
unsigned Indent) {
30013026
assert(Unit.Unit.get() != nullptr);
30023027

@@ -3023,7 +3048,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
30233048
CompileUnits.emplace_back(std::move(Unit.Unit));
30243049
assert(TheDwarfEmitter);
30253050
DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits,
3026-
Options.Update, DebugStrPool, DebugLineStrPool)
3051+
Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
30273052
.cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
30283053
Unit.File.Dwarf->isLittleEndian());
30293054
return Error::success();

0 commit comments

Comments
 (0)