Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions llvm/include/llvm/DWARFLinker/DWARFLinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,22 @@ class AddressesMap {

using Offset2UnitMap = DenseMap<uint64_t, CompileUnit *>;

struct DebugAddrPool {
DenseMap<uint64_t, uint64_t> AddrIndexMap;
SmallVector<uint64_t> Addrs;

uint64_t getAddrIndex(uint64_t Addr) {
DenseMap<uint64_t, uint64_t>::iterator It = AddrIndexMap.find(Addr);
if (It == AddrIndexMap.end()) {
It = AddrIndexMap.insert(std::make_pair(Addr, Addrs.size())).first;
Addrs.push_back(Addr);
struct DebugDieValuePool {
DenseMap<uint64_t, uint64_t> DieValueMap;
SmallVector<uint64_t> DieValues;

uint64_t getValueIndex(uint64_t Value) {
DenseMap<uint64_t, uint64_t>::iterator It = DieValueMap.find(Value);
if (It == DieValueMap.end()) {
It = DieValueMap.insert(std::make_pair(Value, DieValues.size())).first;
DieValues.push_back(Value);
}
return It->second;
}

void clear() {
AddrIndexMap.clear();
Addrs.clear();
DieValueMap.clear();
DieValues.clear();
}
};

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

/// Emit the debug string offset table described by \p StringOffsets into the
/// .debug_str_offsets table.
virtual void emitStringOffsets(const SmallVector<uint64_t> &StringOffsets,
uint16_t TargetDWARFVersion) = 0;

/// Emit the string table described by \p Pool into .debug_line_str table.
virtual void emitLineStrings(const NonRelocatableStringpool &Pool) = 0;

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

/// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
virtual void
emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
const AddressRanges &LinkedRanges,
PatchLocation Patch) = 0;
virtual void emitDwarfDebugRangeListFragment(
const CompileUnit &Unit, const AddressRanges &LinkedRanges,
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;

/// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
Expand All @@ -153,7 +157,7 @@ class DwarfEmitter {
virtual void emitDwarfDebugLocListFragment(
const CompileUnit &Unit,
const DWARFLocationExpressionsVector &LinkedLocationExpression,
PatchLocation Patch, DebugAddrPool &AddrPool) = 0;
PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;

/// Emit debug locations (.debug_loc, .debug_loclists) footer.
virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
Expand Down Expand Up @@ -604,6 +608,7 @@ class DWARFLinker {
DeclContextTree &ODRContexts,
OffsetsStringPool &DebugStrPool,
OffsetsStringPool &DebugLineStrPool,
DebugDieValuePool &StringOffsetPool,
unsigned Indent = 0);

unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
Expand Down Expand Up @@ -651,7 +656,8 @@ class DWARFLinker {
DWARFFile &ObjFile;
OffsetsStringPool &DebugStrPool;
OffsetsStringPool &DebugLineStrPool;
DebugAddrPool AddrPool;
DebugDieValuePool &StringOffsetPool;
DebugDieValuePool AddrPool;

/// Allocator used for all the DIEValue objects.
BumpPtrAllocator &DIEAlloc;
Expand All @@ -669,10 +675,12 @@ class DWARFLinker {
BumpPtrAllocator &DIEAlloc,
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
bool Update, OffsetsStringPool &DebugStrPool,
OffsetsStringPool &DebugLineStrPool)
OffsetsStringPool &DebugLineStrPool,
DebugDieValuePool &StringOffsetPool)
: Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
DebugStrPool(DebugStrPool), DebugLineStrPool(DebugLineStrPool),
DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Update(Update) {}
StringOffsetPool(StringOffsetPool), DIEAlloc(DIEAlloc),
CompileUnits(CompileUnits), Update(Update) {}

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

/// Is there a DW_AT_str_offsets_base in the CU?
bool AttrStrOffsetBaseSeen = false;

AttributesInfo() = default;
};

Expand Down Expand Up @@ -821,7 +832,8 @@ class DWARFLinker {

/// Compute and emit debug ranges(.debug_aranges, .debug_ranges,
/// .debug_rnglists) for \p Unit, patch the attributes referencing it.
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const;
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
DebugDieValuePool &AddrPool) const;

/// Emit the accelerator entries for \p Unit.
void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
Expand Down
16 changes: 12 additions & 4 deletions llvm/include/llvm/DWARFLinker/DWARFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class DwarfStreamer : public DwarfEmitter {
/// Emit the string table described by \p Pool into .debug_str table.
void emitStrings(const NonRelocatableStringpool &Pool) override;

/// Emit the debug string offset table described by \p StringOffsets into the
/// .debug_str_offsets table.
void emitStringOffsets(const SmallVector<uint64_t> &StringOffset,
uint16_t TargetDWARFVersion) override;

/// Emit the string table described by \p Pool into .debug_line_str table.
void emitLineStrings(const NonRelocatableStringpool &Pool) override;

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

/// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
Expand All @@ -119,7 +125,7 @@ class DwarfStreamer : public DwarfEmitter {
void emitDwarfDebugLocListFragment(
const CompileUnit &Unit,
const DWARFLocationExpressionsVector &LinkedLocationExpression,
PatchLocation Patch, DebugAddrPool &AddrPool) override;
PatchLocation Patch, DebugDieValuePool &AddrPool) override;

/// Emit debug ranges(.debug_loc, .debug_loclists) footer.
void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
Expand Down Expand Up @@ -217,7 +223,8 @@ class DwarfStreamer : public DwarfEmitter {
/// Emit piece of .debug_rnglists for \p LinkedRanges.
void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit,
const AddressRanges &LinkedRanges,
PatchLocation Patch);
PatchLocation Patch,
DebugDieValuePool &AddrPool);

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

/// \defgroup Line table emission
/// @{
Expand Down Expand Up @@ -288,6 +295,7 @@ class DwarfStreamer : public DwarfEmitter {
uint64_t MacInfoSectionSize = 0;
uint64_t MacroSectionSize = 0;
uint64_t AddrSectionSize = 0;
uint64_t StrOffsetSectionSize = 0;

/// Keep track of emitted CUs and their Unique ID.
struct EmittedUnit {
Expand Down
67 changes: 46 additions & 21 deletions llvm/lib/DWARFLinker/DWARFLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,32 +1014,36 @@ void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) {
unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
AttributeSpec AttrSpec,
const DWARFFormValue &Val,
const DWARFUnit &,
const DWARFUnit &U,
AttributesInfo &Info) {
std::optional<const char *> String = dwarf::toString(Val);
if (!String)
return 0;

DwarfStringPoolEntryRef StringEntry;
if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
StringEntry = DebugLineStrPool.getEntry(*String);
} else {
StringEntry = DebugStrPool.getEntry(*String);

// Update attributes info.
if (AttrSpec.Attr == dwarf::DW_AT_name)
Info.Name = StringEntry;
else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
AttrSpec.Attr == dwarf::DW_AT_linkage_name)
Info.MangledName = StringEntry;

if (U.getVersion() >= 5) {
// Switch everything to DW_FORM_strx strings.
auto StringOffsetIndex =
StringOffsetPool.getValueIndex(StringEntry.getOffset());
return Die
.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex))
->sizeOf(U.getFormParams());
}
// Switch everything to out of line strings.
AttrSpec.Form = dwarf::DW_FORM_strp;
}

Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form,
DIEInteger(StringEntry.getOffset()));

return 4;
}

