Skip to content

[BOLT][DWARF] Add support for DW_IDX_parent #85285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 15, 2024
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
8 changes: 7 additions & 1 deletion bolt/include/bolt/Core/DIEBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,13 @@ class DIEBuilder {
void updateReferences();

/// Update the Offset and Size of DIE, populate DebugNames table.
uint32_t finalizeDIEs(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
/// Along with current CU, and DIE being processed and the new DIE offset to
/// be updated, it takes in Parents vector that can be empty if this DIE has
/// no parents.
uint32_t
finalizeDIEs(DWARFUnit &CU, DIE &Die,
std::vector<std::optional<BOLTDWARF5AccelTableData *>> &Parents,
uint32_t &CurOffset);

void registerUnit(DWARFUnit &DU, bool NeedSort);

Expand Down
17 changes: 12 additions & 5 deletions bolt/include/bolt/Core/DebugNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class BOLTDWARF5AccelTableData : public DWARF5AccelTableData {
bool isTU() const { return DWARF5AccelTableData::isTU(); }
std::optional<unsigned> getSecondUnitID() const { return SecondUnitID; }

void setPatchOffset(uint64_t PatchOffset) { OffsetVal = PatchOffset; }
uint64_t getPatchOffset() const { return std::get<uint64_t>(OffsetVal); }

private:
std::optional<unsigned> SecondUnitID;
};
Expand All @@ -49,10 +52,12 @@ class DWARF5AcceleratorTable {
Abbrev->~DebugNamesAbbrev();
}
/// Add DWARF5 Accelerator table entry.
/// Input is DWARFUnit being processed, DIE that belongs to it, and potential
/// SkeletonCU if the Unit comes from a DWO section.
void addAccelTableEntry(DWARFUnit &Unit, const DIE &Die,
const std::optional<uint64_t> &DWOID);
/// Input is DWARFUnit being processed, DIE that belongs to it, potential
/// DWOID if the Unit comes from a DWO section, and potential parent entry.
std::optional<BOLTDWARF5AccelTableData *>
addAccelTableEntry(DWARFUnit &Unit, const DIE &Die,
const std::optional<uint64_t> &DWOID,
std::optional<BOLTDWARF5AccelTableData *> &Parent);
/// Set current unit being processed.
void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset);
/// Emit Accelerator table.
Expand Down Expand Up @@ -121,6 +126,8 @@ class DWARF5AcceleratorTable {
llvm::DenseMap<llvm::hash_code, uint64_t> StrCacheToOffsetMap;
// Contains DWO ID to CUList Index.
llvm::DenseMap<uint64_t, uint32_t> CUOffsetsToPatch;
// Contains a map of Entry ID to Entry relative offset.
llvm::DenseMap<uint64_t, uint32_t> EntryRelativeOffsets;
/// Adds Unit to either CUList, LocalTUList or ForeignTUList.
/// Input Unit being processed, and DWO ID if Unit is being processed comes
/// from a DWO section.
Expand All @@ -143,7 +150,7 @@ class DWARF5AcceleratorTable {
/// Write Entries.
void writeEntries();
/// Write an Entry.
void writeEntry(const BOLTDWARF5AccelTableData &Entry);
void writeEntry(BOLTDWARF5AccelTableData &Entry);
/// Write augmentation_string for BOLT.
void writeAugmentationString();
/// Emit out Header for DWARF5 Accelerator table.
Expand Down
28 changes: 22 additions & 6 deletions bolt/lib/Core/DIEBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,20 +377,32 @@ getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx,
return nullptr;
}

uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die,
uint32_t &CurOffset) {
uint32_t DIEBuilder::finalizeDIEs(
DWARFUnit &CU, DIE &Die,
std::vector<std::optional<BOLTDWARF5AccelTableData *>> &Parents,
uint32_t &CurOffset) {
getState().DWARFDieAddressesParsed.erase(Die.getOffset());
uint32_t CurSize = 0;
Die.setOffset(CurOffset);
DebugNamesTable.addAccelTableEntry(
CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt);
std::optional<BOLTDWARF5AccelTableData *> NameEntry =
DebugNamesTable.addAccelTableEntry(
CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt,
Parents.back());
// It is possible that an indexed debugging information entry has a parent
// that is not indexed (for example, if its parent does not have a name
// attribute). In such a case, a parent attribute may point to a nameless
// index entry (that is, one that cannot be reached from any entry in the name
// table), or it may point to the nearest ancestor that does have an index
// entry.
if (NameEntry)
Parents.push_back(std::move(NameEntry));
for (DIEValue &Val : Die.values())
CurSize += Val.sizeOf(CU.getFormParams());
CurSize += getULEB128Size(Die.getAbbrevNumber());
CurOffset += CurSize;

for (DIE &Child : Die.children()) {
uint32_t ChildSize = finalizeDIEs(CU, Child, CurOffset);
uint32_t ChildSize = finalizeDIEs(CU, Child, Parents, CurOffset);
CurSize += ChildSize;
}
// for children end mark.
Expand All @@ -400,6 +412,8 @@ uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die,
}

Die.setSize(CurSize);
if (NameEntry)
Parents.pop_back();

return CurSize;
}
Expand All @@ -410,7 +424,9 @@ void DIEBuilder::finish() {
uint32_t HeaderSize = CU.getHeaderSize();
uint32_t CurOffset = HeaderSize;
DebugNamesTable.setCurrentUnit(CU, UnitStartOffset);
finalizeDIEs(CU, *UnitDIE, CurOffset);
std::vector<std::optional<BOLTDWARF5AccelTableData *>> Parents;
Parents.push_back(std::nullopt);
finalizeDIEs(CU, *UnitDIE, Parents, CurOffset);

DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU);
CurUnitInfo.UnitOffset = UnitStartOffset;
Expand Down
83 changes: 71 additions & 12 deletions bolt/lib/Core/DebugNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/LEB128.h"
#include <cstdint>
#include <optional>

namespace llvm {
namespace bolt {
Expand Down Expand Up @@ -163,10 +164,16 @@ static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit,
Index * DwarfOffsetByteSize);
}

void DWARF5AcceleratorTable::addAccelTableEntry(
DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID) {
static uint64_t getEntryID(const BOLTDWARF5AccelTableData &Entry) {
return reinterpret_cast<uint64_t>(&Entry);
}

std::optional<BOLTDWARF5AccelTableData *>
DWARF5AcceleratorTable::addAccelTableEntry(
DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID,
std::optional<BOLTDWARF5AccelTableData *> &Parent) {
if (Unit.getVersion() < 5 || !NeedToCreate)
return;
return std::nullopt;
std::string NameToUse = "";
auto canProcess = [&](const DIE &Die) -> bool {
switch (Die.getTag()) {
Expand Down Expand Up @@ -217,7 +224,7 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
};

if (!canProcess(Die))
return;
return std::nullopt;

// Addes a Unit to either CU, LocalTU or ForeignTU list the first time we
// encounter it.
Expand All @@ -227,10 +234,11 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
addUnit(Unit, DWOID);
}

auto addEntry = [&](DIEValue ValName) -> void {
auto addEntry =
[&](DIEValue ValName) -> std::optional<BOLTDWARF5AccelTableData *> {
if ((!ValName || ValName.getForm() == dwarf::DW_FORM_string) &&
NameToUse.empty())
return;
return std::nullopt;
std::string Name = "";
uint64_t NameIndexOffset = 0;
if (NameToUse.empty()) {
Expand Down Expand Up @@ -275,13 +283,23 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
<< ".\n";
SecondIndex = Iter->second;
}
std::optional<uint64_t> ParentOffset =
(Parent ? std::optional<uint64_t>(getEntryID(**Parent)) : std::nullopt);
// This will be populated later in writeEntry.
// This way only parent entries get tracked.
// Keeping memory footprint down.
if (ParentOffset)
EntryRelativeOffsets.insert({*ParentOffset, 0});
It.Values.push_back(new (Allocator) BOLTDWARF5AccelTableData(
Die.getOffset(), std::nullopt, DieTag, UnitID, IsTU, SecondIndex));
Die.getOffset(), ParentOffset, DieTag, UnitID, IsTU, SecondIndex));
return It.Values.back();
};

addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name));
addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name));
return;
std::optional<BOLTDWARF5AccelTableData *> NameEntry =
addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name));
std::optional<BOLTDWARF5AccelTableData *> LinkageNameEntry =
addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name));
return NameEntry ? NameEntry : LinkageNameEntry;
}

