Skip to content

Commit 88c5df3

Browse files
sayhaanyuxuanchen1997
authored andcommitted
[BOLT][DWARF][NFC] Refactor address writers (#98094)
Summary: Refactors address writers to create an instance for each CU and its DWO CU. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251470
1 parent 62c8d22 commit 88c5df3

File tree

5 files changed

+165
-117
lines changed

5 files changed

+165
-117
lines changed

bolt/include/bolt/Core/DebugData.h

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class DebugRangeListsSectionWriter : public DebugRangesSectionWriter {
256256
};
257257
virtual ~DebugRangeListsSectionWriter(){};
258258

259-
static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
259+
void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
260260

261261
/// Add ranges with caching.
262262
uint64_t addRanges(
@@ -284,7 +284,7 @@ class DebugRangeListsSectionWriter : public DebugRangesSectionWriter {
284284
}
285285

286286
private:
287-
static DebugAddrWriter *AddrWriter;
287+
DebugAddrWriter *AddrWriter = nullptr;
288288
/// Used to find unique CU ID.
289289
DWARFUnit *CU;
290290
/// Current relative offset of range list entry within this CUs rangelist
@@ -336,21 +336,36 @@ using AddressSectionBuffer = SmallVector<char, 4>;
336336
class DebugAddrWriter {
337337
public:
338338
DebugAddrWriter() = delete;
339-
DebugAddrWriter(BinaryContext *BC_);
339+
DebugAddrWriter(BinaryContext *BC_) : DebugAddrWriter(BC_, UCHAR_MAX) {};
340+
DebugAddrWriter(BinaryContext *BC_, uint8_t AddressByteSize);
340341
virtual ~DebugAddrWriter(){};
341342
/// Given an address returns an index in .debug_addr.
342343
/// Adds Address to map.
343344
uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU);
344345

345346
/// Write out entries in to .debug_addr section for CUs.
346-
virtual void update(DIEBuilder &DIEBlder, DWARFUnit &CUs);
347+
virtual std::optional<uint64_t> finalize(const size_t BufferSize);
347348

348349
/// Return buffer with all the entries in .debug_addr already writen out using
349350
/// update(...).
350-
virtual AddressSectionBuffer &finalize() { return *Buffer; }
351+
virtual std::unique_ptr<AddressSectionBuffer> releaseBuffer() {
352+
return std::move(Buffer);
353+
}
354+
355+
/// Returns buffer size.
356+
virtual size_t getBufferSize() const { return Buffer->size(); }
357+
358+
/// Returns True if Buffer is not empty.
359+
bool isInitialized() const { return !Buffer->empty(); }
351360

352-
/// Returns False if .debug_addr section was created..
353-
bool isInitialized() const { return !AddressMaps.empty(); }
361+
/// Updates address base with the given Offset.
362+
virtual void updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
363+
const uint64_t Offset);
364+
365+
/// Appends an AddressSectionBuffer to the address writer's buffer.
366+
void appendToAddressBuffer(const AddressSectionBuffer &Buffer) {
367+
*AddressStream << Buffer;
368+
}
354369

355370
protected:
356371
class AddressForDWOCU {
@@ -407,23 +422,32 @@ class DebugAddrWriter {
407422
}
408423

409424
BinaryContext *BC;
410-
/// Maps DWOID to AddressForDWOCU.
411-
std::unordered_map<uint64_t, AddressForDWOCU> AddressMaps;
425+
/// Address for the DWO CU associated with the address writer.
426+
AddressForDWOCU Map;
427+
uint8_t AddressByteSize;
412428
/// Mutex used for parallel processing of debug info.
413429
std::mutex WriterMutex;
414430
std::unique_ptr<AddressSectionBuffer> Buffer;
415431
std::unique_ptr<raw_svector_ostream> AddressStream;
416432
/// Used to track sections that were not modified so that they can be re-used.
417-
DenseMap<uint64_t, uint64_t> UnmodifiedAddressOffsets;
433+
static DenseMap<uint64_t, uint64_t> UnmodifiedAddressOffsets;
418434
};
419435

420436
class DebugAddrWriterDwarf5 : public DebugAddrWriter {
421437
public:
422438
DebugAddrWriterDwarf5() = delete;
423439
DebugAddrWriterDwarf5(BinaryContext *BC) : DebugAddrWriter(BC) {}
440+
DebugAddrWriterDwarf5(BinaryContext *BC, uint8_t AddressByteSize,
441+
std::optional<uint64_t> AddrOffsetSectionBase)
442+
: DebugAddrWriter(BC, AddressByteSize),
443+
AddrOffsetSectionBase(AddrOffsetSectionBase) {}
424444

425445
/// Write out entries in to .debug_addr section for CUs.
426-
virtual void update(DIEBuilder &DIEBlder, DWARFUnit &CUs) override;
446+
virtual std::optional<uint64_t> finalize(const size_t BufferSize) override;
447+
448+
/// Updates address base with the given Offset.
449+
virtual void updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
450+
const uint64_t Offset) override;
427451

428452
protected:
429453
/// Given DWARFUnit \p Unit returns either DWO ID or it's offset within
@@ -435,6 +459,10 @@ class DebugAddrWriterDwarf5 : public DebugAddrWriter {
435459
}
436460
return Unit.getOffset();
437461
}
462+
463+
private:
464+
std::optional<uint64_t> AddrOffsetSectionBase = std::nullopt;
465+
static constexpr uint32_t HeaderSize = 8;
438466
};
439467