Expand Down Expand Up @@ -1359,7 +1363,7 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
return Unit.getOrigUnit().getAddressByteSize();
}

auto AddrIndex = AddrPool.getAddrIndex(*Addr);
auto AddrIndex = AddrPool.getValueIndex(*Addr);

return Die
.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
Expand Down Expand Up @@ -1391,6 +1395,17 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
}
}

if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
// DWARFLinker generates common .debug_str_offsets table used for all
// compile units. The offset to the common .debug_str_offsets table is 8 on
// DWARF32.
Info.AttrStrOffsetBaseSeen = true;
return Die
.addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
dwarf::DW_FORM_sec_offset, DIEInteger(8))
->sizeOf(Unit.getOrigUnit().getFormParams());
}

if (LLVM_UNLIKELY(Linker.Options.Update)) {
if (auto OptionalValue = Val.getAsUnsignedConstant())
Value = *OptionalValue;
Expand Down Expand Up @@ -1608,9 +1623,6 @@ shouldSkipAttribute(bool Update,
// Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
// DW_AT_rnglists_base is removed.
return !Update;
case dwarf::DW_AT_str_offsets_base:
// FIXME: Use the string offset table with Dwarf 5.
return true;
case dwarf::DW_AT_loclists_base:
// In case !Update the .debug_addr table is not generated/preserved.
// Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
Expand Down Expand Up @@ -1777,6 +1789,14 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
}
}