/// Algorithm from llvm implementation.
Expand Down Expand Up @@ -382,6 +400,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
if (SecondEntryRet)
Abbrev.addAttribute(SecondEntryRet->Encoding);
Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
if (std::optional<uint64_t> Offset = Value->getParentDieOffset())
Abbrev.addAttribute({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
else
Abbrev.addAttribute(
{dwarf::DW_IDX_parent, dwarf::DW_FORM_flag_present});
FoldingSetNodeID ID;
Abbrev.Profile(ID);
void *InsertPos;
Expand All @@ -401,7 +424,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
}
}

void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
void DWARF5AcceleratorTable::writeEntry(BOLTDWARF5AccelTableData &Entry) {
const uint64_t EntryID = getEntryID(Entry);
if (EntryRelativeOffsets.find(EntryID) != EntryRelativeOffsets.end())
EntryRelativeOffsets[EntryID] = EntriesBuffer->size();

const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
getIndexForEntry(Entry);
// For forgeign type (FTU) units that need to refer to the FTU and to the CU.
Expand Down Expand Up @@ -456,6 +483,17 @@ void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
llvm::endianness::little);
break;
}
case dwarf::DW_IDX_parent: {
assert(
(AttrEnc.Form == dwarf::DW_FORM_ref4 && Entry.getParentDieOffset()) ||
AttrEnc.Form == dwarf::DW_FORM_flag_present);
if (std::optional<uint64_t> ParentOffset = Entry.getParentDieOffset()) {
Entry.setPatchOffset(EntriesBuffer->size());
support::endian::write(*Entriestream, static_cast<uint32_t>(UINT32_MAX),
llvm::endianness::little);
}
break;
}
}
}
}
Expand All @@ -464,13 +502,34 @@ void DWARF5AcceleratorTable::writeEntries() {
for (auto &Bucket : getBuckets()) {
for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
Hash->EntryOffset = EntriesBuffer->size();
for (const BOLTDWARF5AccelTableData *Value : Hash->Values) {
for (BOLTDWARF5AccelTableData *Value : Hash->Values) {
writeEntry(*Value);
}
support::endian::write(*Entriestream, static_cast<uint8_t>(0),
llvm::endianness::little);
}
}
// Patching parent offsets.
for (auto &Bucket : getBuckets()) {
for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
for (BOLTDWARF5AccelTableData *Entry : Hash->Values) {
std::optional<uint64_t> ParentOffset = Entry->getParentDieOffset();
if (!ParentOffset)
continue;
if (const auto Iter = EntryRelativeOffsets.find(*ParentOffset);
Iter != EntryRelativeOffsets.end()) {
const uint64_t PatchOffset = Entry->getPatchOffset();
uint32_t *Ptr = reinterpret_cast<uint32_t *>(
&EntriesBuffer.get()->data()[PatchOffset]);
*Ptr = Iter->second;
} else {
BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find "
"entry with offset "
<< *ParentOffset << "\n";
}
}
}
}
}

