Skip to content

Commit 014eccf

Browse files
rastogishubhamadrian-prantl
authored andcommitted
Emit a .debug_str_offsets section with dsymutil to
support DW_FORM_strx in dsymutil. Differential Revision: https://reviews.llvm.org/D157036 (cherry picked from commit 53d40b9)
1 parent 9c1f518 commit 014eccf

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

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

113+
/// Emit the debug string offset table described by \p StringOffsets into the
114+
/// .debug_str_offsets table.
115+
virtual void emitStringOffsets(const SmallVector<uint64_t> &StringOffsets,
116+
uint16_t TargetDWARFVersion) = 0;
117+
113118
/// Emit the string table described by \p Pool into .debug_line_str table.
114119
virtual void emitLineStrings(const NonRelocatableStringpool &Pool) = 0;
115120

@@ -139,7 +144,7 @@ class DwarfEmitter {
139144
/// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
140145
virtual void emitDwarfDebugRangeListFragment(
141146
const CompileUnit &Unit, const AddressRanges &LinkedRanges,
142-
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
147+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
143148

144149
/// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
145150
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -152,7 +157,7 @@ class DwarfEmitter {
152157
virtual void emitDwarfDebugLocListFragment(
153158
const CompileUnit &Unit,
154159
const DWARFLocationExpressionsVector &LinkedLocationExpression,
155-
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
160+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
156161

157162
/// Emit debug locations (.debug_loc, .debug_loclists) footer.
158163
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -603,6 +608,7 @@ class DWARFLinker {
603608
DeclContextTree &ODRContexts,
604609
OffsetsStringPool &DebugStrPool,
605610
OffsetsStringPool &DebugLineStrPool,
611+
DebugDieValuePool &StringOffsetPool,
606612
unsigned Indent = 0);
607613

608614
unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
@@ -650,7 +656,8 @@ class DWARFLinker {
650656
DWARFFile &ObjFile;
651657
OffsetsStringPool &DebugStrPool;
652658
OffsetsStringPool &DebugLineStrPool;
653-
DebugAddrPool AddrPool;
659+
DebugDieValuePool &StringOffsetPool;
660+
DebugDieValuePool AddrPool;
654661

655662
/// Allocator used for all the DIEValue objects.
656663
BumpPtrAllocator &DIEAlloc;
@@ -668,10 +675,12 @@ class DWARFLinker {
668675
BumpPtrAllocator &DIEAlloc,
669676
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
670677
bool Update, OffsetsStringPool &DebugStrPool,
671-
OffsetsStringPool &DebugLineStrPool)
678+
OffsetsStringPool &DebugLineStrPool,
679+
DebugDieValuePool &StringOffsetPool)
672680
: Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
673681
DebugStrPool(DebugStrPool), DebugLineStrPool(DebugLineStrPool),
674-
DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Update(Update) {}
682+
StringOffsetPool(StringOffsetPool), DIEAlloc(DIEAlloc),
683+
CompileUnits(CompileUnits), Update(Update) {}
675684

676685
/// Recursively clone \p InputDIE into an tree of DIE objects
677686
/// where useless (as decided by lookForDIEsToKeep()) bits have been
@@ -732,6 +741,9 @@ class DWARFLinker {
732741
/// Is this DIE only a declaration?
733742
bool IsDeclaration = false;
734743

744+
/// Is there a DW_AT_str_offsets_base in the CU?
745+
bool AttrStrOffsetBaseSeen = false;
746+
735747
AttributesInfo() = default;
736748
};
737749

@@ -821,7 +833,7 @@ class DWARFLinker {
821833
/// Compute and emit debug ranges(.debug_aranges, .debug_ranges,
822834
/// .debug_rnglists) for \p Unit, patch the attributes referencing it.
823835
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
824-
DebugAddrPool &AddrPool) const;
836+
DebugDieValuePool &AddrPool) const;
825837

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

llvm/include/llvm/DWARFLinker/DWARFStreamer.h

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

81+
/// Emit the debug string offset table described by \p StringOffsets into the
82+
/// .debug_str_offsets table.
83+
void emitStringOffsets(const SmallVector<uint64_t> &StringOffset,
84+
uint16_t TargetDWARFVersion) override;
85+
8186
/// Emit the string table described by \p Pool into .debug_line_str table.
8287
void emitLineStrings(const NonRelocatableStringpool &Pool) override;
8388

@@ -96,7 +101,7 @@ class DwarfStreamer : public DwarfEmitter {
96101
void emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
97102
const AddressRanges &LinkedRanges,
98103
PatchLocation Patch,
99-
DebugAddrPool &AddrPool) override;
104+
DebugDieValuePool &AddrPool) override;
100105

101106
/// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
102107
void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -120,7 +125,7 @@ class DwarfStreamer : public DwarfEmitter {
120125
void emitDwarfDebugLocListFragment(
121126
const CompileUnit &Unit,
122127
const DWARFLocationExpressionsVector &LinkedLocationExpression,
123-
PatchLocation Patch, DebugAddrPool &AddrPool) override;
128+
PatchLocation Patch, DebugDieValuePool &AddrPool) override;
124129

125130
/// Emit debug ranges(.debug_loc, .debug_loclists) footer.
126131
void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -219,7 +224,7 @@ class DwarfStreamer : public DwarfEmitter {
219224
void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit,
220225
const AddressRanges &LinkedRanges,
221226
PatchLocation Patch,
222-
DebugAddrPool &AddrPool);
227+
DebugDieValuePool &AddrPool);
223228

224229
/// Emit piece of .debug_loc for \p LinkedRanges.
225230
void emitDwarfDebugLocTableFragment(
@@ -231,7 +236,7 @@ class DwarfStreamer : public DwarfEmitter {
231236
void emitDwarfDebugLocListsTableFragment(
232237
const CompileUnit &Unit,
233238
const DWARFLocationExpressionsVector &LinkedLocationExpression,
234-
PatchLocation Patch, DebugAddrPool &AddrPool);
239+
PatchLocation Patch, DebugDieValuePool &AddrPool);
235240

236241
/// \defgroup Line table emission
237242
/// @{
@@ -290,6 +295,7 @@ class DwarfStreamer : public DwarfEmitter {
290295
uint64_t MacInfoSectionSize = 0;
291296
uint64_t MacroSectionSize = 0;
292297
uint64_t AddrSectionSize = 0;
298+
uint64_t StrOffsetSectionSize = 0;
293299

294300
/// Keep track of emitted CUs and their Unique ID.
295301
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;
@@ -1608,9 +1623,6 @@ shouldSkipAttribute(bool Update,
16081623
// Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
16091624
// DW_AT_rnglists_base is removed.
16101625
return !Update;
1611-
case dwarf::DW_AT_str_offsets_base:
1612-
// FIXME: Use the string offset table with Dwarf 5.
1613-
return true;
16141626
case dwarf::DW_AT_loclists_base:
16151627
// In case !Update the .debug_addr table is not generated/preserved.
16161628
// Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
@@ -1777,6 +1789,14 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
17771789
}
17781790
}
17791791

1792+
if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
1793+
Die->getTag() == dwarf::DW_TAG_compile_unit) {
1794+
// No DW_AT_str_offsets_base seen, add it to the DIE.
1795+
Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
1796+
dwarf::DW_FORM_sec_offset, DIEInteger(8));
1797+
OutOffset += 4;
1798+
}
1799+
17801800
DIEAbbrev NewAbbrev = Die->generateAbbrev();
17811801
if (HasChildren)
17821802
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
@@ -1813,7 +1833,7 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
18131833
/// entries and emit them in the output file. Update the relevant attributes
18141834
/// to point at the new entries.
18151835
void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
1816-
DebugAddrPool &AddrPool) const {
1836+
DebugDieValuePool &AddrPool) const {
18171837
if (LLVM_UNLIKELY(Options.Update))
18181838
return;
18191839

@@ -1955,13 +1975,14 @@ void DWARFLinker::DIECloner::emitDebugAddrSection(
19551975
if (DwarfVersion < 5)
19561976
return;
19571977

1958-
if (AddrPool.Addrs.empty())
1978+
if (AddrPool.DieValues.empty())
19591979
return;
19601980

19611981
MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);
19621982
patchAddrBase(*Unit.getOutputUnitDIE(),
19631983
DIEInteger(Emitter->getDebugAddrSectionSize()));
1964-
Emitter->emitDwarfDebugAddrs(AddrPool.Addrs, Unit.getOrigUnit().getAddressByteSize());
1984+
Emitter->emitDwarfDebugAddrs(AddrPool.DieValues,
1985+
Unit.getOrigUnit().getAddressByteSize());
19651986
Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
19661987
}
19671988

