Skip to content

Commit ba1ac98

Browse files
committed
[BOLT][DWARF] Add version 5 split dwarf support
Added support for DWARF5 Split Dwarf. Reviewed By: maksfb Differential Revision: https://reviews.llvm.org/D122988
1 parent c4f95ef commit ba1ac98

22 files changed

+2063
-128
lines changed

bolt/include/bolt/Core/DebugData.h

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class DebugRangesSectionWriter {
155155
uint64_t getSectionOffset();
156156

157157
/// Returns a buffer containing Ranges.
158-
virtual std::unique_ptr<DebugBufferVector> finalize() {
158+
virtual std::unique_ptr<DebugBufferVector> releaseBuffer() {
159159
return std::move(RangesBuffer);
160160
}
161161

@@ -165,6 +165,12 @@ class DebugRangesSectionWriter {
165165
return Writer->getKind() == RangesWriterKind::DebugRangesWriter;
166166
}
167167

168+
/// Writes out range lists for a current CU being processed.
169+
void virtual finalizeSection(){};
170+
171+
/// Needs to be invoked before each \p CU is processed.
172+
void virtual initSection(DWARFUnit &CU){};
173+
168174
protected:
169175
std::unique_ptr<DebugBufferVector> RangesBuffer;
170176

@@ -203,25 +209,27 @@ class DebugRangeListsSectionWriter : public DebugRangesSectionWriter {
203209
/// Add ranges and return offset into section.
204210
virtual uint64_t addRanges(const DebugAddressRangesVector &Ranges) override;
205211

206-
virtual std::unique_ptr<DebugBufferVector> finalize() override {
212+
virtual std::unique_ptr<DebugBufferVector> releaseBuffer() override {
207213
return std::move(RangesBuffer);
208214
}
209215

210-
/// Needs to be invoked before each CU is processed.
211-
/// \p CUID is a unique ID of each CU.
212-
void initSection(uint64_t CUID);
216+
/// Needs to be invoked before each \p CU is processed.
217+
void virtual initSection(DWARFUnit &CU) override;
213218

214219
/// Writes out range lists for a current CU being processed.
215-
void finalizeSection();
220+
void virtual finalizeSection() override;
221+
222+
// Returns true if section is empty.
223+
bool empty() { return RangesBuffer->empty(); }
216224

217225
static bool classof(const DebugRangesSectionWriter *Writer) {
218226
return Writer->getKind() == RangesWriterKind::DebugRangeListsWriter;
219227
}
220228

221229
private:
222230
static DebugAddrWriter *AddrWriter;
223-
/// Unique ID of CU being processed.
224-
uint64_t CUID{0};
231+
/// Used to find unique CU ID.
232+
DWARFUnit *CU;
225233
/// Current relative offset of range list entry within this CUs rangelist
226234
/// body.
227235
uint32_t CurrentOffset{0};
@@ -275,10 +283,10 @@ class DebugAddrWriter {
275283
virtual ~DebugAddrWriter(){};
276284
/// Given an address returns an index in .debug_addr.
277285
/// Adds Address to map.
278-
uint32_t getIndexFromAddress(uint64_t Address, uint64_t CUID);
286+
uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU);
279287

280-
/// Adds {Address, Index} to DWO ID CU.
281-
void addIndexAddress(uint64_t Address, uint32_t Index, uint64_t CUID);
288+
/// Adds {\p Address, \p Index} to \p CU.
289+
void addIndexAddress(uint64_t Address, uint32_t Index, DWARFUnit &CU);
282290

283291
/// Creates consolidated .debug_addr section, and builds DWOID to offset map.
284292
virtual AddressSectionBuffer finalize();
@@ -338,6 +346,12 @@ class DebugAddrWriter {
338346
IndexToAddressMap IndexToAddress;
339347
uint32_t CurrentIndex{0};
340348
};
349+
350+
virtual uint64_t getCUID(DWARFUnit &Unit) {
351+
assert(Unit.getDWOId() && "Unit is not Skeleton CU.");
352+
return *Unit.getDWOId();
353+
}
354+
341355
BinaryContext *BC;
342356
/// Maps DWOID to AddressForDWOCU.
343357
std::unordered_map<uint64_t, AddressForDWOCU> AddressMaps;
@@ -357,14 +371,60 @@ class DebugAddrWriterDwarf5 : public DebugAddrWriter {
357371
/// Given DWARFUnit \p Unit returns offset of this CU in to .debug_addr
358372
/// section.
359373
virtual uint64_t getOffset(DWARFUnit &Unit) override;
374+
375+
protected:
376+
/// Given DWARFUnit \p Unit returns either DWO ID or it's offset within
377+
/// .debug_info.
378+
virtual uint64_t getCUID(DWARFUnit &Unit) override {
379+
if (Unit.isDWOUnit()) {
380+
DWARFUnit *SkeletonCU = Unit.getLinkedUnit();
381+
return SkeletonCU->getOffset();
382+
}
383+
return Unit.getOffset();
384+
}
385+
};
386+
387+
/// This class is NOT thread safe.
388+
using DebugStrOffsetsBufferVector = SmallVector<char, 16>;
389+
class DebugStrOffsetsWriter {
390+
public:
391+
DebugStrOffsetsWriter() {
392+
StrOffsetsBuffer = std::make_unique<DebugStrOffsetsBufferVector>();
393+
StrOffsetsStream = std::make_unique<raw_svector_ostream>(*StrOffsetsBuffer);
394+
}
395+
396+
/// Initializes Buffer and Stream.
397+
void initialize(const DWARFSection &StrOffsetsSection,
398+
const Optional<StrOffsetsContributionDescriptor> Contr);
399+
400+
/// Update Str offset in .debug_str in .debug_str_offsets.
401+
void updateAddressMap(uint32_t Index, uint32_t Address);
402+
403+
/// Writes out current sections entry into .debug_str_offsets.
404+
void finalizeSection();
405+
406+
/// Returns False if no strings were added to .debug_str.
407+
bool isFinalized() const { return !StrOffsetsBuffer->empty(); }
408+
409+
/// Returns buffer containing .debug_str_offsets.
410+
std::unique_ptr<DebugStrOffsetsBufferVector> releaseBuffer() {
411+
return std::move(StrOffsetsBuffer);
412+
}
413+
414+
private:
415+
std::unique_ptr<DebugStrOffsetsBufferVector> StrOffsetsBuffer;
416+
std::unique_ptr<raw_svector_ostream> StrOffsetsStream;
417+
std::map<uint32_t, uint32_t> IndexToAddressMap;
418+
// Section size not including header.
419+
uint32_t CurrentSectionSize{0};
360420
};
361421

362422
using DebugStrBufferVector = SmallVector<char, 16>;
363423
class DebugStrWriter {
364424
public:
365425
DebugStrWriter() = delete;
366-
DebugStrWriter(BinaryContext *Bc) : BC(Bc) { create(); }
367-
std::unique_ptr<DebugStrBufferVector> finalize() {
426+
DebugStrWriter(BinaryContext &BC) : BC(BC) { create(); }
427+
std::unique_ptr<DebugStrBufferVector> releaseBuffer() {
368428
return std::move(StrBuffer);
369429
}
370430

@@ -384,7 +444,7 @@ class DebugStrWriter {
384444
void create();
385445
std::unique_ptr<DebugStrBufferVector> StrBuffer;
386446
std::unique_ptr<raw_svector_ostream> StrStream;
387-
BinaryContext *BC;
447+
BinaryContext &BC;
388448
};
389449

390450
enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter };
@@ -451,9 +511,9 @@ class DebugLoclistWriter : public DebugLocWriter {
451511
public:
452512
~DebugLoclistWriter() {}
453513
DebugLoclistWriter() = delete;
454-
DebugLoclistWriter(BinaryContext *BC, uint64_t CID,
514+
DebugLoclistWriter(BinaryContext *BC, DWARFUnit &Unit,
455515
uint32_t LocListsBaseAttrOffset, uint8_t DV, bool SD)
456-
: DebugLocWriter(BC), CUID(CID),
516+
: DebugLocWriter(BC), CU(Unit),
457517
LocListsBaseAttrOffset(LocListsBaseAttrOffset), IsSplitDwarf(SD) {
458518
Kind = LocWriterKind::DebugLoclistWriter;
459519
DwarfVersion = DV;
@@ -472,8 +532,12 @@ class DebugLoclistWriter : public DebugLocWriter {
472532
void finalize(uint64_t SectionOffset,
473533
SimpleBinaryPatcher &DebugInfoPatcher) override;
474534

475-
/// Returns DWO ID.
476-
uint64_t getCUID() const { return CUID; }
535+
/// Returns CU ID.
536+
/// For Skelton CU it is a CU Offset.
537+
/// For DWO CU it is a DWO ID.
538+
uint64_t getCUID() const {
539+
return CU.isDWOUnit() ? *CU.getDWOId() : CU.getOffset();
540+
}
477541

478542
LocWriterKind getKind() const { return DebugLocWriter::getKind(); }
479543

@@ -511,7 +575,7 @@ class DebugLoclistWriter : public DebugLocWriter {
511575
uint64_t Address{0};
512576
};
513577
static DebugAddrWriter *AddrWriter;
514-
uint64_t CUID{0};
578+
DWARFUnit &CU;
515579
uint32_t LocListsBaseAttrOffset{InvalidLocListsBaseAttrOffset};
516580
bool IsSplitDwarf{false};
517581
};

bolt/include/bolt/Rewrite/DWARFRewriter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,23 @@ class DWARFRewriter {
4848
/// Does not do de-duplication.
4949
std::unique_ptr<DebugStrWriter> StrWriter;
5050

51+
/// Stores and serializes information that will be put in to the
52+
/// .debug_str_offsets DWARF section.
53+
std::unique_ptr<DebugStrOffsetsWriter> StrOffstsWriter;
54+
5155
/// .debug_abbrev section writer for the main binary.
5256
std::unique_ptr<DebugAbbrevWriter> AbbrevWriter;
5357

5458
using LocWriters = std::map<uint64_t, std::unique_ptr<DebugLocWriter>>;
5559
/// Use a separate location list writer for each compilation unit
5660
LocWriters LocListWritersByCU;
5761

62+
using RangeListsDWOWriers =
63+
std::unordered_map<uint64_t,
64+
std::unique_ptr<DebugRangeListsSectionWriter>>;
65+
/// Store Rangelists writer for each DWO CU.
66+
RangeListsDWOWriers RangeListsWritersByCU;
67+
5868
using DebugAbbrevDWOWriters =
5969
std::unordered_map<uint64_t, std::unique_ptr<DebugAbbrevWriter>>;
6070
/// Abbrev section writers for DWOs.
@@ -167,6 +177,14 @@ class DWARFRewriter {
167177
return static_cast<Patcher *>(Iter->second.get());
168178
}
169179

180+
/// Adds a \p Str to .debug_str section.
181+
/// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using
182+
/// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets
183+
/// for this contribution of \p Unit.
184+
void addStringHelper(DebugInfoBinaryPatcher &DebugInfoPatcher,
185+
const DWARFUnit &Unit, const AttrInfo &AttrInfoVal,
186+
StringRef Str);
187+
170188
public:
171189
DWARFRewriter(BinaryContext &BC) : BC(BC) {}
172190

bolt/lib/Core/BinaryContext.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,8 @@ void BinaryContext::preprocessDebugInfo() {
15001500
<< DwCtx->getNumCompileUnits() << " CUs will be updated\n";
15011501
}
15021502

1503+
preprocessDWODebugInfo();
1504+
15031505
// Populate MCContext with DWARF files from all units.
15041506
StringRef GlobalPrefix = AsmInfo->getPrivateGlobalPrefix();
15051507
for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
@@ -1521,10 +1523,16 @@ void BinaryContext::preprocessDebugInfo() {
15211523
Optional<MD5::MD5Result> Checksum = None;
15221524
if (LineTable->Prologue.ContentTypes.HasMD5)
15231525
Checksum = LineTable->Prologue.FileNames[0].Checksum;
1524-
BinaryLineTable.setRootFile(
1525-
CU->getCompilationDir(),
1526-
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr),
1527-
Checksum, None);
1526+
Optional<const char *> Name =
1527+
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
1528+
if (Optional<uint64_t> DWOID = CU->getDWOId()) {
1529+
auto Iter = DWOCUs.find(*DWOID);
1530+
assert(Iter != DWOCUs.end() && "DWO CU was not found.");
1531+
Name = dwarf::toString(
1532+
Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
1533+
}
1534+
BinaryLineTable.setRootFile(CU->getCompilationDir(), *Name, Checksum,
1535+
None);
15281536
}
15291537

15301538
BinaryLineTable.setDwarfVersion(DwarfVersion);
@@ -1557,8 +1565,6 @@ void BinaryContext::preprocessDebugInfo() {
15571565
getDwarfFile(Dir, FileName, 0, Checksum, None, CUID, DwarfVersion));
15581566
}
15591567
}
1560-
1561-
preprocessDWODebugInfo();
15621568
}
15631569

15641570
bool BinaryContext::shouldEmit(const BinaryFunction &Function) const {

0 commit comments

Comments
 (0)