Skip to content

Commit b573a13

Browse files
Merge pull request swiftlang#7650 from adrian-prantl/strx725
Cherry-pick dsymutil DWARF 5 improvements
2 parents 9004c0e + 014eccf commit b573a13

File tree

19 files changed

+626
-158
lines changed

19 files changed

+626
-158
lines changed

llvm/include/llvm/DWARFLinker/DWARFLinker.h

Lines changed: 32 additions & 20 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

@@ -137,10 +142,9 @@ class DwarfEmitter {
137142
virtual MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) = 0;
138143

139144
/// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
140-
virtual void
141-
emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
142-
const AddressRanges &LinkedRanges,
143-
PatchLocation Patch) = 0;
145+
virtual void emitDwarfDebugRangeListFragment(
146+
const CompileUnit &Unit, const AddressRanges &LinkedRanges,
147+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
144148

145149
/// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
146150
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -153,7 +157,7 @@ class DwarfEmitter {
153157
virtual void emitDwarfDebugLocListFragment(
154158
const CompileUnit &Unit,
155159
const DWARFLocationExpressionsVector &LinkedLocationExpression,
156-
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
160+
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
157161

158162
/// Emit debug locations (.debug_loc, .debug_loclists) footer.
159163
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -604,6 +608,7 @@ class DWARFLinker {
604608
DeclContextTree &ODRContexts,
605609
OffsetsStringPool &DebugStrPool,
606610
OffsetsStringPool &DebugLineStrPool,
611+
DebugDieValuePool &StringOffsetPool,
607612
unsigned Indent = 0);
608613

609614
unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
@@ -651,7 +656,8 @@ class DWARFLinker {
651656
DWARFFile &ObjFile;
652657
OffsetsStringPool &DebugStrPool;
653658
OffsetsStringPool &DebugLineStrPool;
654-
DebugAddrPool AddrPool;
659+
DebugDieValuePool &StringOffsetPool;
660+
DebugDieValuePool AddrPool;
655661

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

677685
/// Recursively clone \p InputDIE into an tree of DIE objects
678686
/// where useless (as decided by lookForDIEsToKeep()) bits have been
@@ -733,6 +741,9 @@ class DWARFLinker {
733741
/// Is this DIE only a declaration?
734742
bool IsDeclaration = false;
735743

744+
/// Is there a DW_AT_str_offsets_base in the CU?
745+
bool AttrStrOffsetBaseSeen = false;
746+
736747
AttributesInfo() = default;
737748
};
738749

@@ -821,7 +832,8 @@ class DWARFLinker {
821832

822833
/// Compute and emit debug ranges(.debug_aranges, .debug_ranges,
823834
/// .debug_rnglists) for \p Unit, patch the attributes referencing it.
824-
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const;
835+
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
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: 12 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

@@ -95,7 +100,8 @@ class DwarfStreamer : public DwarfEmitter {
95100
/// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment.
96101
void emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
97102
const AddressRanges &LinkedRanges,
98-
PatchLocation Patch) override;
103+
PatchLocation Patch,
104+
DebugDieValuePool &AddrPool) override;
99105

100106
/// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
101107
void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
@@ -119,7 +125,7 @@ class DwarfStreamer : public DwarfEmitter {
119125
void emitDwarfDebugLocListFragment(
120126
const CompileUnit &Unit,
121127
const DWARFLocationExpressionsVector &LinkedLocationExpression,
122-
PatchLocation Patch, DebugAddrPool &AddrPool) override;
128+
PatchLocation Patch, DebugDieValuePool &AddrPool) override;
123129

124130
/// Emit debug ranges(.debug_loc, .debug_loclists) footer.
125131
void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
@@ -217,7 +223,8 @@ class DwarfStreamer : public DwarfEmitter {
217223
/// Emit piece of .debug_rnglists for \p LinkedRanges.
218224
void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit,
219225
const AddressRanges &LinkedRanges,
220-
PatchLocation Patch);
226+
PatchLocation Patch,
227+
DebugDieValuePool &AddrPool);
221228

222229
/// Emit piece of .debug_loc for \p LinkedRanges.
223230
void emitDwarfDebugLocTableFragment(
@@ -229,7 +236,7 @@ class DwarfStreamer : public DwarfEmitter {
229236
void emitDwarfDebugLocListsTableFragment(
230237
const CompileUnit &Unit,
231238
const DWARFLocationExpressionsVector &LinkedLocationExpression,
232-
PatchLocation Patch, DebugAddrPool &AddrPool);
239+
PatchLocation Patch, DebugDieValuePool &AddrPool);
233240

234241
/// \defgroup Line table emission
235242
/// @{
@@ -288,6 +295,7 @@ class DwarfStreamer : public DwarfEmitter {
288295
uint64_t MacInfoSectionSize = 0;
289296
uint64_t MacroSectionSize = 0;
290297
uint64_t AddrSectionSize = 0;
298+
uint64_t StrOffsetSectionSize = 0;
291299

292300
/// Keep track of emitted CUs and their Unique ID.
293301
struct EmittedUnit {

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 46 additions & 21 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);
@@ -1812,8 +1832,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
18121832
/// Patch the input object file relevant debug_ranges or debug_rnglists
18131833
/// entries and emit them in the output file. Update the relevant attributes
18141834
/// to point at the new entries.
1815-
void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
1816-
const DWARFFile &File) const {
1835+
void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
1836+
DebugDieValuePool &AddrPool) const {
18171837
if (LLVM_UNLIKELY(Options.Update))
18181838
return;
18191839

@@ -1866,14 +1886,14 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
18661886
}
18671887

18681888
// Emit linked ranges.
1869-
TheDwarfEmitter->emitDwarfDebugRangeListFragment(Unit, LinkedRanges,
1870-
AttributePatch);
1889+
TheDwarfEmitter->emitDwarfDebugRangeListFragment(
1890+
Unit, LinkedRanges, AttributePatch, AddrPool);
18711891
}
18721892

18731893
// Emit ranges for Unit AT_ranges attribute.
18741894
if (UnitRngListAttribute.has_value())
18751895
TheDwarfEmitter->emitDwarfDebugRangeListFragment(
1876-
Unit, LinkedFunctionRanges, *UnitRngListAttribute);
1896+
Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
18771897

18781898
// Emit ranges footer.
18791899
TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
@@ -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

@@ -2515,7 +2536,7 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
25152536
if (LLVM_UNLIKELY(Linker.Options.Update))
25162537
continue;
25172538

2518-
Linker.generateUnitRanges(*CurrentUnit, File);
2539+
Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);
25192540

25202541
auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
25212542
SmallVectorImpl<uint8_t> &OutBytes,
@@ -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)