Skip to content

Commit 61589b8

Browse files
authored
[BOLT][DWARF] Fix parent chain in debug_names entries with forward declaration. (#93865)
Previously when an entry was skipped in parent chain a child will point to the next valid entry in the chain. After discussion in #91808 this is not very useful. Changed implemenation so that all the children of the entry that is skipped won't have DW_IDX_parent.
1 parent baa6609 commit 61589b8

File tree

5 files changed

+743
-19
lines changed

5 files changed

+743
-19
lines changed

bolt/include/bolt/Core/DIEBuilder.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,9 @@ class DIEBuilder {
215215
/// Along with current CU, and DIE being processed and the new DIE offset to
216216
/// be updated, it takes in Parents vector that can be empty if this DIE has
217217
/// no parents.
218-
uint32_t
219-
finalizeDIEs(DWARFUnit &CU, DIE &Die,
220-
std::vector<std::optional<BOLTDWARF5AccelTableData *>> &Parents,
221-
uint32_t &CurOffset);
218+
uint32_t finalizeDIEs(DWARFUnit &CU, DIE &Die,
219+
std::optional<BOLTDWARF5AccelTableData *> Parent,
220+
uint32_t NumberParentsInChain, uint32_t &CurOffset);
222221

223222
void registerUnit(DWARFUnit &DU, bool NeedSort);
224223

bolt/include/bolt/Core/DebugNames.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,25 @@ class BOLTDWARF5AccelTableData : public DWARF5AccelTableData {
2424
BOLTDWARF5AccelTableData(const uint64_t DieOffset,
2525
const std::optional<uint64_t> DefiningParentOffset,
2626
const unsigned DieTag, const unsigned UnitID,
27-
const bool IsTU,
27+
const bool IsParentRoot, const bool IsTU,
2828
const std::optional<unsigned> SecondUnitID)
2929
: DWARF5AccelTableData(DieOffset, DefiningParentOffset, DieTag, UnitID,
3030
IsTU),
31-
SecondUnitID(SecondUnitID) {}
31+
SecondUnitID(SecondUnitID), IsParentRoot(IsParentRoot) {}
3232

3333
uint64_t getDieOffset() const { return DWARF5AccelTableData::getDieOffset(); }
3434
unsigned getDieTag() const { return DWARF5AccelTableData::getDieTag(); }
3535
unsigned getUnitID() const { return DWARF5AccelTableData::getUnitID(); }
3636
bool isTU() const { return DWARF5AccelTableData::isTU(); }
37+
bool isParentRoot() const { return IsParentRoot; }
3738
std::optional<unsigned> getSecondUnitID() const { return SecondUnitID; }
3839

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

4243
private:
4344
std::optional<unsigned> SecondUnitID;
45+
bool IsParentRoot;
4446
};
4547

4648
class DWARF5AcceleratorTable {
@@ -57,6 +59,7 @@ class DWARF5AcceleratorTable {
5759
std::optional<BOLTDWARF5AccelTableData *>
5860
addAccelTableEntry(DWARFUnit &Unit, const DIE &Die,
5961
const std::optional<uint64_t> &DWOID,
62+
const uint32_t NumberParentsInChain,
6063
std::optional<BOLTDWARF5AccelTableData *> &Parent);
6164
/// Set current unit being processed.
6265
void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset);

bolt/lib/Core/DIEBuilder.cpp

+18-11
Original file line numberDiff line numberDiff line change
@@ -461,32 +461,42 @@ getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx,
461461
return nullptr;
462462
}
463463

464-
uint32_t DIEBuilder::finalizeDIEs(
465-
DWARFUnit &CU, DIE &Die,
466-
std::vector<std::optional<BOLTDWARF5AccelTableData *>> &Parents,
467-
uint32_t &CurOffset) {
464+
uint32_t
465+
DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die,
466+
std::optional<BOLTDWARF5AccelTableData *> Parent,
467+
uint32_t NumberParentsInChain, uint32_t &CurOffset) {
468468
getState().DWARFDieAddressesParsed.erase(Die.getOffset());
469469
uint32_t CurSize = 0;
470470
Die.setOffset(CurOffset);
471471
std::optional<BOLTDWARF5AccelTableData *> NameEntry =
472472
DebugNamesTable.addAccelTableEntry(
473473
CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt,
474-
Parents.back());
474+
NumberParentsInChain, Parent);
475475
// It is possible that an indexed debugging information entry has a parent
476476
// that is not indexed (for example, if its parent does not have a name
477477
// attribute). In such a case, a parent attribute may point to a nameless
478478
// index entry (that is, one that cannot be reached from any entry in the name
479479
// table), or it may point to the nearest ancestor that does have an index
480480
// entry.
481+
// Skipping entry is not very useful for LLDB. This follows clang where
482+
// children of forward declaration won't have DW_IDX_parent.
483+
// https://github.com/llvm/llvm-project/pull/91808
484+
485+
// If Parent is nullopt and NumberParentsInChain is not zero, then forward
486+
// declaration was encountered in this DF traversal. Propagating nullopt for
487+
// Parent to children.
488+
if (!Parent && NumberParentsInChain)
489+
NameEntry = std::nullopt;
481490
if (NameEntry)
482-
Parents.push_back(std::move(NameEntry));
491+
++NumberParentsInChain;
483492
for (DIEValue &Val : Die.values())
484493
CurSize += Val.sizeOf(CU.getFormParams());
485494
CurSize += getULEB128Size(Die.getAbbrevNumber());
486495
CurOffset += CurSize;
487496

488497
for (DIE &Child : Die.children()) {
489-
uint32_t ChildSize = finalizeDIEs(CU, Child, Parents, CurOffset);
498+
uint32_t ChildSize =
499+
finalizeDIEs(CU, Child, NameEntry, NumberParentsInChain, CurOffset);
490500
CurSize += ChildSize;
491501
}
492502
// for children end mark.
@@ -496,9 +506,6 @@ uint32_t DIEBuilder::finalizeDIEs(
496506
}
497507

498508
Die.setSize(CurSize);
499-
if (NameEntry)
500-
Parents.pop_back();
501-
502509
return CurSize;
503510
}
504511

@@ -510,7 +517,7 @@ void DIEBuilder::finish() {
510517
DebugNamesTable.setCurrentUnit(CU, UnitStartOffset);
511518
std::vector<std::optional<BOLTDWARF5AccelTableData *>> Parents;
512519
Parents.push_back(std::nullopt);
513-
finalizeDIEs(CU, *UnitDIE, Parents, CurOffset);
520+
finalizeDIEs(CU, *UnitDIE, std::nullopt, 0, CurOffset);
514521

515522
DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU);
516523
CurUnitInfo.UnitOffset = UnitStartOffset;

bolt/lib/Core/DebugNames.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ static uint64_t getEntryID(const BOLTDWARF5AccelTableData &Entry) {
220220
std::optional<BOLTDWARF5AccelTableData *>
221221
DWARF5AcceleratorTable::addAccelTableEntry(
222222
DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID,
223+
const uint32_t NumberParentsInChain,
223224
std::optional<BOLTDWARF5AccelTableData *> &Parent) {
224225
if (Unit.getVersion() < 5 || !NeedToCreate)
225226
return std::nullopt;
@@ -312,8 +313,14 @@ DWARF5AcceleratorTable::addAccelTableEntry(
312313
// Keeping memory footprint down.
313314
if (ParentOffset)
314315
EntryRelativeOffsets.insert({*ParentOffset, 0});
316+
bool IsParentRoot = false;
317+
// If there is no parent and no valid Entries in parent chain this is a root
318+
// to be marked with a flag.
319+
if (!Parent && !NumberParentsInChain)
320+
IsParentRoot = true;
315321
It.Values.push_back(new (Allocator) BOLTDWARF5AccelTableData(
316-
Die.getOffset(), ParentOffset, DieTag, UnitID, IsTU, SecondIndex));
322+
Die.getOffset(), ParentOffset, DieTag, UnitID, IsParentRoot, IsTU,
323+
SecondIndex));
317324
return It.Values.back();
318325
};
319326

@@ -462,7 +469,7 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
462469
Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
463470
if (std::optional<uint64_t> Offset = Value->getParentDieOffset())
464471
Abbrev.addAttribute({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
465-
else
472+
else if (Value->isParentRoot())
466473
Abbrev.addAttribute(
467474
{dwarf::DW_IDX_parent, dwarf::DW_FORM_flag_present});
468475
FoldingSetNodeID ID;

0 commit comments

Comments
 (0)