440468
/// This class is NOT thread safe.
@@ -583,12 +611,10 @@ class DebugLoclistWriter : public DebugLocWriter {
583611
public:
584612
~DebugLoclistWriter() {}
585613
DebugLoclistWriter() = delete;
586-
DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD)
587-
: DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), CU(Unit),
588-
IsSplitDwarf(SD) {
589-
assert(DebugLoclistWriter::AddrWriter &&
590-
"Please use SetAddressWriter to initialize "
591-
"DebugAddrWriter before instantiation.");
614+
DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD,
615+
DebugAddrWriter &AddrW)
616+
: DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter),
617+
AddrWriter(AddrW), CU(Unit), IsSplitDwarf(SD) {
592618
if (DwarfVersion >= 5) {
593619
LocBodyBuffer = std::make_unique<DebugBufferVector>();
594620
LocBodyStream = std::make_unique<raw_svector_ostream>(*LocBodyBuffer);
@@ -600,8 +626,6 @@ class DebugLoclistWriter : public DebugLocWriter {
600626
}
601627
}
602628

603-
static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
604-
605629
/// Stores location lists internally to be written out during finalize phase.
606630
virtual void addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
607631
DebugLocationsVector &LocList) override;
@@ -630,7 +654,7 @@ class DebugLoclistWriter : public DebugLocWriter {
630654
/// Writes out locations in to a local buffer and applies debug info patches.
631655
void finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die);
632656

633-
static DebugAddrWriter *AddrWriter;
657+
DebugAddrWriter &AddrWriter;
634658
DWARFUnit &CU;
635659
bool IsSplitDwarf{false};
636660
// Used for DWARF5 to store location lists before being finalized.

