13
13
#include " llvm/Support/EndianStream.h"
14
14
#include " llvm/Support/LEB128.h"
15
15
#include < cstdint>
16
+ #include < optional>
16
17
17
18
namespace llvm {
18
19
namespace bolt {
@@ -163,10 +164,16 @@ static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit,
163
164
Index * DwarfOffsetByteSize);
164
165
}
165
166
166
- void DWARF5AcceleratorTable::addAccelTableEntry (
167
- DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t > &DWOID) {
167
+ static uint64_t getEntryID (const BOLTDWARF5AccelTableData &Entry) {
168
+ return reinterpret_cast <uint64_t >(&Entry);
169
+ }
170
+
171
+ std::optional<BOLTDWARF5AccelTableData *>
172
+ DWARF5AcceleratorTable::addAccelTableEntry (
173
+ DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t > &DWOID,
174
+ std::optional<BOLTDWARF5AccelTableData *> &Parent) {
168
175
if (Unit.getVersion () < 5 || !NeedToCreate)
169
- return ;
176
+ return std::nullopt ;
170
177
std::string NameToUse = " " ;
171
178
auto canProcess = [&](const DIE &Die) -> bool {
172
179
switch (Die.getTag ()) {
@@ -217,7 +224,7 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
217
224
};
218
225
219
226
if (!canProcess (Die))
220
- return ;
227
+ return std::nullopt ;
221
228
222
229
// Addes a Unit to either CU, LocalTU or ForeignTU list the first time we
223
230
// encounter it.
@@ -227,10 +234,11 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
227
234
addUnit (Unit, DWOID);
228
235
}
229
236
230
- auto addEntry = [&](DIEValue ValName) -> void {
237
+ auto addEntry =
238
+ [&](DIEValue ValName) -> std::optional<BOLTDWARF5AccelTableData *> {
231
239
if ((!ValName || ValName.getForm () == dwarf::DW_FORM_string) &&
232
240
NameToUse.empty ())
233
- return ;
241
+ return std::nullopt ;
234
242
std::string Name = " " ;
235
243
uint64_t NameIndexOffset = 0 ;
236
244
if (NameToUse.empty ()) {
@@ -275,13 +283,23 @@ void DWARF5AcceleratorTable::addAccelTableEntry(
275
283
<< " .\n " ;
276
284
SecondIndex = Iter->second ;
277
285
}
286
+ std::optional<uint64_t > ParentOffset =
287
+ (Parent ? std::optional<uint64_t >(getEntryID (**Parent)) : std::nullopt);
288
+ // This will be populated later in writeEntry.
289
+ // This way only parent entries get tracked.
290
+ // Keeping memory footprint down.
291
+ if (ParentOffset)
292
+ EntryRelativeOffsets.insert ({*ParentOffset, 0 });
278
293
It.Values .push_back (new (Allocator) BOLTDWARF5AccelTableData (
279
- Die.getOffset (), std::nullopt, DieTag, UnitID, IsTU, SecondIndex));
294
+ Die.getOffset (), ParentOffset, DieTag, UnitID, IsTU, SecondIndex));
295
+ return It.Values .back ();
280
296
};
281
297
282
- addEntry (Die.findAttribute (dwarf::Attribute::DW_AT_name));
283
- addEntry (Die.findAttribute (dwarf::Attribute::DW_AT_linkage_name));
284
- return ;
298
+ std::optional<BOLTDWARF5AccelTableData *> NameEntry =
299
+ addEntry (Die.findAttribute (dwarf::Attribute::DW_AT_name));
300
+ std::optional<BOLTDWARF5AccelTableData *> LinkageNameEntry =
301
+ addEntry (Die.findAttribute (dwarf::Attribute::DW_AT_linkage_name));
302
+ return NameEntry ? NameEntry : LinkageNameEntry;
285
303
}
286
304
287
305
// / Algorithm from llvm implementation.
@@ -382,6 +400,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
382
400
if (SecondEntryRet)
383
401
Abbrev.addAttribute (SecondEntryRet->Encoding );
384
402
Abbrev.addAttribute ({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
403
+ if (std::optional<uint64_t > Offset = Value->getParentDieOffset ())
404
+ Abbrev.addAttribute ({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
405
+ else
406
+ Abbrev.addAttribute (
407
+ {dwarf::DW_IDX_parent, dwarf::DW_FORM_flag_present});
385
408
FoldingSetNodeID ID;
386
409
Abbrev.Profile (ID);
387
410
void *InsertPos;
@@ -401,7 +424,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() {
401
424
}
402
425
}
403
426
404
- void DWARF5AcceleratorTable::writeEntry (const BOLTDWARF5AccelTableData &Entry) {
427
+ void DWARF5AcceleratorTable::writeEntry (BOLTDWARF5AccelTableData &Entry) {
428
+ const uint64_t EntryID = getEntryID (Entry);
429
+ if (EntryRelativeOffsets.find (EntryID) != EntryRelativeOffsets.end ())
430
+ EntryRelativeOffsets[EntryID] = EntriesBuffer->size ();
431
+
405
432
const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
406
433
getIndexForEntry (Entry);
407
434
// For forgeign type (FTU) units that need to refer to the FTU and to the CU.
@@ -456,6 +483,17 @@ void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
456
483
llvm::endianness::little);
457
484
break ;
458
485
}
486
+ case dwarf::DW_IDX_parent: {
487
+ assert (
488
+ (AttrEnc.Form == dwarf::DW_FORM_ref4 && Entry.getParentDieOffset ()) ||
489
+ AttrEnc.Form == dwarf::DW_FORM_flag_present);
490
+ if (std::optional<uint64_t > ParentOffset = Entry.getParentDieOffset ()) {
491
+ Entry.setPatchOffset (EntriesBuffer->size ());
492
+ support::endian::write (*Entriestream, static_cast <uint32_t >(UINT32_MAX),
493
+ llvm::endianness::little);
494
+ }
495
+ break ;
496
+ }
459
497
}
460
498
}
461
499
}
@@ -464,13 +502,34 @@ void DWARF5AcceleratorTable::writeEntries() {
464
502
for (auto &Bucket : getBuckets ()) {
465
503
for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
466
504
Hash->EntryOffset = EntriesBuffer->size ();
467
- for (const BOLTDWARF5AccelTableData *Value : Hash->Values ) {
505
+ for (BOLTDWARF5AccelTableData *Value : Hash->Values ) {
468
506
writeEntry (*Value);
469
507
}
470
508
support::endian::write (*Entriestream, static_cast <uint8_t >(0 ),
471
509
llvm::endianness::little);
472
510
}
473
511
}
512
+ // Patching parent offsets.
513
+ for (auto &Bucket : getBuckets ()) {
514
+ for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
515
+ for (BOLTDWARF5AccelTableData *Entry : Hash->Values ) {
516
+ std::optional<uint64_t > ParentOffset = Entry->getParentDieOffset ();
517
+ if (!ParentOffset)
518
+ continue ;
519
+ if (const auto Iter = EntryRelativeOffsets.find (*ParentOffset);
520
+ Iter != EntryRelativeOffsets.end ()) {
521
+ const uint64_t PatchOffset = Entry->getPatchOffset ();
522
+ uint32_t *Ptr = reinterpret_cast <uint32_t *>(
523
+ &EntriesBuffer.get ()->data ()[PatchOffset]);
524
+ *Ptr = Iter->second ;
525
+ } else {
526
+ BC.errs () << " BOLT-WARNING: [internal-dwarf-warning]: Could not find "
527
+ " entry with offset "
528
+ << *ParentOffset << " \n " ;
529
+ }
530
+ }
531
+ }
532
+ }
474
533
}
475
534
476
535
void DWARF5AcceleratorTable::writeAugmentationString () {
0 commit comments