@@ -2612,6 +2633,7 @@ Error DWARFLinker::link() {
26122633
// reproducibility.
26132634
OffsetsStringPool DebugStrPool(StringsTranslator, true);
26142635
OffsetsStringPool DebugLineStrPool(StringsTranslator, false);
2636+
DebugDieValuePool StringOffsetPool;
26152637

26162638
// ODR Contexts for the optimize.
26172639
DeclContextTree ODRContexts;
@@ -2675,7 +2697,7 @@ Error DWARFLinker::link() {
26752697

26762698
for (auto &CU : OptContext.ModuleUnits) {
26772699
if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool,
2678-
DebugLineStrPool))
2700+
DebugLineStrPool, StringOffsetPool))
26792701
reportWarning(toString(std::move(Err)), CU.File);
26802702
}
26812703
}
@@ -2772,7 +2794,7 @@ Error DWARFLinker::link() {
27722794
SizeByObject[OptContext.File.FileName].Output =
27732795
DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc,
27742796
OptContext.CompileUnits, Options.Update, DebugStrPool,
2775-
DebugLineStrPool)
2797+
DebugLineStrPool, StringOffsetPool)
27762798
.cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
27772799
OptContext.File.Dwarf->isLittleEndian());
27782800
}
@@ -2789,6 +2811,8 @@ Error DWARFLinker::link() {
27892811
if (TheDwarfEmitter != nullptr) {
27902812
TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
27912813
TheDwarfEmitter->emitStrings(DebugStrPool);
2814+
TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues,
2815+
Options.TargetDWARFVersion);
27922816
TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
27932817
for (AccelTableKind TableKind : Options.AccelTables) {
27942818
switch (TableKind) {
@@ -2905,6 +2929,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
29052929
DeclContextTree &ODRContexts,
29062930
OffsetsStringPool &DebugStrPool,
29072931
OffsetsStringPool &DebugLineStrPool,
2932+
DebugDieValuePool &StringOffsetPool,
29082933
unsigned Indent) {
29092934
assert(Unit.Unit.get() != nullptr);
29102935

@@ -2931,7 +2956,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
29312956
CompileUnits.emplace_back(std::move(Unit.Unit));
29322957
assert(TheDwarfEmitter);
29332958
DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits,
2934-
Options.Update, DebugStrPool, DebugLineStrPool)
2959+
Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
29352960
.cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
29362961
Unit.File.Dwarf->isLittleEndian());
29372962
return Error::success();

0 commit comments

Comments
 (0)