[TableGen] Add TreePatternNode::children and use it in for loops (NFC) (#119877)
[llvm-project.git] / bolt / lib / Rewrite / DWARFRewriter.cpp
blob308881081321a23f817e165eb009d15ce303c685
1 //===- bolt/Rewrite/DWARFRewriter.cpp -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "bolt/Rewrite/DWARFRewriter.h"
10 #include "bolt/Core/BinaryContext.h"
11 #include "bolt/Core/BinaryFunction.h"
12 #include "bolt/Core/DIEBuilder.h"
13 #include "bolt/Core/DebugData.h"
14 #include "bolt/Core/DynoStats.h"
15 #include "bolt/Core/ParallelUtilities.h"
16 #include "bolt/Rewrite/RewriteInstance.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/BinaryFormat/Dwarf.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/DIE.h"
23 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
24 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
27 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
28 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
29 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
30 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
31 #include "llvm/MC/MCAsmBackend.h"
32 #include "llvm/MC/MCAssembler.h"
33 #include "llvm/MC/MCObjectWriter.h"
34 #include "llvm/MC/MCStreamer.h"
35 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
36 #include "llvm/Object/ObjectFile.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/Endian.h"
41 #include "llvm/Support/Error.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/LEB128.h"
44 #include "llvm/Support/ThreadPool.h"
45 #include "llvm/Support/raw_ostream.h"
46 #include <algorithm>
47 #include <cstdint>
48 #include <functional>
49 #include <iterator>
50 #include <memory>
51 #include <optional>
52 #include <string>
53 #include <unordered_map>
54 #include <utility>
55 #include <vector>
57 #undef DEBUG_TYPE
58 #define DEBUG_TYPE "bolt"
60 static mc::RegisterMCTargetOptionsFlags MOF;
62 static void printDie(const DWARFDie &DIE) {
63 DIDumpOptions DumpOpts;
64 DumpOpts.ShowForm = true;
65 DumpOpts.Verbose = true;
66 DumpOpts.ChildRecurseDepth = 0;
67 DumpOpts.ShowChildren = false;
68 DIE.dump(dbgs(), 0, DumpOpts);
71 /// Lazily parse DWARF DIE and print it out.
72 LLVM_ATTRIBUTE_UNUSED
73 static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {
74 uint64_t OriginalOffsets = DIEOffset;
75 uint64_t NextCUOffset = DU.getNextUnitOffset();
76 DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
77 DWARFDebugInfoEntry DIEEntry;
78 if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) {
79 if (DIEEntry.getAbbreviationDeclarationPtr()) {
80 DWARFDie DDie(&DU, &DIEEntry);
81 printDie(DDie);
82 } else {
83 dbgs() << "Failed to extract abbreviation for"
84 << Twine::utohexstr(OriginalOffsets) << "\n";
86 } else {
87 dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets)
88 << " \n";
92 using namespace bolt;
94 /// Take a set of DWARF address ranges corresponding to the input binary and
95 /// translate them to a set of address ranges in the output binary.
96 static DebugAddressRangesVector
97 translateInputToOutputRanges(const BinaryFunction &BF,
98 const DWARFAddressRangesVector &InputRanges) {
99 DebugAddressRangesVector OutputRanges;
101 // If the function hasn't changed return the same ranges.
102 if (!BF.isEmitted()) {
103 OutputRanges.resize(InputRanges.size());
104 llvm::transform(InputRanges, OutputRanges.begin(),
105 [](const DWARFAddressRange &Range) {
106 return DebugAddressRange(Range.LowPC, Range.HighPC);
108 return OutputRanges;
111 for (const DWARFAddressRange &Range : InputRanges)
112 llvm::append_range(OutputRanges, BF.translateInputToOutputRange(
113 {Range.LowPC, Range.HighPC}));
115 // Post-processing pass to sort and merge ranges.
116 llvm::sort(OutputRanges);
117 DebugAddressRangesVector MergedRanges;
118 uint64_t PrevHighPC = 0;
119 for (const DebugAddressRange &Range : OutputRanges) {
120 if (Range.LowPC <= PrevHighPC) {
121 MergedRanges.back().HighPC =
122 std::max(MergedRanges.back().HighPC, Range.HighPC);
123 } else {
124 MergedRanges.emplace_back(Range.LowPC, Range.HighPC);
126 PrevHighPC = MergedRanges.back().HighPC;
129 return MergedRanges;
132 /// Similar to translateInputToOutputRanges() but operates on location lists.
133 static DebugLocationsVector
134 translateInputToOutputLocationList(const BinaryFunction &BF,
135 const DebugLocationsVector &InputLL) {
136 DebugLocationsVector OutputLL;
138 // If the function hasn't changed - there's nothing to update.
139 if (!BF.isEmitted())
140 return InputLL;
142 for (const DebugLocationEntry &Entry : InputLL) {
143 DebugAddressRangesVector OutRanges =
144 BF.translateInputToOutputRange({Entry.LowPC, Entry.HighPC});
145 if (!OutRanges.empty() && !OutputLL.empty()) {
146 if (OutRanges.front().LowPC == OutputLL.back().HighPC &&
147 Entry.Expr == OutputLL.back().Expr) {
148 OutputLL.back().HighPC =
149 std::max(OutputLL.back().HighPC, OutRanges.front().HighPC);
150 OutRanges.erase(OutRanges.begin());
153 llvm::transform(OutRanges, std::back_inserter(OutputLL),
154 [&Entry](const DebugAddressRange &R) {
155 return DebugLocationEntry{R.LowPC, R.HighPC, Entry.Expr};
159 // Sort and merge adjacent entries with identical locations.
160 llvm::stable_sort(
161 OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) {
162 return A.LowPC < B.LowPC;
164 DebugLocationsVector MergedLL;
165 uint64_t PrevHighPC = 0;
166 const SmallVectorImpl<uint8_t> *PrevExpr = nullptr;
167 for (const DebugLocationEntry &Entry : OutputLL) {
168 if (Entry.LowPC <= PrevHighPC && *PrevExpr == Entry.Expr) {
169 MergedLL.back().HighPC = std::max(Entry.HighPC, MergedLL.back().HighPC);
170 } else {
171 const uint64_t Begin = std::max(Entry.LowPC, PrevHighPC);
172 const uint64_t End = std::max(Begin, Entry.HighPC);
173 MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr});
175 PrevHighPC = MergedLL.back().HighPC;
176 PrevExpr = &MergedLL.back().Expr;
179 return MergedLL;
182 using namespace dwarf_linker;
183 using namespace dwarf_linker::classic;
185 namespace llvm {
186 namespace bolt {
187 /// Emits debug information into .debug_info or .debug_types section.
188 class DIEStreamer : public DwarfStreamer {
189 DIEBuilder *DIEBldr;
190 GDBIndex &GDBIndexSection;
192 private:
193 /// Emit the compilation unit header for \p Unit in the debug_info
194 /// section.
196 /// A Dwarf 4 section header is encoded as:
197 /// uint32_t Unit length (omitting this field)
198 /// uint16_t Version
199 /// uint32_t Abbreviation table offset
200 /// uint8_t Address size
201 /// Leading to a total of 11 bytes.
203 /// A Dwarf 5 section header is encoded as:
204 /// uint32_t Unit length (omitting this field)
205 /// uint16_t Version
206 /// uint8_t Unit type
207 /// uint8_t Address size
208 /// uint32_t Abbreviation table offset
209 /// Leading to a total of 12 bytes.
210 void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
211 unsigned DwarfVersion) {
213 AsmPrinter &Asm = getAsmPrinter();
214 switchToDebugInfoSection(DwarfVersion);
216 emitCommonHeader(Unit, UnitDIE, DwarfVersion);
218 if (DwarfVersion >= 5 &&
219 Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) {
220 std::optional<uint64_t> DWOId = Unit.getDWOId();
221 assert(DWOId &&
222 "DWOId does not exist and this is not a DW_UT_compile Unit");
223 Asm.emitInt64(*DWOId);
227 void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) {
228 dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType());
229 llvm::AsmPrinter &Asm = getAsmPrinter();
231 // Emit size of content not including length itself
232 Asm.emitInt32(Unit.getHeaderSize() + UnitDIE.getSize() - 4);
233 Asm.emitInt16(Version);
235 // DWARF v5 reorders the address size and adds a unit type.
236 if (Version >= 5) {
237 Asm.emitInt8(UT);
238 Asm.emitInt8(Asm.MAI->getCodePointerSize());
241 Asm.emitInt32(0);
242 if (Version <= 4) {
243 Asm.emitInt8(Asm.MAI->getCodePointerSize());
247 void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
248 unsigned DwarfVersion) {
249 AsmPrinter &Asm = getAsmPrinter();
250 const uint64_t TypeSignature = cast<DWARFTypeUnit>(Unit).getTypeHash();
251 DIE *TypeDIE = DIEBldr->getTypeDIE(Unit);
252 const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit);
253 GDBIndexSection.addGDBTypeUnitEntry(
254 {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()});
255 if (Unit.getVersion() < 5) {
256 // Switch the section to .debug_types section.
257 std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;
258 llvm::MCContext &MC = Asm.OutContext;
259 const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();
261 MS->switchSection(MOFI->getDwarfTypesSection(0));
262 MC.setDwarfVersion(DwarfVersion);
263 } else
264 switchToDebugInfoSection(DwarfVersion);
266 emitCommonHeader(Unit, UnitDIE, DwarfVersion);
267 Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature));
268 Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0);
271 void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {
272 if (Unit.isTypeUnit())
273 emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion());
274 else
275 emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());
278 void emitDIE(DIE &Die) override {
279 AsmPrinter &Asm = getAsmPrinter();
280 Asm.emitDwarfDIE(Die);
283 public:
284 DIEStreamer(DIEBuilder *DIEBldr, GDBIndex &GDBIndexSection,
285 DWARFLinkerBase::OutputFileType OutFileType,
286 raw_pwrite_stream &OutFile,
287 DWARFLinkerBase::MessageHandlerTy Warning)
288 : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr),
289 GDBIndexSection(GDBIndexSection) {};
291 using DwarfStreamer::emitCompileUnitHeader;
293 void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
294 emitUnitHeader(Unit, UnitDIE);
295 emitDIE(UnitDIE);
299 /// Finds attributes FormValue and Offset.
301 /// \param DIE die to look up in.
302 /// \param Attrs finds the first attribute that matches and extracts it.
303 /// \return an optional AttrInfo with DWARFFormValue and Offset.
304 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
305 std::vector<dwarf::Attribute> Attrs) {
306 for (dwarf::Attribute &Attr : Attrs)
307 if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))
308 return Info;
309 return std::nullopt;
312 } // namespace bolt
313 } // namespace llvm
315 using namespace llvm;
316 using namespace llvm::support::endian;
317 using namespace object;
318 using namespace bolt;
320 namespace opts {
322 extern cl::OptionCategory BoltCategory;
323 extern cl::opt<unsigned> Verbosity;
324 extern cl::opt<std::string> OutputFilename;
326 static cl::opt<bool> KeepARanges(
327 "keep-aranges",
328 cl::desc(
329 "keep or generate .debug_aranges section if .gdb_index is written"),
330 cl::Hidden, cl::cat(BoltCategory));
332 static cl::opt<unsigned>
333 DebugThreadCount("debug-thread-count",
334 cl::desc("specifies thread count for the multithreading "
335 "for updating DWO debug info"),
336 cl::init(1), cl::cat(BoltCategory));
338 static cl::opt<std::string> DwarfOutputPath(
339 "dwarf-output-path",
340 cl::desc("Path to where .dwo files will be written out to."), cl::init(""),
341 cl::cat(BoltCategory));
343 static cl::opt<bool> CreateDebugNames(
344 "create-debug-names-section",
345 cl::desc("Creates .debug_names section, if the input binary doesn't have "
346 "it already, for DWARF5 CU/TUs."),
347 cl::init(false), cl::cat(BoltCategory));
349 static cl::opt<bool>
350 DebugSkeletonCu("debug-skeleton-cu",
351 cl::desc("prints out offsets for abbrev and debug_info of "
352 "Skeleton CUs that get patched."),
353 cl::ZeroOrMore, cl::Hidden, cl::init(false),
354 cl::cat(BoltCategory));
356 static cl::opt<unsigned> BatchSize(
357 "cu-processing-batch-size",
358 cl::desc(
359 "Specifies the size of batches for processing CUs. Higher number has "
360 "better performance, but more memory usage. Default value is 1."),
361 cl::Hidden, cl::init(1), cl::cat(BoltCategory));
363 static cl::opt<bool> AlwaysConvertToRanges(
364 "always-convert-to-ranges",
365 cl::desc("This option is for testing purposes only. It forces BOLT to "
366 "convert low_pc/high_pc to ranges always."),
367 cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));
369 extern cl::opt<std::string> CompDirOverride;
370 } // namespace opts
372 /// If DW_AT_low_pc exists sets LowPC and returns true.
373 static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
374 uint64_t &SectionIndex) {
375 DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);
376 if (!DvalLowPc)
377 return false;
379 dwarf::Form Form = DvalLowPc.getForm();
380 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
381 uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue();
382 if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx ||
383 AddrOffset) {
385 uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue;
386 std::optional<object::SectionedAddress> SA =
387 DU.getAddrOffsetSectionItem(Index);
388 if (!SA)
389 return false;
390 if (AddrOffset)
391 SA->Address += (LowPcValue & 0xffffffff);
393 LowPC = SA->Address;
394 SectionIndex = SA->SectionIndex;
395 } else {
396 LowPC = LowPcValue;
397 SectionIndex = 0;
399 return true;
402 /// If DW_AT_high_pc exists sets HighPC and returns true.
403 static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {
404 DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
405 if (!DvalHighPc)
406 return false;
407 if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
408 HighPC = DvalHighPc.getDIEInteger().getValue();
409 else
410 HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
411 return true;
414 /// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
415 /// true.
416 static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
417 uint64_t &LowPC, uint64_t &HighPC,
418 uint64_t &SectionIndex) {
419 uint64_t TempLowPC = LowPC;
420 uint64_t TempHighPC = HighPC;
421 uint64_t TempSectionIndex = SectionIndex;
422 if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) &&
423 getHighPC(Die, TempLowPC, TempHighPC)) {
424 LowPC = TempLowPC;
425 HighPC = TempHighPC;
426 SectionIndex = TempSectionIndex;
427 return true;
429 return false;
432 static Expected<llvm::DWARFAddressRangesVector>
433 getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
434 uint64_t LowPC, HighPC, Index;
435 if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index))
436 return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
437 if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) {
438 if (Dval.getForm() == dwarf::DW_FORM_rnglistx)
439 return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue());
441 return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue());
444 return DWARFAddressRangesVector();
447 static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
448 const DIEValue &AttrVal) {
449 DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());
450 if (std::optional<object::SectionedAddress> SA =
451 DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU))
452 return SA->Address;
453 return std::nullopt;
456 static std::unique_ptr<DIEStreamer>
457 createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
458 StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
459 GDBIndex &GDBIndexSection) {
461 std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
462 &DIEBldr, GDBIndexSection, DWARFLinkerBase::OutputFileType::Object,
463 OutFile,
464 [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
465 Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
466 if (Err)
467 errs()
468 << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
469 << toString(std::move(Err)) << "\n";
470 return Streamer;
473 static void emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer,
474 DWARFUnit &Unit) {
475 DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit);
476 Streamer.emitUnit(Unit, *UnitDIE);
479 static void emitDWOBuilder(const std::string &DWOName,
480 DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
481 DWARFUnit &SplitCU, DWARFUnit &CU,
482 DebugLocWriter &LocWriter,
483 DebugStrOffsetsWriter &StrOffstsWriter,
484 DebugStrWriter &StrWriter, GDBIndex &GDBIndexSection,
485 DebugRangesSectionWriter &TempRangesSectionWriter) {
486 // Populate debug_info and debug_abbrev for current dwo into StringRef.
487 DWODIEBuilder.generateAbbrevs();
488 DWODIEBuilder.finish();
490 SmallVector<char, 20> OutBuffer;
491 std::shared_ptr<raw_svector_ostream> ObjOS =
492 std::make_shared<raw_svector_ostream>(OutBuffer);
493 const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();
494 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
495 std::unique_ptr<DIEStreamer> Streamer =
496 createDIEStreamer(*TheTriple, *ObjOS, "DwoStreamerInitAug2",
497 DWODIEBuilder, GDBIndexSection);
498 if (SplitCU.getContext().getMaxDWOVersion() >= 5) {
499 for (std::unique_ptr<llvm::DWARFUnit> &CU :
500 SplitCU.getContext().dwo_info_section_units()) {
501 if (!CU->isTypeUnit())
502 continue;
503 emitUnit(DWODIEBuilder, *Streamer, *CU.get());
505 emitUnit(DWODIEBuilder, *Streamer, SplitCU);
506 } else {
507 for (std::unique_ptr<llvm::DWARFUnit> &CU :
508 SplitCU.getContext().dwo_compile_units())
509 emitUnit(DWODIEBuilder, *Streamer, *CU.get());
511 // emit debug_types sections for dwarf4
512 for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector())
513 emitUnit(DWODIEBuilder, *Streamer, *CU);
516 Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(),
517 SplitCU.getContext().getMaxVersion());
518 Streamer->finish();
520 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
521 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
522 std::unique_ptr<object::ObjectFile> Obj = cantFail(
523 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
524 "error creating in-memory object");
526 DWARFRewriter::OverriddenSectionsMap OverriddenSections;
527 for (const SectionRef &Secs : Obj->sections()) {
528 StringRef Contents = cantFail(Secs.getContents());
529 StringRef Name = cantFail(Secs.getName());
530 DWARFSectionKind Kind =
531 StringSwitch<DWARFSectionKind>(Name)
532 .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV)
533 .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO)
534 .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES)
535 .Default(DWARFSectionKind::DW_SECT_EXT_unknown);
536 if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)
537 continue;
538 OverriddenSections[Kind] = Contents;
540 Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter,
541 StrOffstsWriter, StrWriter, TempRangesSectionWriter);
544 using DWARFUnitVec = std::vector<DWARFUnit *>;
545 using CUPartitionVector = std::vector<DWARFUnitVec>;
546 /// Partitions CUs in to buckets. Bucket size is controlled by
547 /// cu-processing-batch-size. All the CUs that have cross CU reference reference
548 /// as a source are put in to the same initial bucket.
549 static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {
550 CUPartitionVector Vec(2);
551 unsigned Counter = 0;
552 const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();
553 for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {
554 Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =
555 Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset());
556 if (!AbbrDeclSet) {
557 consumeError(AbbrDeclSet.takeError());
558 return Vec;
560 bool CrossCURefFound = false;
561 for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) {
562 for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr :
563 Decl.attributes()) {
564 if (Attr.Form == dwarf::DW_FORM_ref_addr) {
565 CrossCURefFound = true;
566 break;
569 if (CrossCURefFound)
570 break;
572 if (CrossCURefFound) {
573 Vec[0].push_back(CU.get());
574 } else {
575 ++Counter;
576 Vec.back().push_back(CU.get());
578 if (Counter % opts::BatchSize == 0 && !Vec.back().empty())
579 Vec.push_back({});
581 return Vec;
584 void DWARFRewriter::updateDebugInfo() {
585 ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
586 if (!DebugInfo)
587 return;
589 ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
590 StrWriter = std::make_unique<DebugStrWriter>(*BC.DwCtx, false);
591 StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>(BC);
593 /// Stores and serializes information that will be put into the
594 /// .debug_addr DWARF section.
595 std::unique_ptr<DebugAddrWriter> FinalAddrWriter;
597 if (BC.isDWARF5Used()) {
598 FinalAddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC);
599 RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();
600 } else {
601 FinalAddrWriter = std::make_unique<DebugAddrWriter>(&BC);
604 if (BC.isDWARFLegacyUsed()) {
605 LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
606 LegacyRangesSectionWriter->initSection();
609 uint32_t CUIndex = 0;
610 std::mutex AccessMutex;
611 // Needs to be invoked in the same order as CUs are processed.
612 llvm::DenseMap<uint64_t, uint64_t> LocListWritersIndexByCU;
613 auto createRangeLocListAddressWriters = [&](DWARFUnit &CU) {
614 std::lock_guard<std::mutex> Lock(AccessMutex);
615 const uint16_t DwarfVersion = CU.getVersion();
616 if (DwarfVersion >= 5) {
617 auto AddrW = std::make_unique<DebugAddrWriterDwarf5>(
618 &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase());
619 RangeListsSectionWriter->setAddressWriter(AddrW.get());
620 LocListWritersByCU[CUIndex] =
621 std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *AddrW);
623 if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
624 assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
625 "RangeLists writer for DWO unit already exists.");
626 auto DWORangeListsSectionWriter =
627 std::make_unique<DebugRangeListsSectionWriter>();
628 DWORangeListsSectionWriter->initSection(CU);
629 DWORangeListsSectionWriter->setAddressWriter(AddrW.get());
630 RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter);
632 AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
633 } else {
634 auto AddrW =
635 std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize());
636 AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
637 LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
638 if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
639 assert(LegacyRangesWritersByCU.count(*DWOId) == 0 &&
640 "LegacyRangeLists writer for DWO unit already exists.");
641 auto LegacyRangesSectionWriterByCU =
642 std::make_unique<DebugRangesSectionWriter>();
643 LegacyRangesSectionWriterByCU->initSection(CU);
644 LegacyRangesWritersByCU[*DWOId] =
645 std::move(LegacyRangesSectionWriterByCU);
648 LocListWritersIndexByCU[CU.getOffset()] = CUIndex++;
651 DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
652 *StrWriter);
653 GDBIndex GDBIndexSection(BC);
654 auto processSplitCU = [&](DWARFUnit &Unit, DWARFUnit &SplitCU,
655 DebugRangesSectionWriter &TempRangesSectionWriter,
656 DebugAddrWriter &AddressWriter,
657 const std::string &DWOName,
658 const std::optional<std::string> &DwarfOutputPath,
659 DIEBuilder &DWODIEBuilder) {
660 DWODIEBuilder.buildDWOUnit(SplitCU);
661 DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
662 DebugStrWriter DWOStrWriter((SplitCU).getContext(), true);
663 DWODIEBuilder.updateDWONameCompDirForTypes(
664 DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName);
665 DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true,
666 AddressWriter);
668 updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter,
669 TempRangesSectionWriter, AddressWriter);
670 DebugLocDWoWriter.finalize(DWODIEBuilder,
671 *DWODIEBuilder.getUnitDIEbyUnit(SplitCU));
672 if (Unit.getVersion() >= 5)
673 TempRangesSectionWriter.finalizeSection();
675 emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit,
676 DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter,
677 GDBIndexSection, TempRangesSectionWriter);
679 auto processMainBinaryCU = [&](DWARFUnit &Unit, DIEBuilder &DIEBlder) {
680 std::optional<DWARFUnit *> SplitCU;
681 std::optional<uint64_t> RangesBase;
682 std::optional<uint64_t> DWOId = Unit.getDWOId();
683 if (DWOId)
684 SplitCU = BC.getDWOCU(*DWOId);
685 DebugLocWriter &DebugLocWriter =
686 *LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get();
687 DebugRangesSectionWriter &RangesSectionWriter =
688 Unit.getVersion() >= 5 ? *RangeListsSectionWriter.get()
689 : *LegacyRangesSectionWriter.get();
690 DebugAddrWriter &AddressWriter =
691 *AddressWritersByCU[Unit.getOffset()].get();
692 if (Unit.getVersion() >= 5)
693 RangeListsSectionWriter->setAddressWriter(&AddressWriter);
694 if (Unit.getVersion() >= 5) {
695 RangesBase = RangesSectionWriter.getSectionOffset() +
696 getDWARF5RngListLocListHeaderSize();
697 RangesSectionWriter.initSection(Unit);
698 if (!SplitCU)
699 StrOffstsWriter->finalizeSection(Unit, DIEBlder);
700 } else if (SplitCU) {
701 RangesBase = LegacyRangesSectionWriter.get()->getSectionOffset();
704 updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter,
705 AddressWriter, RangesBase);
706 DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit));
707 if (Unit.getVersion() >= 5)
708 RangesSectionWriter.finalizeSection();
711 DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
712 DIEBlder.buildTypeUnits(StrOffstsWriter.get());
713 SmallVector<char, 20> OutBuffer;
714 std::unique_ptr<raw_svector_ostream> ObjOS =
715 std::make_unique<raw_svector_ostream>(OutBuffer);
716 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
717 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
718 std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(
719 *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);
720 CUOffsetMap OffsetMap =
721 finalizeTypeSections(DIEBlder, *Streamer, GDBIndexSection);
723 CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
724 const unsigned int ThreadCount =
725 std::min(opts::DebugThreadCount, opts::ThreadCount);
726 for (std::vector<DWARFUnit *> &Vec : PartVec) {
727 DIEBlder.buildCompileUnits(Vec);
728 llvm::SmallVector<std::unique_ptr<DIEBuilder>, 72> DWODIEBuildersByCU;
729 ThreadPoolInterface &ThreadPool =
730 ParallelUtilities::getThreadPool(ThreadCount);
731 for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) {
732 createRangeLocListAddressWriters(*CU);
733 std::optional<DWARFUnit *> SplitCU;
734 std::optional<uint64_t> DWOId = CU->getDWOId();
735 if (DWOId)
736 SplitCU = BC.getDWOCU(*DWOId);
737 if (!SplitCU)
738 continue;
739 DebugAddrWriter &AddressWriter =
740 *AddressWritersByCU[CU->getOffset()].get();
741 DebugRangesSectionWriter &TempRangesSectionWriter =
742 CU->getVersion() >= 5 ? *RangeListsWritersByCU[*DWOId].get()
743 : *LegacyRangesWritersByCU[*DWOId].get();
744 std::optional<std::string> DwarfOutputPath =
745 opts::DwarfOutputPath.empty()
746 ? std::nullopt
747 : std::optional<std::string>(opts::DwarfOutputPath.c_str());
748 std::string DWOName = DIEBlder.updateDWONameCompDir(
749 *StrOffstsWriter, *StrWriter, *CU, DwarfOutputPath, std::nullopt);
750 auto DWODIEBuilderPtr = std::make_unique<DIEBuilder>(
751 BC, &(**SplitCU).getContext(), DebugNamesTable, CU);
752 DIEBuilder &DWODIEBuilder =
753 *DWODIEBuildersByCU.emplace_back(std::move(DWODIEBuilderPtr)).get();
754 if (CU->getVersion() >= 5)
755 StrOffstsWriter->finalizeSection(*CU, DIEBlder);
756 // Important to capture CU and SplitCU by value here, otherwise when the
757 // thread is executed at some point after the current iteration of the
758 // loop, dereferencing CU/SplitCU in the call to processSplitCU means it
759 // will dereference a different variable than the one intended, causing a
760 // seg fault.
761 ThreadPool.async([&, DwarfOutputPath, DWOName, CU, SplitCU] {
762 processSplitCU(*CU, **SplitCU, TempRangesSectionWriter, AddressWriter,
763 DWOName, DwarfOutputPath, DWODIEBuilder);
766 ThreadPool.wait();
767 for (std::unique_ptr<DIEBuilder> &DWODIEBuilderPtr : DWODIEBuildersByCU)
768 DWODIEBuilderPtr->updateDebugNamesTable();
769 for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
770 processMainBinaryCU(*CU, DIEBlder);
771 finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
772 DIEBlder.getProcessedCUs(), *FinalAddrWriter);
775 DebugNamesTable.emitAccelTable();
777 finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, OffsetMap,
778 *FinalAddrWriter);
779 GDBIndexSection.updateGdbIndexSection(OffsetMap, CUIndex,
780 *ARangesSectionWriter);
783 void DWARFRewriter::updateUnitDebugInfo(
784 DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
785 DebugRangesSectionWriter &RangesSectionWriter,
786 DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) {
787 // Cache debug ranges so that the offset for identical ranges could be reused.
788 std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
790 uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();
791 uint64_t NextCUOffset = Unit.getNextUnitOffset();
792 const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =
793 DIEBldr.getDIEsByUnit(Unit);
795 // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
796 auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,
797 const DIEValue &HighPCVal, uint64_t LowPC,
798 const uint64_t HighPC) {
799 dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;
800 dwarf::Form FormLowPC = dwarf::DW_FORM_addr;
801 dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;
802 dwarf::Form FormHighPC = dwarf::DW_FORM_data4;
803 const uint32_t Size = HighPC - LowPC;
804 // Whatever was generated is not low_pc/high_pc, so will reset to
805 // default for size 1.
806 if (!LowPCVal || !HighPCVal) {
807 if (Unit.getVersion() >= 5)
808 FormLowPC = dwarf::DW_FORM_addrx;
809 else if (Unit.isDWOUnit())
810 FormLowPC = dwarf::DW_FORM_GNU_addr_index;
811 } else {
812 AttrLowPC = LowPCVal.getAttribute();
813 FormLowPC = LowPCVal.getForm();
814 AttrHighPC = HighPCVal.getAttribute();
815 FormHighPC = HighPCVal.getForm();
818 if (FormLowPC == dwarf::DW_FORM_addrx ||
819 FormLowPC == dwarf::DW_FORM_GNU_addr_index)
820 LowPC = AddressWriter.getIndexFromAddress(LowPC, Unit);
822 if (LowPCVal)
823 DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
824 else
825 DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
826 if (HighPCVal) {
827 DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
828 } else {
829 DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges);
830 DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
834 for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {
835 DIE *Die = DI->Die;
836 switch (Die->getTag()) {
837 case dwarf::DW_TAG_compile_unit:
838 case dwarf::DW_TAG_skeleton_unit: {
839 // For dwarf5 section 3.1.3
840 // The following attributes are not part of a split full compilation unit
841 // entry but instead are inherited (if present) from the corresponding
842 // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges,
843 // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base,
844 // DW_AT_addr_base and DW_AT_rnglists_base.
845 if (Unit.getVersion() == 5 && Unit.isDWOUnit())
846 continue;
847 auto ModuleRangesOrError = getDIEAddressRanges(*Die, Unit);
848 if (!ModuleRangesOrError) {
849 consumeError(ModuleRangesOrError.takeError());
850 break;
852 DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;
853 DebugAddressRangesVector OutputRanges =
854 BC.translateModuleAddressRanges(ModuleRanges);
855 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
856 // For a case where LLD GCs only function used in the CU.
857 // If CU doesn't have DW_AT_low_pc we are not going to convert,
858 // so don't need to do anything.
859 if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)
860 OutputRanges.push_back({0, 0});
861 const uint64_t RangesSectionOffset =
862 RangesSectionWriter.addRanges(OutputRanges);
863 // Don't emit the zero low_pc arange.
864 if (!Unit.isDWOUnit() && !OutputRanges.empty() &&
865 OutputRanges.back().LowPC)
866 ARangesSectionWriter->addCURanges(Unit.getOffset(),
867 std::move(OutputRanges));
868 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset,
869 RangesBase);
870 DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list);
871 if (LineTablePatchMap.count(&Unit))
872 DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list,
873 StmtListAttrVal.getForm(),
874 DIEInteger(LineTablePatchMap[&Unit]));
875 break;
878 case dwarf::DW_TAG_subprogram: {
879 // Get function address either from ranges or [LowPC, HighPC) pair.
880 uint64_t Address = UINT64_MAX;
881 uint64_t SectionIndex, HighPC;
882 DebugAddressRangesVector FunctionRanges;
883 if (!getLowAndHighPC(*Die, Unit, Address, HighPC, SectionIndex)) {
884 Expected<DWARFAddressRangesVector> RangesOrError =
885 getDIEAddressRanges(*Die, Unit);
886 if (!RangesOrError) {
887 consumeError(RangesOrError.takeError());
888 break;
890 DWARFAddressRangesVector Ranges = *RangesOrError;
891 // Not a function definition.
892 if (Ranges.empty())
893 break;
895 for (const DWARFAddressRange &Range : Ranges) {
896 if (const BinaryFunction *Function =
897 BC.getBinaryFunctionAtAddress(Range.LowPC))
898 FunctionRanges.append(Function->getOutputAddressRanges());
900 } else {
901 if (const BinaryFunction *Function =
902 BC.getBinaryFunctionAtAddress(Address))
903 FunctionRanges = Function->getOutputAddressRanges();
906 // Clear cached ranges as the new function will have its own set.
907 CachedRanges.clear();
908 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
909 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
910 if (FunctionRanges.empty()) {
911 if (LowPCVal && HighPCVal)
912 FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()});
913 else
914 FunctionRanges.push_back({0, 1});
917 if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) {
918 updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC,
919 FunctionRanges.back().HighPC);
920 break;
923 updateDWARFObjectAddressRanges(
924 Unit, DIEBldr, *Die, RangesSectionWriter.addRanges(FunctionRanges));
926 break;
928 case dwarf::DW_TAG_lexical_block:
929 case dwarf::DW_TAG_inlined_subroutine:
930 case dwarf::DW_TAG_try_block:
931 case dwarf::DW_TAG_catch_block: {
932 uint64_t RangesSectionOffset = 0;
933 Expected<DWARFAddressRangesVector> RangesOrError =
934 getDIEAddressRanges(*Die, Unit);
935 const BinaryFunction *Function =
936 RangesOrError && !RangesOrError->empty()
937 ? BC.getBinaryFunctionContainingAddress(
938 RangesOrError->front().LowPC)
939 : nullptr;
940 DebugAddressRangesVector OutputRanges;
941 if (Function) {
942 OutputRanges = translateInputToOutputRanges(*Function, *RangesOrError);
943 LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {
944 dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
945 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"
946 << Twine::utohexstr(Unit.getOffset()) << '\n';
948 if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {
949 RangesSectionOffset = RangesSectionWriter.addRanges(
950 std::move(OutputRanges), CachedRanges);
951 OutputRanges.clear();
952 } else if (OutputRanges.empty()) {
953 OutputRanges.push_back({0, RangesOrError.get().front().HighPC});
955 } else if (!RangesOrError) {
956 consumeError(RangesOrError.takeError());
957 } else {
958 OutputRanges.push_back({0, !RangesOrError->empty()
959 ? RangesOrError.get().front().HighPC
960 : 0});
962 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
963 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
964 if (OutputRanges.size() == 1) {
965 updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,
966 OutputRanges.back().HighPC);
967 break;
969 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset);
970 break;
972 case dwarf::DW_TAG_call_site: {
973 auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void {
974 std::optional<uint64_t> Address = getAsAddress(Unit, AttrVal);
975 const BinaryFunction *Function =
976 BC.getBinaryFunctionContainingAddress(*Address);
977 uint64_t UpdatedAddress = *Address;
978 if (Function)
979 UpdatedAddress =
980 Function->translateInputToOutputAddress(UpdatedAddress);
982 if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {
983 const uint32_t Index =
984 AddressWriter.getIndexFromAddress(UpdatedAddress, Unit);
985 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
986 DIEInteger(Index));
987 } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {
988 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
989 DIEInteger(UpdatedAddress));
990 } else {
991 errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";
994 DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc);
995 if (CallPcAttrVal)
996 patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");
998 DIEValue CallRetPcAttrVal =
999 Die->findAttribute(dwarf::DW_AT_call_return_pc);
1000 if (CallRetPcAttrVal)
1001 patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc");
1003 break;
1005 default: {
1006 // Handle any tag that can have DW_AT_location attribute.
1007 DIEValue LocAttrInfo = Die->findAttribute(dwarf::DW_AT_location);
1008 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
1009 if (LocAttrInfo) {
1010 if (doesFormBelongToClass(LocAttrInfo.getForm(),
1011 DWARFFormValue::FC_Constant,
1012 Unit.getVersion()) ||
1013 doesFormBelongToClass(LocAttrInfo.getForm(),
1014 DWARFFormValue::FC_SectionOffset,
1015 Unit.getVersion())) {
1016 uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx
1017 ? LocAttrInfo.getDIELocList().getValue()
1018 : LocAttrInfo.getDIEInteger().getValue();
1019 DebugLocationsVector InputLL;
1021 std::optional<object::SectionedAddress> SectionAddress =
1022 Unit.getBaseAddress();
1023 uint64_t BaseAddress = 0;
1024 if (SectionAddress)
1025 BaseAddress = SectionAddress->Address;
1027 if (Unit.getVersion() >= 5 &&
1028 LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) {
1029 std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset);
1030 assert(LocOffset && "Location Offset is invalid.");
1031 Offset = *LocOffset;
1034 Error E = Unit.getLocationTable().visitLocationList(
1035 &Offset, [&](const DWARFLocationEntry &Entry) {
1036 switch (Entry.Kind) {
1037 default:
1038 llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
1039 case dwarf::DW_LLE_end_of_list:
1040 return false;
1041 case dwarf::DW_LLE_base_address: {
1042 assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
1043 "absolute address expected");
1044 BaseAddress = Entry.Value0;
1045 break;
1047 case dwarf::DW_LLE_offset_pair:
1048 assert(
1049 (Entry.SectionIndex == SectionedAddress::UndefSection &&
1050 (!Unit.isDWOUnit() || Unit.getVersion() == 5)) &&
1051 "absolute address expected");
1052 InputLL.emplace_back(DebugLocationEntry{
1053 BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,
1054 Entry.Loc});
1055 break;
1056 case dwarf::DW_LLE_start_length:
1057 InputLL.emplace_back(DebugLocationEntry{
1058 Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});
1059 break;
1060 case dwarf::DW_LLE_base_addressx: {
1061 std::optional<object::SectionedAddress> EntryAddress =
1062 Unit.getAddrOffsetSectionItem(Entry.Value0);
1063 assert(EntryAddress && "base Address not found.");
1064 BaseAddress = EntryAddress->Address;
1065 break;
1067 case dwarf::DW_LLE_startx_length: {
1068 std::optional<object::SectionedAddress> EntryAddress =
1069 Unit.getAddrOffsetSectionItem(Entry.Value0);
1070 assert(EntryAddress && "Address does not exist.");
1071 InputLL.emplace_back(DebugLocationEntry{
1072 EntryAddress->Address,
1073 EntryAddress->Address + Entry.Value1, Entry.Loc});
1074 break;
1076 case dwarf::DW_LLE_startx_endx: {
1077 std::optional<object::SectionedAddress> StartAddress =
1078 Unit.getAddrOffsetSectionItem(Entry.Value0);
1079 assert(StartAddress && "Start Address does not exist.");
1080 std::optional<object::SectionedAddress> EndAddress =
1081 Unit.getAddrOffsetSectionItem(Entry.Value1);
1082 assert(EndAddress && "Start Address does not exist.");
1083 InputLL.emplace_back(DebugLocationEntry{
1084 StartAddress->Address, EndAddress->Address, Entry.Loc});
1085 break;
1088 return true;
1091 if (E || InputLL.empty()) {
1092 consumeError(std::move(E));
1093 errs() << "BOLT-WARNING: empty location list detected at 0x"
1094 << Twine::utohexstr(Offset) << " for DIE at 0x" << Die
1095 << " in CU at 0x" << Twine::utohexstr(Unit.getOffset())
1096 << '\n';
1097 } else {
1098 const uint64_t Address = InputLL.front().LowPC;
1099 DebugLocationsVector OutputLL;
1100 if (const BinaryFunction *Function =
1101 BC.getBinaryFunctionContainingAddress(Address)) {
1102 OutputLL = translateInputToOutputLocationList(*Function, InputLL);
1103 LLVM_DEBUG(if (OutputLL.empty()) {
1104 dbgs() << "BOLT-DEBUG: location list translated to an empty "
1105 "one at 0x"
1106 << Die << " in CU at 0x"
1107 << Twine::utohexstr(Unit.getOffset()) << '\n';
1109 } else {
1110 // It's possible for a subprogram to be removed and to have
1111 // address of 0. Adding this entry to output to preserve debug
1112 // information.
1113 OutputLL = InputLL;
1115 DebugLocWriter.addList(DIEBldr, *Die, LocAttrInfo, OutputLL);
1117 } else {
1118 assert((doesFormBelongToClass(LocAttrInfo.getForm(),
1119 DWARFFormValue::FC_Exprloc,
1120 Unit.getVersion()) ||
1121 doesFormBelongToClass(LocAttrInfo.getForm(),
1122 DWARFFormValue::FC_Block,
1123 Unit.getVersion())) &&
1124 "unexpected DW_AT_location form");
1125 if (Unit.isDWOUnit() || Unit.getVersion() >= 5) {
1126 std::vector<uint8_t> Sblock;
1127 DIEValueList *AttrLocValList;
1128 if (doesFormBelongToClass(LocAttrInfo.getForm(),
1129 DWARFFormValue::FC_Exprloc,
1130 Unit.getVersion())) {
1131 for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {
1132 Sblock.push_back(Val.getDIEInteger().getValue());
1134 DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc());
1135 AttrLocValList = static_cast<DIEValueList *>(LocAttr);
1136 } else {
1137 for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) {
1138 Sblock.push_back(Val.getDIEInteger().getValue());
1140 DIEBlock *BlockAttr =
1141 const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock());
1142 AttrLocValList = static_cast<DIEValueList *>(BlockAttr);
1144 ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);
1145 DataExtractor Data(
1146 StringRef((const char *)Expr.data(), Expr.size()),
1147 Unit.getContext().isLittleEndian(), 0);
1148 DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
1149 Unit.getFormParams().Format);
1150 uint32_t PrevOffset = 0;
1151 DIEValueList *NewAttr;
1152 DIEValue Value;
1153 uint32_t NewExprSize = 0;
1154 DIELoc *Loc = nullptr;
1155 DIEBlock *Block = nullptr;
1156 if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) {
1157 Loc = DIEBldr.allocateDIEValue<DIELoc>();
1158 NewAttr = Loc;
1159 Value = DIEValue(LocAttrInfo.getAttribute(),
1160 LocAttrInfo.getForm(), Loc);
1161 } else if (doesFormBelongToClass(LocAttrInfo.getForm(),
1162 DWARFFormValue::FC_Block,
1163 Unit.getVersion())) {
1164 Block = DIEBldr.allocateDIEValue<DIEBlock>();
1165 NewAttr = Block;
1166 Value = DIEValue(LocAttrInfo.getAttribute(),
1167 LocAttrInfo.getForm(), Block);
1168 } else {
1169 errs() << "BOLT-WARNING: Unexpected Form value in Updating "
1170 "DW_AT_Location\n";
1171 continue;
1174 for (const DWARFExpression::Operation &Expr : LocExpr) {
1175 uint32_t CurEndOffset = PrevOffset + 1;
1176 if (Expr.getDescription().Op.size() == 1)
1177 CurEndOffset = Expr.getOperandEndOffset(0);
1178 if (Expr.getDescription().Op.size() == 2)
1179 CurEndOffset = Expr.getOperandEndOffset(1);
1180 if (Expr.getDescription().Op.size() > 2)
1181 errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "
1182 "number of operands.\n";
1183 // not addr index, just copy.
1184 if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
1185 Expr.getCode() == dwarf::DW_OP_addrx)) {
1186 auto Itr = AttrLocValList->values().begin();
1187 std::advance(Itr, PrevOffset);
1188 uint32_t CopyNum = CurEndOffset - PrevOffset;
1189 NewExprSize += CopyNum;
1190 while (CopyNum--) {
1191 DIEBldr.addValue(NewAttr, *Itr);
1192 std::advance(Itr, 1);
1194 } else {
1195 const uint64_t Index = Expr.getRawOperand(0);
1196 std::optional<object::SectionedAddress> EntryAddress =
1197 Unit.getAddrOffsetSectionItem(Index);
1198 assert(EntryAddress && "Address is not found.");
1199 assert(Index <= std::numeric_limits<uint32_t>::max() &&
1200 "Invalid Operand Index.");
1201 const uint32_t AddrIndex = AddressWriter.getIndexFromAddress(
1202 EntryAddress->Address, Unit);
1203 // update Index into .debug_address section for DW_AT_location.
1204 // The Size field is not stored in IR, we need to minus 1 in
1205 // offset for each expr.
1206 SmallString<8> Tmp;
1207 raw_svector_ostream OSE(Tmp);
1208 encodeULEB128(AddrIndex, OSE);
1210 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1211 dwarf::DW_FORM_data1,
1212 DIEInteger(Expr.getCode()));
1213 NewExprSize += 1;
1214 for (uint8_t Byte : Tmp) {
1215 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1216 dwarf::DW_FORM_data1, DIEInteger(Byte));
1217 NewExprSize += 1;
1220 PrevOffset = CurEndOffset;
1223 // update the size since the index might be changed
1224 if (Loc)
1225 Loc->setSize(NewExprSize);
1226 else
1227 Block->setSize(NewExprSize);
1228 DIEBldr.replaceValue(Die, LocAttrInfo.getAttribute(),
1229 LocAttrInfo.getForm(), Value);
1232 } else if (LowPCAttrInfo) {
1233 uint64_t Address = 0;
1234 uint64_t SectionIndex = 0;
1235 if (getLowPC(*Die, Unit, Address, SectionIndex)) {
1236 uint64_t NewAddress = 0;
1237 if (const BinaryFunction *Function =
1238 BC.getBinaryFunctionContainingAddress(Address)) {
1239 NewAddress = Function->translateInputToOutputAddress(Address);
1240 LLVM_DEBUG(dbgs()
1241 << "BOLT-DEBUG: Fixing low_pc 0x"
1242 << Twine::utohexstr(Address) << " for DIE with tag "
1243 << Die->getTag() << " to 0x"
1244 << Twine::utohexstr(NewAddress) << '\n');
1247 dwarf::Form Form = LowPCAttrInfo.getForm();
1248 assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&
1249 "DW_FORM_LLVM_addrx_offset is not supported");
1250 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
1251 if (Form == dwarf::DW_FORM_addrx ||
1252 Form == dwarf::DW_FORM_GNU_addr_index) {
1253 const uint32_t Index = AddressWriter.getIndexFromAddress(
1254 NewAddress ? NewAddress : Address, Unit);
1255 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1256 LowPCAttrInfo.getForm(), DIEInteger(Index));
1257 } else {
1258 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1259 LowPCAttrInfo.getForm(),
1260 DIEInteger(NewAddress));
1262 } else if (opts::Verbosity >= 1) {
1263 errs() << "BOLT-WARNING: unexpected form value for attribute "
1264 "LowPCAttrInfo\n";
1270 if (DIEOffset > NextCUOffset)
1271 errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"
1272 << Twine::utohexstr(Unit.getOffset()) << '\n';
1275 void DWARFRewriter::updateDWARFObjectAddressRanges(
1276 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
1277 std::optional<uint64_t> RangesBase) {
1279 if (RangesBase) {
1280 // If DW_AT_GNU_ranges_base is present, update it. No further modifications
1281 // are needed for ranges base.
1283 DIEValue RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_GNU_ranges_base);
1284 if (!RangesBaseInfo) {
1285 RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_rnglists_base);
1288 if (RangesBaseInfo) {
1289 if (RangesBaseInfo.getAttribute() == dwarf::DW_AT_GNU_ranges_base) {
1290 auto RangesWriterIterator =
1291 LegacyRangesWritersByCU.find(*Unit.getDWOId());
1292 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1293 "RangesWriter does not exist for DWOId");
1294 RangesWriterIterator->second->setDie(&Die);
1295 } else {
1296 DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(),
1297 RangesBaseInfo.getForm(),
1298 DIEInteger(static_cast<uint32_t>(*RangesBase)));
1300 RangesBase = std::nullopt;
1304 DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc);
1305 DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges);
1306 if (RangesAttrInfo) {
1307 // Case 1: The object was already non-contiguous and had DW_AT_ranges.
1308 // In this case we simply need to update the value of DW_AT_ranges
1309 // and introduce DW_AT_GNU_ranges_base if required.
1310 // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
1311 bool NeedConverted = false;
1313 if (Unit.getVersion() >= 5 &&
1314 RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset)
1315 NeedConverted = true;
1317 if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx)
1318 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx,
1319 DIEInteger(DebugRangesOffset));
1320 else
1321 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(),
1322 DIEInteger(DebugRangesOffset));
1324 if (!RangesBase) {
1325 if (LowPCAttrInfo &&
1326 LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index &&
1327 LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx)
1328 DIEBldr.replaceValue(&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(),
1329 DIEInteger(0));
1330 return;
1333 if (!(Die.getTag() == dwarf::DW_TAG_compile_unit ||
1334 Die.getTag() == dwarf::DW_TAG_skeleton_unit))
1335 return;
1337 // If we are at this point we are in the CU/Skeleton CU, and
1338 // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist.
1339 if (Unit.getVersion() <= 4) {
1340 DIEBldr.addValue(&Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
1341 DIEInteger(INT_MAX));
1342 auto RangesWriterIterator =
1343 LegacyRangesWritersByCU.find(*Unit.getDWOId());
1344 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1345 "RangesWriter does not exist for DWOId");
1346 RangesWriterIterator->second->setDie(&Die);
1347 } else if (Unit.getVersion() >= 5) {
1348 DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
1349 dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
1351 return;
1354 // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
1355 // to back. Replace with new attributes and patch the DIE.
1356 DIEValue HighPCAttrInfo = Die.findAttribute(dwarf::DW_AT_high_pc);
1357 if (LowPCAttrInfo && HighPCAttrInfo) {
1359 convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset,
1360 LowPCAttrInfo, HighPCAttrInfo, RangesBase);
1361 } else if (!(Unit.isDWOUnit() &&
1362 Die.getTag() == dwarf::DW_TAG_compile_unit)) {
1363 if (opts::Verbosity >= 1)
1364 errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
1365 << Twine::utohexstr(Unit.getOffset()) << '\n';
1369 void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) {
1370 ErrorOr<BinarySection &> DbgInfoSection =
1371 BC.getUniqueSectionByName(".debug_info");
1372 ErrorOr<BinarySection &> TypeInfoSection =
1373 BC.getUniqueSectionByName(".debug_types");
1374 assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||
1375 BC.DwCtx->getNumTypeUnits() == 0) &&
1376 "Was not able to retrieve Debug Types section.");
1378 // There is no direct connection between CU and TU, but same offsets,
1379 // encoded in DW_AT_stmt_list, into .debug_line get modified.
1380 // We take advantage of that to map original CU line table offsets to new
1381 // ones.
1382 std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;
1384 auto GetStatementListValue =
1385 [](const DWARFDie &DIE) -> std::optional<uint64_t> {
1386 std::optional<DWARFFormValue> StmtList = DIE.find(dwarf::DW_AT_stmt_list);
1387 if (!StmtList)
1388 return std::nullopt;
1389 std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);
1390 assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");
1391 return *Offset;
1394 SmallVector<DWARFUnit *, 1> TUs;
1395 for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1396 if (CU->isTypeUnit()) {
1397 TUs.push_back(CU.get());
1398 continue;
1400 const unsigned CUID = CU->getOffset();
1401 MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
1402 if (!Label)
1403 continue;
1405 std::optional<uint64_t> StmtOffset =
1406 GetStatementListValue(CU.get()->getUnitDIE());
1407 if (!StmtOffset)
1408 continue;
1410 const uint64_t LineTableOffset =
1411 Asm.getSymbolOffset(*Label);
1412 DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
1413 assert(DbgInfoSection && ".debug_info section must exist");
1414 LineTablePatchMap[CU.get()] = LineTableOffset;
1417 for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())
1418 TUs.push_back(TU.get());
1420 for (DWARFUnit *TU : TUs) {
1421 std::optional<uint64_t> StmtOffset =
1422 GetStatementListValue(TU->getUnitDIE());
1423 if (!StmtOffset)
1424 continue;
1425 auto Iter = DebugLineOffsetMap.find(*StmtOffset);
1426 if (Iter == DebugLineOffsetMap.end()) {
1427 // Implementation depends on TU sharing DW_AT_stmt_list with a CU.
1428 // Only case that it hasn't been true was for manually modified assembly
1429 // file. Adding this warning in case assumption is false.
1430 errs()
1431 << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"
1432 << Twine::utohexstr(TU->getOffset())
1433 << " is not sharing "
1434 ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "
1435 "updated.\n";
1436 continue;
1438 TypeUnitRelocMap[TU] = Iter->second;
1441 // Set .debug_info as finalized so it won't be skipped over when
1442 // we process sections while writing out the new binary. This ensures
1443 // that the pending relocations will be processed and not ignored.
1444 if (DbgInfoSection)
1445 DbgInfoSection->setIsFinalized();
1447 if (TypeInfoSection)
1448 TypeInfoSection->setIsFinalized();
1451 CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
1452 DIEStreamer &Streamer,
1453 GDBIndex &GDBIndexSection) {
1454 // update TypeUnit DW_AT_stmt_list with new .debug_line information.
1455 auto updateLineTable = [&](const DWARFUnit &Unit) -> void {
1456 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit);
1457 DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);
1458 if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit))
1459 return;
1460 DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,
1461 StmtAttrInfo.getForm(),
1462 DIEInteger(TypeUnitRelocMap[&Unit]));
1465 // generate and populate abbrevs here
1466 DIEBlder.generateAbbrevs();
1467 DIEBlder.finish();
1468 DIEBlder.updateDebugNamesTable();
1469 SmallVector<char, 20> OutBuffer;
1470 std::shared_ptr<raw_svector_ostream> ObjOS =
1471 std::make_shared<raw_svector_ostream>(OutBuffer);
1472 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1473 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
1474 std::unique_ptr<DIEStreamer> TypeStreamer = createDIEStreamer(
1475 *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);
1477 // generate debug_info and CUMap
1478 CUOffsetMap CUMap;
1479 for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1480 if (!CU->isTypeUnit())
1481 continue;
1482 updateLineTable(*CU.get());
1483 emitUnit(DIEBlder, Streamer, *CU.get());
1484 uint32_t StartOffset = CUOffset;
1485 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get());
1486 CUOffset += CU.get()->getHeaderSize();
1487 CUOffset += UnitDIE->getSize();
1488 CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
1491 // Emit Type Unit of DWARF 4 to .debug_type section
1492 for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {
1493 updateLineTable(*TU);
1494 emitUnit(DIEBlder, *TypeStreamer, *TU);
1497 TypeStreamer->finish();
1499 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1500 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
1501 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1502 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1503 "error creating in-memory object");
1505 for (const SectionRef &Section : Obj->sections()) {
1506 StringRef Contents = cantFail(Section.getContents());
1507 StringRef Name = cantFail(Section.getName());
1508 if (Name == ".debug_types")
1509 BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents),
1510 Contents.size());
1512 return CUMap;
1515 void DWARFRewriter::finalizeDebugSections(
1516 DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
1517 DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap,
1518 DebugAddrWriter &FinalAddrWriter) {
1519 if (StrWriter->isInitialized()) {
1520 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
1521 std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
1522 StrWriter->releaseBuffer();
1523 BC.registerOrUpdateNoteSection(".debug_str",
1524 copyByteArray(*DebugStrSectionContents),
1525 DebugStrSectionContents->size());
1528 if (StrOffstsWriter->isFinalized()) {
1529 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");
1530 std::unique_ptr<DebugStrOffsetsBufferVector>
1531 DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();
1532 BC.registerOrUpdateNoteSection(
1533 ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents),
1534 DebugStrOffsetsSectionContents->size());
1537 if (BC.isDWARFLegacyUsed()) {
1538 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1539 LegacyRangesSectionWriter->releaseBuffer();
1540 BC.registerOrUpdateNoteSection(".debug_ranges",
1541 copyByteArray(*RangesSectionContents),
1542 RangesSectionContents->size());
1545 if (BC.isDWARF5Used()) {
1546 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1547 RangeListsSectionWriter->releaseBuffer();
1548 BC.registerOrUpdateNoteSection(".debug_rnglists",
1549 copyByteArray(*RangesSectionContents),
1550 RangesSectionContents->size());
1553 if (BC.isDWARF5Used()) {
1554 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1555 makeFinalLocListsSection(DWARFVersion::DWARF5);
1556 if (!LocationListSectionContents->empty())
1557 BC.registerOrUpdateNoteSection(
1558 ".debug_loclists", copyByteArray(*LocationListSectionContents),
1559 LocationListSectionContents->size());
1562 if (BC.isDWARFLegacyUsed()) {
1563 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1564 makeFinalLocListsSection(DWARFVersion::DWARFLegacy);
1565 if (!LocationListSectionContents->empty())
1566 BC.registerOrUpdateNoteSection(
1567 ".debug_loc", copyByteArray(*LocationListSectionContents),
1568 LocationListSectionContents->size());
1571 if (FinalAddrWriter.isInitialized()) {
1572 std::unique_ptr<AddressSectionBuffer> AddressSectionContents =
1573 FinalAddrWriter.releaseBuffer();
1574 BC.registerOrUpdateNoteSection(".debug_addr",
1575 copyByteArray(*AddressSectionContents),
1576 AddressSectionContents->size());
1579 Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion());
1580 Streamer.finish();
1582 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1583 MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false);
1584 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1585 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1586 "error creating in-memory object");
1588 for (const SectionRef &Secs : Obj->sections()) {
1589 StringRef Contents = cantFail(Secs.getContents());
1590 StringRef Name = cantFail(Secs.getName());
1591 if (Name == ".debug_abbrev") {
1592 BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents),
1593 Contents.size());
1594 } else if (Name == ".debug_info") {
1595 BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents),
1596 Contents.size());
1600 // Skip .debug_aranges if we are re-generating .gdb_index.
1601 if (opts::KeepARanges || !BC.getGdbIndexSection()) {
1602 SmallVector<char, 16> ARangesBuffer;
1603 raw_svector_ostream OS(ARangesBuffer);
1605 auto MAB = std::unique_ptr<MCAsmBackend>(
1606 BC.TheTarget->createMCAsmBackend(*BC.STI, *BC.MRI, MCTargetOptions()));
1608 ARangesSectionWriter->writeARangesSection(OS, CUMap);
1609 const StringRef &ARangesContents = OS.str();
1611 BC.registerOrUpdateNoteSection(".debug_aranges",
1612 copyByteArray(ARangesContents),
1613 ARangesContents.size());
1616 if (DebugNamesTable.isCreated()) {
1617 RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");
1618 std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =
1619 DebugNamesTable.releaseBuffer();
1620 BC.registerOrUpdateNoteSection(".debug_names",
1621 copyByteArray(*DebugNamesSectionContents),
1622 DebugNamesSectionContents->size());
1626 void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
1627 DIEStreamer &Streamer,
1628 CUOffsetMap &CUMap,
1629 const std::list<DWARFUnit *> &CUs,
1630 DebugAddrWriter &FinalAddrWriter) {
1631 for (DWARFUnit *CU : CUs) {
1632 auto AddressWriterIterator = AddressWritersByCU.find(CU->getOffset());
1633 assert(AddressWriterIterator != AddressWritersByCU.end() &&
1634 "AddressWriter does not exist for CU");
1635 DebugAddrWriter *AddressWriter = AddressWriterIterator->second.get();
1636 const size_t BufferOffset = FinalAddrWriter.getBufferSize();
1637 std::optional<uint64_t> Offset = AddressWriter->finalize(BufferOffset);
1638 /// If Offset already exists in UnmodifiedAddressOffsets, then update with
1639 /// Offset, else update with BufferOffset.
1640 if (Offset)
1641 AddressWriter->updateAddrBase(DIEBlder, *CU, *Offset);
1642 else if (AddressWriter->isInitialized())
1643 AddressWriter->updateAddrBase(DIEBlder, *CU, BufferOffset);
1644 if (AddressWriter->isInitialized()) {
1645 std::unique_ptr<AddressSectionBuffer> AddressSectionContents =
1646 AddressWriter->releaseBuffer();
1647 FinalAddrWriter.appendToAddressBuffer(*AddressSectionContents);
1649 if (CU->getVersion() != 4)
1650 continue;
1651 std::optional<uint64_t> DWOId = CU->getDWOId();
1652 if (!DWOId)
1653 continue;
1654 auto RangesWriterIterator = LegacyRangesWritersByCU.find(*DWOId);
1655 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1656 "RangesWriter does not exist for DWOId");
1657 std::unique_ptr<DebugRangesSectionWriter> &LegacyRangesWriter =
1658 RangesWriterIterator->second;
1659 DIE *Die = LegacyRangesWriter->getDie();
1660 if (!Die)
1661 continue;
1662 DIEValue DvalGNUBase = Die->findAttribute(dwarf::DW_AT_GNU_ranges_base);
1663 assert(DvalGNUBase && "GNU_ranges_base attribute does not exist for DWOId");
1664 DIEBlder.replaceValue(
1665 Die, dwarf::DW_AT_GNU_ranges_base, DvalGNUBase.getForm(),
1666 DIEInteger(LegacyRangesSectionWriter->getSectionOffset()));
1667 std::unique_ptr<DebugBufferVector> RangesWritersContents =
1668 LegacyRangesWriter->releaseBuffer();
1669 LegacyRangesSectionWriter->appendToRangeBuffer(*RangesWritersContents);
1671 DIEBlder.generateAbbrevs();
1672 DIEBlder.finish();
1673 DIEBlder.updateDebugNamesTable();
1674 // generate debug_info and CUMap
1675 for (DWARFUnit *CU : CUs) {
1676 emitUnit(DIEBlder, Streamer, *CU);
1677 const uint32_t StartOffset = CUOffset;
1678 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);
1679 CUOffset += CU->getHeaderSize();
1680 CUOffset += UnitDIE->getSize();
1681 CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
1685 // Creates all the data structures necessary for creating MCStreamer.
1686 // They are passed by reference because they need to be kept around.
1687 // Also creates known debug sections. These are sections handled by
1688 // handleDebugDataPatching.
1689 namespace {
1691 std::unique_ptr<BinaryContext>
1692 createDwarfOnlyBC(const object::ObjectFile &File) {
1693 return cantFail(BinaryContext::createBinaryContext(
1694 File.makeTriple(), std::make_shared<orc::SymbolStringPool>(),
1695 File.getFileName(), nullptr, false,
1696 DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,
1697 nullptr, "", WithColor::defaultErrorHandler,
1698 WithColor::defaultWarningHandler),
1699 {llvm::outs(), llvm::errs()}));
1702 StringMap<DWARFRewriter::KnownSectionsEntry>
1703 createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {
1704 StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {
1705 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
1706 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
1707 {"debug_str_offsets.dwo",
1708 {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},
1709 {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},
1710 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
1711 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
1712 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
1713 {"debug_loclists.dwo",
1714 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
1715 {"debug_rnglists.dwo",
1716 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};
1717 return KnownSectionsTemp;
1720 StringRef getSectionName(const SectionRef &Section) {
1721 Expected<StringRef> SectionName = Section.getName();
1722 assert(SectionName && "Invalid section name.");
1723 StringRef Name = *SectionName;
1724 Name = Name.substr(Name.find_first_not_of("._"));
1725 return Name;
1728 // Exctracts an appropriate slice if input is DWP.
1729 // Applies patches or overwrites the section.
1730 std::optional<StringRef> updateDebugData(
1731 DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
1732 const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
1733 MCStreamer &Streamer, DWARFRewriter &Writer,
1734 const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
1735 std::unique_ptr<DebugBufferVector> &OutputBuffer,
1736 DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
1737 DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
1738 const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {
1740 using DWOSectionContribution =
1741 const DWARFUnitIndex::Entry::SectionContribution;
1742 auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,
1743 StringRef OutData, DWARFSectionKind Sec,
1744 uint64_t &DWPOffset) -> StringRef {
1745 if (DWOEntry) {
1746 DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);
1747 DWPOffset = DWOContrubution->getOffset();
1748 OutData = OutData.substr(DWPOffset, DWOContrubution->getLength());
1750 return OutData;
1753 auto SectionIter = KnownSections.find(SectionName);
1754 if (SectionIter == KnownSections.end())
1755 return std::nullopt;
1756 Streamer.switchSection(SectionIter->second.first);
1757 uint64_t DWPOffset = 0;
1759 auto getOverridenSection =
1760 [&](DWARFSectionKind Kind) -> std::optional<StringRef> {
1761 auto Iter = OverridenSections.find(Kind);
1762 if (Iter == OverridenSections.end()) {
1763 errs()
1764 << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
1765 "section for: "
1766 << Twine::utohexstr(DWOId) << ".\n";
1767 return std::nullopt;
1769 return Iter->second;
1771 switch (SectionIter->second.second) {
1772 default: {
1773 if (SectionName != "debug_str.dwo")
1774 errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
1775 << "\n";
1776 if (StrWriter.isInitialized()) {
1777 OutputBuffer = StrWriter.releaseBuffer();
1778 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1779 OutputBuffer->size());
1781 return SectionContents;
1783 case DWARFSectionKind::DW_SECT_INFO: {
1784 return getOverridenSection(DWARFSectionKind::DW_SECT_INFO);
1786 case DWARFSectionKind::DW_SECT_EXT_TYPES: {
1787 return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);
1789 case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
1790 if (StrOffstsWriter.isFinalized()) {
1791 OutputBuffer = StrOffstsWriter.releaseBuffer();
1792 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1793 OutputBuffer->size());
1795 return getSliceData(CUDWOEntry, SectionContents,
1796 DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
1798 case DWARFSectionKind::DW_SECT_ABBREV: {
1799 return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV);
1801 case DWARFSectionKind::DW_SECT_EXT_LOC:
1802 case DWARFSectionKind::DW_SECT_LOCLISTS: {
1803 OutputBuffer = LocWriter.getBuffer();
1804 // Creating explicit StringRef here, otherwise
1805 // with implicit conversion it will take null byte as end of
1806 // string.
1807 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1808 OutputBuffer->size());
1810 case DWARFSectionKind::DW_SECT_LINE: {
1811 return getSliceData(CUDWOEntry, SectionContents,
1812 DWARFSectionKind::DW_SECT_LINE, DWPOffset);
1814 case DWARFSectionKind::DW_SECT_RNGLISTS: {
1815 assert(RangeListsWriter && "RangeListsWriter was not created.");
1816 OutputBuffer = RangeListsWriter->releaseBuffer();
1817 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1818 OutputBuffer->size());
1823 } // namespace
1825 void DWARFRewriter::writeDWOFiles(
1826 DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
1827 const std::string &DWOName, DebugLocWriter &LocWriter,
1828 DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
1829 DebugRangesSectionWriter &TempRangesSectionWriter) {
1830 // Setup DWP code once.
1831 DWARFContext *DWOCtx = BC.getDWOContext();
1832 const uint64_t DWOId = *CU.getDWOId();
1833 const DWARFUnitIndex *CUIndex = nullptr;
1834 bool IsDWP = false;
1835 if (DWOCtx) {
1836 CUIndex = &DWOCtx->getCUIndex();
1837 IsDWP = !CUIndex->getRows().empty();
1840 // Skipping CUs that we failed to load.
1841 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
1842 if (!DWOCU) {
1843 errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "
1844 << Twine::utohexstr(DWOId) << " is not found.\n";
1845 return;
1848 std::string CompDir = CU.getCompilationDir();
1850 if (!opts::DwarfOutputPath.empty())
1851 CompDir = opts::DwarfOutputPath.c_str();
1852 else if (!opts::CompDirOverride.empty())
1853 CompDir = opts::CompDirOverride;
1855 SmallString<16> AbsolutePath;
1856 sys::path::append(AbsolutePath, CompDir);
1857 sys::path::append(AbsolutePath, DWOName);
1859 std::error_code EC;
1860 std::unique_ptr<ToolOutputFile> TempOut =
1861 std::make_unique<ToolOutputFile>(AbsolutePath, EC, sys::fs::OF_None);
1863 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
1864 if (IsDWP)
1865 CUDWOEntry = CUIndex->getFromHash(DWOId);
1867 const object::ObjectFile *File =
1868 (*DWOCU)->getContext().getDWARFObj().getFile();
1869 std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
1870 std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
1871 const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
1872 StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
1874 DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
1875 if (CU.getVersion() == 5) {
1876 RangeListssWriter =
1877 llvm::dyn_cast<DebugRangeListsSectionWriter>(&TempRangesSectionWriter);
1879 // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not
1880 // have .debug_rnglists so won't be part of the loop below.
1881 if (!RangeListssWriter->empty()) {
1882 std::unique_ptr<DebugBufferVector> OutputData;
1883 if (std::optional<StringRef> OutData =
1884 updateDebugData((*DWOCU)->getContext(), "debug_rnglists.dwo", "",
1885 KnownSections, *Streamer, *this, CUDWOEntry,
1886 DWOId, OutputData, RangeListssWriter, LocWriter,
1887 StrOffstsWriter, StrWriter, OverridenSections))
1888 Streamer->emitBytes(*OutData);
1892 for (const SectionRef &Section : File->sections()) {
1893 std::unique_ptr<DebugBufferVector> OutputData;
1894 StringRef SectionName = getSectionName(Section);
1895 if (SectionName == "debug_rnglists.dwo")
1896 continue;
1897 Expected<StringRef> ContentsExp = Section.getContents();
1898 assert(ContentsExp && "Invalid contents.");
1899 if (std::optional<StringRef> OutData = updateDebugData(
1900 (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
1901 *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
1902 LocWriter, StrOffstsWriter, StrWriter, OverridenSections))
1903 Streamer->emitBytes(*OutData);
1905 Streamer->finish();
1906 TempOut->keep();
1909 std::unique_ptr<DebugBufferVector>
1910 DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
1911 auto LocBuffer = std::make_unique<DebugBufferVector>();
1912 auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
1913 auto Writer =
1914 std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));
1916 for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :
1917 LocListWritersByCU) {
1918 DebugLocWriter *LocWriter = Loc.second.get();
1919 auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter);
1921 // Filter out DWARF4, writing out DWARF5
1922 if (Version == DWARFVersion::DWARF5 &&
1923 (!LocListWriter || LocListWriter->getDwarfVersion() <= 4))
1924 continue;
1926 // Filter out DWARF5, writing out DWARF4
1927 if (Version == DWARFVersion::DWARFLegacy &&
1928 (LocListWriter && LocListWriter->getDwarfVersion() >= 5))
1929 continue;
1931 // Skipping DWARF4/5 split dwarf.
1932 if (LocListWriter && LocListWriter->getDwarfVersion() <= 4)
1933 continue;
1934 std::unique_ptr<DebugBufferVector> CurrCULocationLists =
1935 LocWriter->getBuffer();
1936 *LocStream << *CurrCULocationLists;
1939 return LocBuffer;
1942 void DWARFRewriter::convertToRangesPatchDebugInfo(
1943 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
1944 uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
1945 DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {
1946 dwarf::Form LowForm = LowPCAttrInfo.getForm();
1947 dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
1948 dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;
1950 if (Unit.getVersion() >= 5) {
1951 RangeBaseAttribute = dwarf::DW_AT_rnglists_base;
1952 RangesForm = dwarf::DW_FORM_rnglistx;
1953 } else if (Unit.getVersion() < 4) {
1954 RangesForm = dwarf::DW_FORM_data4;
1956 bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit ||
1957 Die.getTag() == dwarf::DW_TAG_skeleton_unit;
1958 if (!IsUnitDie)
1959 DIEBldr.deleteValue(&Die, LowPCAttrInfo.getAttribute());
1961 // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
1962 // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
1963 // when it's absent.
1964 if (IsUnitDie) {
1965 if (LowForm == dwarf::DW_FORM_addrx) {
1966 auto AddrWriterIterator = AddressWritersByCU.find(Unit.getOffset());
1967 assert(AddrWriterIterator != AddressWritersByCU.end() &&
1968 "AddressWriter does not exist for CU");
1969 DebugAddrWriter *AddrWriter = AddrWriterIterator->second.get();
1970 const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit);
1971 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
1972 LowPCAttrInfo.getForm(), DIEInteger(Index));
1973 } else {
1974 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
1975 LowPCAttrInfo.getForm(), DIEInteger(0));
1977 // Original CU didn't have DW_AT_*_base. We converted it's children (or
1978 // dwo), so need to insert it into CU.
1979 if (RangesBase) {
1980 if (Unit.getVersion() >= 5) {
1981 DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
1982 DIEInteger(*RangesBase));
1983 } else {
1984 DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
1985 DIEInteger(INT_MAX));
1986 auto RangesWriterIterator =
1987 LegacyRangesWritersByCU.find(*Unit.getDWOId());
1988 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1989 "RangesWriter does not exist for DWOId");
1990 RangesWriterIterator->second->setDie(&Die);
1995 // HighPC was conveted into DW_AT_ranges.
1996 // For DWARF5 we only access ranges through index.
1998 DIEBldr.replaceValue(&Die, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges,
1999 RangesForm, DIEInteger(RangesSectionOffset));