void DWARF5AcceleratorTable::writeAugmentationString() {
Expand Down
16 changes: 14 additions & 2 deletions bolt/test/X86/dwarf5-debug-names-generate-debug-names.test
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit
; BOLT: Name Index @ 0x0 {
; BOLT-NEXT: Header {
; BOLT-NEXT: Length: 0x103
; BOLT-NEXT: Length: 0x109
; BOLT-NEXT: Format: DWARF32
; BOLT-NEXT: Version: 5
; BOLT-NEXT: CU count: 2
; BOLT-NEXT: Local TU count: 0
; BOLT-NEXT: Foreign TU count: 0
; BOLT-NEXT: Bucket count: 8
; BOLT-NEXT: Name count: 8
; BOLT-NEXT: Abbreviations table size: 0x19
; BOLT-NEXT: Abbreviations table size: 0x1F
; BOLT-NEXT: Augmentation: 'BOLT'
; BOLT-NEXT: }
; BOLT-NEXT: Compilation Unit offsets [
Expand All @@ -34,16 +34,19 @@
; BOLT-NEXT: Tag: DW_TAG_base_type
; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present
; BOLT-NEXT: }
; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present
; BOLT-NEXT: }
; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
; BOLT-NEXT: Tag: DW_TAG_variable
; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present
; BOLT-NEXT: }
; BOLT-NEXT: ]
; BOLT-NEXT: Bucket 0 [
Expand All @@ -55,12 +58,14 @@
; BOLT-NEXT: Tag: DW_TAG_base_type
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
; BOLT-NEXT: DW_IDX_die_offset: 0x00000033
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: Entry @ {{.+}} {
; BOLT-NEXT: Abbrev: [[ABBREV1]]
; BOLT-NEXT: Tag: DW_TAG_base_type
; BOLT-NEXT: DW_IDX_compile_unit: 0x00
; BOLT-NEXT: DW_IDX_die_offset: 0x0000007f
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: ]
Expand All @@ -73,6 +78,7 @@
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: Name 3 {
Expand All @@ -83,6 +89,7 @@
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: 0x00
; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: ]
Expand All @@ -95,6 +102,7 @@
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: 0x00
; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: Name 5 {
Expand All @@ -105,6 +113,7 @@
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: 0x00
; BOLT-NEXT: DW_IDX_die_offset: 0x00000049
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: Name 6 {
Expand All @@ -115,6 +124,7 @@
; BOLT-NEXT: Tag: DW_TAG_variable
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: ]
Expand All @@ -127,6 +137,7 @@
; BOLT-NEXT: Tag: DW_TAG_base_type
; BOLT-NEXT: DW_IDX_compile_unit: 0x00
; BOLT-NEXT: DW_IDX_die_offset: 0x00000092
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: ]
Expand All @@ -145,6 +156,7 @@
; BOLT-NEXT: Tag: DW_TAG_subprogram
; BOLT-NEXT: DW_IDX_compile_unit: 0x01
; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e
; BOLT-NEXT: DW_IDX_parent: <parent not indexed>
; BOLT-NEXT: }
; BOLT-NEXT: }
; BOLT-NEXT: ]
Expand Down
Loading