bolt/include/bolt/Rewrite/DWARFRewriter.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ class DWARFRewriter {
6666
/// .debug_aranges DWARF section.
6767
std::unique_ptr<DebugARangesSectionWriter> ARangesSectionWriter;
6868

69-
/// Stores and serializes information that will be put into the
70-
/// .debug_addr DWARF section.
71-
std::unique_ptr<DebugAddrWriter> AddrWriter;
72-
7369
/// Stores and serializes information that will be put in to the
7470
/// .debug_addr DWARF section.
7571
/// Does not do de-duplication.
@@ -93,6 +89,10 @@ class DWARFRewriter {
9389
std::unordered_map<uint64_t, std::unique_ptr<DebugRangesSectionWriter>>
9490
LegacyRangesWritersByCU;
9591

92+
/// Stores address writer for each CU.
93+
std::unordered_map<uint64_t, std::unique_ptr<DebugAddrWriter>>
94+
AddressWritersByCU;
95+
9696
std::mutex LocListDebugInfoPatchesMutex;
9797

9898
/// Dwo id specific its RangesBase.
@@ -115,6 +115,7 @@ class DWARFRewriter {
115115
void updateUnitDebugInfo(DWARFUnit &Unit, DIEBuilder &DIEBldr,
116116
DebugLocWriter &DebugLocWriter,
117117
DebugRangesSectionWriter &RangesSectionWriter,
118+
DebugAddrWriter &AddressWriter,
118119
std::optional<uint64_t> RangesBase = std::nullopt);
119120

120121
/// Patches the binary for an object's address ranges to be updated.
@@ -141,13 +142,15 @@ class DWARFRewriter {
141142
/// Process and write out CUs that are passsed in.
142143
void finalizeCompileUnits(DIEBuilder &DIEBlder, DIEStreamer &Streamer,
143144
CUOffsetMap &CUMap,
144-
const std::list<DWARFUnit *> &CUs);
145+
const std::list<DWARFUnit *> &CUs,
146+
DebugAddrWriter &FinalAddrWriter);
145147

146148
/// Finalize debug sections in the main binary.
147149
void finalizeDebugSections(DIEBuilder &DIEBlder,
148150
DWARF5AcceleratorTable &DebugNamesTable,
149151
DIEStreamer &Streamer, raw_svector_ostream &ObjOS,
150-
CUOffsetMap &CUMap);
152+
CUOffsetMap &CUMap,
153+
DebugAddrWriter &FinalAddrWriter);
151154

152155
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical
153156
/// blocks) to be updated.

bolt/lib/Core/DebugData.cpp

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,6 @@ void DebugRangesSectionWriter::appendToRangeBuffer(
184184
*RangesStream << CUBuffer;
185185
}
186186

187-
DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr;
188-
189187
uint64_t DebugRangeListsSectionWriter::addRanges(
190188
DebugAddressRangesVector &&Ranges,
191189
std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
@@ -390,7 +388,9 @@ void DebugARangesSectionWriter::writeARangesSection(
390388
}
391389
}
392390

393-
DebugAddrWriter::DebugAddrWriter(BinaryContext *BC) : BC(BC) {
391+
DebugAddrWriter::DebugAddrWriter(BinaryContext *BC,
392+
const uint8_t AddressByteSize)
393+
: BC(BC), AddressByteSize(AddressByteSize) {
394394
Buffer = std::make_unique<AddressSectionBuffer>();
395395
AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);
396396
}
@@ -405,11 +405,6 @@ void DebugAddrWriter::AddressForDWOCU::dump() {
405405
}
406406
uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
407407
std::lock_guard<std::mutex> Lock(WriterMutex);
408-
const uint64_t CUID = getCUID(CU);
409-
if (!AddressMaps.count(CUID))
410-
AddressMaps[CUID] = AddressForDWOCU();
411-
412-
AddressForDWOCU &Map = AddressMaps[CUID];
413408
auto Entry = Map.find(Address);
414409
if (Entry == Map.end()) {
415410
auto Index = Map.getNextIndex();
@@ -449,29 +444,23 @@ static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,
449444
}
450445
}
451446

452-
void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
453-
// Handling the case where debug information is a mix of Debug fission and
454-
// monolithic.
455-
if (!CU.getDWOId())
456-
return;
457-
const uint64_t CUID = getCUID(CU);
458-
auto AM = AddressMaps.find(CUID);
459-
// Adding to map even if it did not contribute to .debug_addr.
460-
// The Skeleton CU might still have DW_AT_GNU_addr_base.
461-
uint64_t Offset = Buffer->size();
462-
// If does not exist this CUs DWO section didn't contribute to .debug_addr.
463-
if (AM == AddressMaps.end())
464-
return;
465-
std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
466-
AM->second.indexToAdddessEnd());
447+
void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
448+
const uint64_t Offset) {
449+
updateAddressBase(DIEBlder, *this, CU, Offset);
450+
}
451+
452+
std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) {
453+
if (Map.begin() == Map.end())
454+
return std::nullopt;
455+
std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
456+
Map.indexToAdddessEnd());
467457
// Sorting address in increasing order of indices.
468458
llvm::sort(SortedMap, llvm::less_first());
469459

470-
uint8_t AddrSize = CU.getAddressByteSize();
471460
uint32_t Counter = 0;
472461
auto WriteAddress = [&](uint64_t Address) -> void {
473462
++Counter;
474-
switch (AddrSize) {
463+
switch (AddressByteSize) {
475464
default:
476465
assert(false && "Address Size is invalid.");
477466
break;
@@ -490,10 +479,19 @@ void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
490479
WriteAddress(0);
491480
WriteAddress(Val.second);
492481
}
493-
updateAddressBase(DIEBlder, *this, CU, Offset);
482+
return std::nullopt;
483+
}
484+
485+
void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
486+
const uint64_t Offset) {
487+
/// Header for DWARF5 has size 8, so we add it to the offset.
488+
updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize);
494489
}
495490