if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen &&
Die->getTag() == dwarf::DW_TAG_compile_unit) {
// No DW_AT_str_offsets_base seen, add it to the DIE.
Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base,
dwarf::DW_FORM_sec_offset, DIEInteger(8));
OutOffset += 4;
}

DIEAbbrev NewAbbrev = Die->generateAbbrev();
if (HasChildren)
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
Expand Down Expand Up @@ -1812,8 +1832,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
/// Patch the input object file relevant debug_ranges or debug_rnglists
/// entries and emit them in the output file. Update the relevant attributes
/// to point at the new entries.
void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
const DWARFFile &File) const {
void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
DebugDieValuePool &AddrPool) const {
if (LLVM_UNLIKELY(Options.Update))
return;

Expand Down Expand Up @@ -1866,14 +1886,14 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit,
}

// Emit linked ranges.
TheDwarfEmitter->emitDwarfDebugRangeListFragment(Unit, LinkedRanges,
AttributePatch);
TheDwarfEmitter->emitDwarfDebugRangeListFragment(
Unit, LinkedRanges, AttributePatch, AddrPool);
}

// Emit ranges for Unit AT_ranges attribute.
if (UnitRngListAttribute.has_value())
TheDwarfEmitter->emitDwarfDebugRangeListFragment(
Unit, LinkedFunctionRanges, *UnitRngListAttribute);
Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);

// Emit ranges footer.
TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
Expand Down Expand Up @@ -1955,13 +1975,14 @@ void DWARFLinker::DIECloner::emitDebugAddrSection(
if (DwarfVersion < 5)
return;

if (AddrPool.Addrs.empty())
if (AddrPool.DieValues.empty())
return;

MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);
patchAddrBase(*Unit.getOutputUnitDIE(),
DIEInteger(Emitter->getDebugAddrSectionSize()));
Emitter->emitDwarfDebugAddrs(AddrPool.Addrs, Unit.getOrigUnit().getAddressByteSize());
Emitter->emitDwarfDebugAddrs(AddrPool.DieValues,
Unit.getOrigUnit().getAddressByteSize());
Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
}

Expand Down Expand Up @@ -2515,7 +2536,7 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
if (LLVM_UNLIKELY(Linker.Options.Update))
continue;

Linker.generateUnitRanges(*CurrentUnit, File);
Linker.generateUnitRanges(*CurrentUnit, File, AddrPool);

auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
SmallVectorImpl<uint8_t> &OutBytes,
Expand Down Expand Up @@ -2612,6 +2633,7 @@ Error DWARFLinker::link() {
// reproducibility.
OffsetsStringPool DebugStrPool(StringsTranslator, true);
OffsetsStringPool DebugLineStrPool(StringsTranslator, false);
DebugDieValuePool StringOffsetPool;

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

for (auto &CU : OptContext.ModuleUnits) {
if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool,
DebugLineStrPool))
DebugLineStrPool, StringOffsetPool))
reportWarning(toString(std::move(Err)), CU.File);
}
}
Expand Down Expand Up @@ -2772,7 +2794,7 @@ Error DWARFLinker::link() {
SizeByObject[OptContext.File.FileName].Output =
DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc,
OptContext.CompileUnits, Options.Update, DebugStrPool,
DebugLineStrPool)
DebugLineStrPool, StringOffsetPool)
.cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
OptContext.File.Dwarf->isLittleEndian());
}
Expand All @@ -2789,6 +2811,8 @@ Error DWARFLinker::link() {
if (TheDwarfEmitter != nullptr) {
TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
TheDwarfEmitter->emitStrings(DebugStrPool);
TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues,
Options.TargetDWARFVersion);
TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
for (AccelTableKind TableKind : Options.AccelTables) {
switch (TableKind) {
Expand Down Expand Up @@ -2905,6 +2929,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
DeclContextTree &ODRContexts,
OffsetsStringPool &DebugStrPool,
OffsetsStringPool &DebugLineStrPool,
DebugDieValuePool &StringOffsetPool,
unsigned Indent) {
assert(Unit.Unit.get() != nullptr);

Expand All @@ -2931,7 +2956,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
CompileUnits.emplace_back(std::move(Unit.Unit));
assert(TheDwarfEmitter);
DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits,
Options.Update, DebugStrPool, DebugLineStrPool)
Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
.cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
Unit.File.Dwarf->isLittleEndian());
return Error::success();
Expand Down
Loading