496-
void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
491+
DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;
492+
493+
std::optional<uint64_t>
494+
DebugAddrWriterDwarf5::finalize(const size_t BufferSize) {
497495
// Need to layout all sections within .debug_addr
498496
// Within each section sort Address by index.
499497
const endianness Endian = BC->DwCtx->isLittleEndian()
@@ -504,55 +502,44 @@ void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
504502
Endian == llvm::endianness::little, 0);
505503
DWARFDebugAddrTable AddrTable;
506504
DIDumpOptions DumpOpts;
507-
constexpr uint32_t HeaderSize = 8;
508-
const uint64_t CUID = getCUID(CU);
509-
const uint8_t AddrSize = CU.getAddressByteSize();
510-
auto AMIter = AddressMaps.find(CUID);
511505
// A case where CU has entry in .debug_addr, but we don't modify addresses
512506
// for it.
513-
if (AMIter == AddressMaps.end()) {
514-
AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
515-
std::optional<uint64_t> BaseOffset = CU.getAddrOffsetSectionBase();
516-
if (!BaseOffset)
517-
return;
507+
if (Map.begin() == Map.end()) {
508+
if (!AddrOffsetSectionBase)
509+
return std::nullopt;
518510
// Address base offset is to the first entry.
519511
// The size of header is 8 bytes.
520-
uint64_t Offset = *BaseOffset - HeaderSize;
512+
uint64_t Offset = *AddrOffsetSectionBase - HeaderSize;
521513
auto Iter = UnmodifiedAddressOffsets.find(Offset);
522-
if (Iter != UnmodifiedAddressOffsets.end()) {
523-
updateAddressBase(DIEBlder, *this, CU, Iter->getSecond());
524-
return;
525-
}
526-
UnmodifiedAddressOffsets[Offset] = Buffer->size() + HeaderSize;
527-
if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
514+
if (Iter != UnmodifiedAddressOffsets.end())
515+
return Iter->second;
516+
UnmodifiedAddressOffsets[Offset] = BufferSize;
517+
if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,
528518
DumpOpts.WarningHandler)) {
529519
DumpOpts.RecoverableErrorHandler(std::move(Err));
530-
return;
520+
return std::nullopt;
531521
}
532-
533522
uint32_t Index = 0;
534523
for (uint64_t Addr : AddrTable.getAddressEntries())
535-
AMIter->second.insert(Addr, Index++);
524+
Map.insert(Addr, Index++);
536525
}
537526

538-
updateAddressBase(DIEBlder, *this, CU, Buffer->size() + HeaderSize);
539-
540-
std::vector<IndexAddressPair> SortedMap(AMIter->second.indexToAddressBegin(),
541-
AMIter->second.indexToAdddessEnd());
527+
std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
528+
Map.indexToAdddessEnd());
542529
// Sorting address in increasing order of indices.
543530
llvm::sort(SortedMap, llvm::less_first());
544531
// Writing out Header
545-
const uint32_t Length = SortedMap.size() * AddrSize + 4;
532+
const uint32_t Length = SortedMap.size() * AddressByteSize + 4;
546533
support::endian::write(*AddressStream, Length, Endian);
547534
support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);
548-
support::endian::write(*AddressStream, static_cast<uint8_t>(AddrSize),
535+
support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize),
549536
Endian);
550537
support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);
551538

552539
uint32_t Counter = 0;
553540
auto writeAddress = [&](uint64_t Address) -> void {
554541
++Counter;
555-
switch (AddrSize) {
542+
switch (AddressByteSize) {
556543
default:
557544
llvm_unreachable("Address Size is invalid.");
558545
break;
@@ -571,6 +558,7 @@ void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
571558
writeAddress(0);
572559
writeAddress(Val.second);
573560
}
561+
return std::nullopt;
574562
}
575563

576564
void DebugLocWriter::init() {
@@ -723,11 +711,11 @@ void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,
723711
DIEValue &AttrInfo,
724712
DebugLocationsVector &LocList) {
725713
if (DwarfVersion < 5)
726-
writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer,
714+
writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer,
727715
CU, *LocStream);
728716
else
729717
writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
730-
*AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
718+
AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
731719
*LocBodyStream);
732720
}
733721

@@ -789,8 +777,6 @@ void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
789777
finalizeDWARF5(DIEBldr, Die);
790778
}
791779

792-
DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
793-
794780
static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
795781
std::string LE64(ByteSize, 0);
796782
for (size_t I = 0; I < ByteSize; ++I) {

0 commit comments

Comments
 (0)