Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / bolt / lib / Rewrite / DWARFRewriter.cpp
blob0ac8e3956b90f610588868df903b4b6bc645f7c9
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 "bolt/Utils/Utils.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/BinaryFormat/Dwarf.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DIE.h"
24 #include "llvm/DWARFLinker/DWARFStreamer.h"
25 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
27 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
28 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
29 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
30 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
31 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
32 #include "llvm/MC/MCAsmBackend.h"
33 #include "llvm/MC/MCAsmLayout.h"
34 #include "llvm/MC/MCObjectWriter.h"
35 #include "llvm/MC/MCStreamer.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 void printDie(const DWARFDie &DIE) {
61 DIDumpOptions DumpOpts;
62 DumpOpts.ShowForm = true;
63 DumpOpts.Verbose = true;
64 DumpOpts.ChildRecurseDepth = 0;
65 DumpOpts.ShowChildren = false;
66 DIE.dump(dbgs(), 0, DumpOpts);
69 /// Lazily parse DWARF DIE and print it out.
70 LLVM_ATTRIBUTE_UNUSED
71 static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {
72 uint64_t OriginalOffsets = DIEOffset;
73 uint64_t NextCUOffset = DU.getNextUnitOffset();
74 DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
75 DWARFDebugInfoEntry DIEEntry;
76 if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) {
77 if (const DWARFAbbreviationDeclaration *AbbrDecl =
78 DIEEntry.getAbbreviationDeclarationPtr()) {
79 DWARFDie DDie(&DU, &DIEEntry);
80 printDie(DDie);
81 } else {
82 dbgs() << "Failed to extract abbreviation for"
83 << Twine::utohexstr(OriginalOffsets) << "\n";
85 } else {
86 dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets)
87 << " \n";
91 namespace llvm {
92 namespace bolt {
93 /// Emits debug information into .debug_info or .debug_types section.
94 class DIEStreamer : public DwarfStreamer {
95 DIEBuilder *DIEBldr;
96 DWARFRewriter &Rewriter;
98 private:
99 /// Emit the compilation unit header for \p Unit in the debug_info
100 /// section.
102 /// A Dwarf 4 section header is encoded as:
103 /// uint32_t Unit length (omitting this field)
104 /// uint16_t Version
105 /// uint32_t Abbreviation table offset
106 /// uint8_t Address size
107 /// Leading to a total of 11 bytes.
109 /// A Dwarf 5 section header is encoded as:
110 /// uint32_t Unit length (omitting this field)
111 /// uint16_t Version
112 /// uint8_t Unit type
113 /// uint8_t Address size
114 /// uint32_t Abbreviation table offset
115 /// Leading to a total of 12 bytes.
116 void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
117 unsigned DwarfVersion) {
119 AsmPrinter &Asm = getAsmPrinter();
120 switchToDebugInfoSection(DwarfVersion);
122 emitCommonHeader(Unit, UnitDIE, DwarfVersion);
124 if (DwarfVersion >= 5 &&
125 Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) {
126 std::optional<uint64_t> DWOId = Unit.getDWOId();
127 assert(DWOId &&
128 "DWOId does not exist and this is not a DW_UT_compile Unit");
129 Asm.emitInt64(*DWOId);
133 void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) {
134 dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType());
135 llvm::AsmPrinter &Asm = getAsmPrinter();
137 // Emit size of content not including length itself
138 Asm.emitInt32(Unit.getHeaderSize() + UnitDIE.getSize() - 4);
139 Asm.emitInt16(Version);
141 // DWARF v5 reorders the address size and adds a unit type.
142 if (Version >= 5) {
143 Asm.emitInt8(UT);
144 Asm.emitInt8(Asm.MAI->getCodePointerSize());
147 Asm.emitInt32(0);
148 if (Version <= 4) {
149 Asm.emitInt8(Asm.MAI->getCodePointerSize());
153 void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
154 unsigned DwarfVersion) {
155 AsmPrinter &Asm = getAsmPrinter();
156 const uint64_t TypeSignature = cast<DWARFTypeUnit>(Unit).getTypeHash();
157 DIE *TypeDIE = DIEBldr->getTypeDIE(Unit);
158 const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit);
159 Rewriter.addGDBTypeUnitEntry(
160 {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()});
161 if (Unit.getVersion() < 5) {
162 // Switch the section to .debug_types section.
163 std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;
164 llvm::MCContext &MC = Asm.OutContext;
165 const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();
167 MS->switchSection(MOFI->getDwarfTypesSection(0));
168 MC.setDwarfVersion(DwarfVersion);
169 } else
170 switchToDebugInfoSection(DwarfVersion);
172 emitCommonHeader(Unit, UnitDIE, DwarfVersion);
173 Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature));
174 Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0);
177 void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {
178 if (Unit.isTypeUnit())
179 emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion());
180 else
181 emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());
184 void emitDIE(DIE &Die) override {
185 AsmPrinter &Asm = getAsmPrinter();
186 Asm.emitDwarfDIE(Die);
189 public:
190 DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter,
191 DWARFLinker::OutputFileType OutFileType,
192 raw_pwrite_stream &OutFile,
193 std::function<StringRef(StringRef Input)> Translator,
194 DWARFLinker::messageHandler Warning)
195 : DwarfStreamer(OutFileType, OutFile, Translator, Warning),
196 DIEBldr(DIEBldr), Rewriter(Rewriter){};
198 using DwarfStreamer::emitCompileUnitHeader;
200 void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
201 emitUnitHeader(Unit, UnitDIE);
202 emitDIE(UnitDIE);
206 /// Finds attributes FormValue and Offset.
208 /// \param DIE die to look up in.
209 /// \param Attrs finds the first attribute that matches and extracts it.
210 /// \return an optional AttrInfo with DWARFFormValue and Offset.
211 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
212 std::vector<dwarf::Attribute> Attrs) {
213 for (dwarf::Attribute &Attr : Attrs)
214 if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))
215 return Info;
216 return std::nullopt;
219 } // namespace bolt
220 } // namespace llvm
222 using namespace llvm;
223 using namespace llvm::support::endian;
224 using namespace object;
225 using namespace bolt;
227 namespace opts {
229 extern cl::OptionCategory BoltCategory;
230 extern cl::opt<unsigned> Verbosity;
231 extern cl::opt<std::string> OutputFilename;
233 static cl::opt<bool> KeepARanges(
234 "keep-aranges",
235 cl::desc(
236 "keep or generate .debug_aranges section if .gdb_index is written"),
237 cl::Hidden, cl::cat(BoltCategory));
239 static cl::opt<bool>
240 DeterministicDebugInfo("deterministic-debuginfo",
241 cl::desc("disables parallel execution of tasks that may produce "
242 "nondeterministic debug info"),
243 cl::init(true),
244 cl::cat(BoltCategory));
246 static cl::opt<std::string> DwarfOutputPath(
247 "dwarf-output-path",
248 cl::desc("Path to where .dwo files or dwp file will be written out to."),
249 cl::init(""), cl::cat(BoltCategory));
251 static cl::opt<bool>
252 WriteDWP("write-dwp",
253 cl::desc("output a single dwarf package file (dwp) instead of "
254 "multiple non-relocatable dwarf object files (dwo)."),
255 cl::init(false), cl::cat(BoltCategory));
257 static cl::opt<bool>
258 DebugSkeletonCu("debug-skeleton-cu",
259 cl::desc("prints out offsetrs for abbrev and debu_info of "
260 "Skeleton CUs that get patched."),
261 cl::ZeroOrMore, cl::Hidden, cl::init(false),
262 cl::cat(BoltCategory));
264 static cl::opt<unsigned> BatchSize(
265 "cu-processing-batch-size",
266 cl::desc(
267 "Specifies the size of batches for processing CUs. Higher number has "
268 "better performance, but more memory usage. Default value is 1."),
269 cl::Hidden, cl::init(1), cl::cat(BoltCategory));
271 static cl::opt<bool> AlwaysConvertToRanges(
272 "always-convert-to-ranges",
273 cl::desc("This option is for testing purposes only. It forces BOLT to "
274 "convert low_pc/high_pc to ranges always."),
275 cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));
276 } // namespace opts
278 static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
279 uint64_t &LowPC, uint64_t &HighPC,
280 uint64_t &SectionIndex) {
281 DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);
282 DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
283 if (!DvalLowPc || !DvalHighPc)
284 return false;
286 dwarf::Form Form = DvalLowPc.getForm();
287 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
288 uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue();
289 if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx ||
290 AddrOffset) {
292 uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue;
293 std::optional<object::SectionedAddress> SA =
294 DU.getAddrOffsetSectionItem(Index);
295 if (!SA)
296 return false;
297 if (AddrOffset)
298 SA->Address += (LowPcValue & 0xffffffff);
300 LowPC = SA->Address;
301 SectionIndex = SA->SectionIndex;
302 } else {
303 LowPC = LowPcValue;
304 SectionIndex = 0;
306 if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
307 HighPC = DvalHighPc.getDIEInteger().getValue();
308 else
309 HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
311 return true;
314 static Expected<llvm::DWARFAddressRangesVector>
315 getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
316 uint64_t LowPC, HighPC, Index;
317 if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index))
318 return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
319 if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) {
320 if (Dval.getForm() == dwarf::DW_FORM_rnglistx)
321 return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue());
323 return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue());
326 return DWARFAddressRangesVector();
329 static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
330 const DIEValue &AttrVal) {
331 DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());
332 if (std::optional<object::SectionedAddress> SA =
333 DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU))
334 return SA->Address;
335 return std::nullopt;
338 /// Returns DWO Name to be used. Handles case where user specifies output DWO
339 /// directory, and there are duplicate names. Assumes DWO ID is unique.
340 static std::string
341 getDWOName(llvm::DWARFUnit &CU,
342 std::unordered_map<std::string, uint32_t> &NameToIndexMap) {
343 std::optional<uint64_t> DWOId = CU.getDWOId();
344 assert(DWOId && "DWO ID not found.");
345 (void)DWOId;
347 std::string DWOName = dwarf::toString(
348 CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
349 "");
350 assert(!DWOName.empty() &&
351 "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exists.");
352 if (!opts::DwarfOutputPath.empty()) {
353 auto Iter = NameToIndexMap.find(DWOName);
354 if (Iter == NameToIndexMap.end())
355 Iter = NameToIndexMap.insert({DWOName, 0}).first;
356 DWOName.append(std::to_string(Iter->second));
357 ++Iter->second;
359 DWOName.append(".dwo");
360 return DWOName;
363 static std::unique_ptr<DIEStreamer>
364 createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
365 StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
366 DWARFRewriter &Rewriter) {
368 std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
369 &DIEBldr, Rewriter, llvm::DWARFLinker::OutputFileType::Object, OutFile,
370 [](StringRef Input) -> StringRef { return Input; },
371 [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
372 Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
373 if (Err)
374 errs()
375 << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
376 << toString(std::move(Err)) << "\n";
377 return Streamer;
380 static DWARFRewriter::UnitMeta
381 emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer, DWARFUnit &Unit) {
382 DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit);
383 const DIEBuilder::DWARFUnitInfo &U = DIEBldr.getUnitInfoByDwarfUnit(Unit);
384 Streamer.emitUnit(Unit, *UnitDIE);
385 uint64_t TypeHash = 0;
386 if (DWARFTypeUnit *DTU = dyn_cast_or_null<DWARFTypeUnit>(&Unit))
387 TypeHash = DTU->getTypeHash();
388 return {U.UnitOffset, U.UnitLength, TypeHash};
391 static void emitDWOBuilder(const std::string &DWOName,
392 DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
393 const DWARFUnit &SplitCU, DWARFUnit &CU,
394 DWARFRewriter::DWPState &State,
395 DebugLocWriter &LocWriter) {
396 // Populate debug_info and debug_abbrev for current dwo into StringRef.
397 DWODIEBuilder.generateAbbrevs();
398 DWODIEBuilder.finish();
400 SmallVector<char, 20> OutBuffer;
401 std::shared_ptr<raw_svector_ostream> ObjOS =
402 std::make_shared<raw_svector_ostream>(OutBuffer);
403 const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();
404 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
405 std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(
406 *TheTriple, *ObjOS, "DwoStreamerInitAug2", DWODIEBuilder, Rewriter);
407 DWARFRewriter::UnitMetaVectorType TUMetaVector;
408 DWARFRewriter::UnitMeta CUMI = {0, 0, 0};
409 if (SplitCU.getContext().getMaxDWOVersion() >= 5) {
410 // TODO: Handle DWP as input. Right now it will iterate over all of CUs and
411 // TUs
412 for (std::unique_ptr<llvm::DWARFUnit> &CU :
413 SplitCU.getContext().dwo_info_section_units()) {
414 DWARFRewriter::UnitMeta MI =
415 emitUnit(DWODIEBuilder, *Streamer, *CU.get());
416 if (CU->isTypeUnit())
417 TUMetaVector.emplace_back(MI);
418 else
419 CUMI = MI;
421 } else {
422 for (std::unique_ptr<llvm::DWARFUnit> &CU :
423 SplitCU.getContext().dwo_compile_units())
424 emitUnit(DWODIEBuilder, *Streamer, *CU.get());
426 // emit debug_types sections for dwarf4
427 for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector()) {
428 DWARFRewriter::UnitMeta MI = emitUnit(DWODIEBuilder, *Streamer, *CU);
429 TUMetaVector.emplace_back(MI);
433 Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(),
434 SplitCU.getContext().getMaxVersion());
435 Streamer->finish();
437 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
438 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
439 std::unique_ptr<object::ObjectFile> Obj = cantFail(
440 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
441 "error creating in-memory object");
443 DWARFRewriter::OverriddenSectionsMap OverriddenSections;
444 for (const SectionRef &Secs : Obj->sections()) {
445 StringRef Contents = cantFail(Secs.getContents());
446 StringRef Name = cantFail(Secs.getName());
447 DWARFSectionKind Kind =
448 StringSwitch<DWARFSectionKind>(Name)
449 .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV)
450 .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO)
451 .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES)
452 .Default(DWARFSectionKind::DW_SECT_EXT_unknown);
453 if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)
454 continue;
455 OverriddenSections[Kind] = Contents;
457 if (opts::WriteDWP)
458 Rewriter.updateDWP(CU, OverriddenSections, CUMI, TUMetaVector, State,
459 LocWriter);
460 else
461 Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter);
464 void DWARFRewriter::addStringHelper(DIEBuilder &DIEBldr, DIE &Die,
465 const DWARFUnit &Unit,
466 DIEValue &DIEAttrInfo, StringRef Str) {
467 uint32_t NewOffset = StrWriter->addString(Str);
468 if (Unit.getVersion() == 5) {
469 StrOffstsWriter->updateAddressMap(DIEAttrInfo.getDIEInteger().getValue(),
470 NewOffset);
471 return;
473 DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(),
474 DIEInteger(NewOffset));
477 using DWARFUnitVec = std::vector<DWARFUnit *>;
478 using CUPartitionVector = std::vector<DWARFUnitVec>;
479 /// Partitions CUs in to buckets. Bucket size is controlled by
480 /// cu-processing-batch-size. All the CUs that have cross CU reference reference
481 /// as a source are put in to the same initial bucket.
482 static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {
483 CUPartitionVector Vec(2);
484 unsigned Counter = 0;
485 const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();
486 for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {
487 Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =
488 Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset());
489 if (!AbbrDeclSet) {
490 consumeError(AbbrDeclSet.takeError());
491 return Vec;
493 bool CrossCURefFound = false;
494 for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) {
495 for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr :
496 Decl.attributes()) {
497 if (Attr.Form == dwarf::DW_FORM_ref_addr) {
498 CrossCURefFound = true;
499 break;
502 if (CrossCURefFound)
503 break;
505 if (CrossCURefFound) {
506 Vec[0].push_back(CU.get());
507 } else {
508 ++Counter;
509 Vec.back().push_back(CU.get());
511 if (Counter % opts::BatchSize == 0 && !Vec.back().empty())
512 Vec.push_back({});
514 return Vec;
517 void DWARFRewriter::updateDebugInfo() {
518 ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
519 if (!DebugInfo)
520 return;
522 ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
523 StrWriter = std::make_unique<DebugStrWriter>(BC);
525 StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>();
527 if (!opts::DeterministicDebugInfo) {
528 opts::DeterministicDebugInfo = true;
529 errs() << "BOLT-WARNING: --deterministic-debuginfo is being deprecated\n";
532 if (BC.isDWARF5Used()) {
533 AddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC);
534 RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();
535 DebugRangeListsSectionWriter::setAddressWriter(AddrWriter.get());
536 } else {
537 AddrWriter = std::make_unique<DebugAddrWriter>(&BC);
540 if (BC.isDWARFLegacyUsed())
541 LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
543 DebugLoclistWriter::setAddressWriter(AddrWriter.get());
545 uint32_t CUIndex = 0;
546 std::mutex AccessMutex;
547 // Needs to be invoked in the same order as CUs are processed.
548 auto createRangeLocList = [&](DWARFUnit &CU) -> DebugLocWriter * {
549 std::lock_guard<std::mutex> Lock(AccessMutex);
550 const uint16_t DwarfVersion = CU.getVersion();
551 if (DwarfVersion >= 5) {
552 LocListWritersByCU[CUIndex] =
553 std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false);
555 if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
556 assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
557 "RangeLists writer for DWO unit already exists.");
558 auto RangeListsSectionWriter =
559 std::make_unique<DebugRangeListsSectionWriter>();
560 RangeListsSectionWriter->initSection(CU);
561 RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter);
564 } else {
565 LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
567 return LocListWritersByCU[CUIndex++].get();
570 // Unordered maps to handle name collision if output DWO directory is
571 // specified.
572 std::unordered_map<std::string, uint32_t> NameToIndexMap;
574 auto updateDWONameCompDir = [&](DWARFUnit &Unit, DIEBuilder &DIEBldr,
575 DIE &UnitDIE) -> std::string {
576 DIEValue DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_dwo_name);
577 if (!DWONameAttrInfo)
578 DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name);
579 assert(DWONameAttrInfo && "DW_AT_dwo_name is not in Skeleton CU.");
580 std::string ObjectName;
583 std::lock_guard<std::mutex> Lock(AccessMutex);
584 ObjectName = getDWOName(Unit, NameToIndexMap);
586 addStringHelper(DIEBldr, UnitDIE, Unit, DWONameAttrInfo,
587 ObjectName.c_str());
589 DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir);
590 assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU.");
592 if (!opts::DwarfOutputPath.empty()) {
593 addStringHelper(DIEBldr, UnitDIE, Unit, CompDirAttrInfo,
594 opts::DwarfOutputPath.c_str());
596 return ObjectName;
599 DWPState State;
600 if (opts::WriteDWP)
601 initDWPState(State);
602 auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) {
603 // Check if the unit is a skeleton and we need special updates for it and
604 // its matching split/DWO CU.
605 std::optional<DWARFUnit *> SplitCU;
606 std::optional<uint64_t> RangesBase;
607 std::optional<uint64_t> DWOId = Unit->getDWOId();
608 StrOffstsWriter->initialize(Unit->getStringOffsetSection(),
609 Unit->getStringOffsetsTableContribution());
610 if (DWOId)
611 SplitCU = BC.getDWOCU(*DWOId);
612 DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit);
613 DebugRangesSectionWriter *RangesSectionWriter =
614 Unit->getVersion() >= 5 ? RangeListsSectionWriter.get()
615 : LegacyRangesSectionWriter.get();
616 // Skipping CUs that failed to load.
617 if (SplitCU) {
618 DIEBuilder DWODIEBuilder(&(*SplitCU)->getContext(), true);
619 DWODIEBuilder.buildBoth();
620 std::string DWOName = updateDWONameCompDir(
621 *Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
623 DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true);
624 DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
625 if (Unit->getVersion() >= 5) {
626 TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
627 } else {
628 RangesBase = RangesSectionWriter->getSectionOffset();
629 // For DWARF5 there is now .debug_rnglists.dwo, so don't need to
630 // update rnglists base.
631 if (RangesBase) {
632 DwoRangesBase[*DWOId] = *RangesBase;
633 setDwoRangesBase(*DWOId, *RangesBase);
637 updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter,
638 *TempRangesSectionWriter);
639 DebugLocDWoWriter.finalize(DWODIEBuilder,
640 *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU));
641 if (Unit->getVersion() >= 5)
642 TempRangesSectionWriter->finalizeSection();
644 emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
645 DebugLocDWoWriter);
648 if (Unit->getVersion() >= 5) {
649 RangesBase = RangesSectionWriter->getSectionOffset() +
650 getDWARF5RngListLocListHeaderSize();
651 RangesSectionWriter->initSection(*Unit);
652 StrOffstsWriter->finalizeSection(*Unit, *DIEBlder);
655 updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter,
656 RangesBase);
657 DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
658 if (Unit->getVersion() >= 5)
659 RangesSectionWriter->finalizeSection();
660 AddrWriter->update(*DIEBlder, *Unit);
663 DIEBuilder DIEBlder(BC.DwCtx.get());
664 DIEBlder.buildTypeUnits();
665 SmallVector<char, 20> OutBuffer;
666 std::unique_ptr<raw_svector_ostream> ObjOS =
667 std::make_unique<raw_svector_ostream>(OutBuffer);
668 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
669 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
670 std::unique_ptr<DIEStreamer> Streamer =
671 createDIEStreamer(*TheTriple, *ObjOS, "TypeStreamer", DIEBlder, *this);
672 CUOffsetMap OffsetMap = finalizeTypeSections(DIEBlder, *Streamer);
674 const bool SingleThreadedMode =
675 opts::NoThreads || opts::DeterministicDebugInfo;
676 if (!SingleThreadedMode)
677 DIEBlder.buildCompileUnits();
678 if (SingleThreadedMode) {
679 CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
680 for (std::vector<DWARFUnit *> &Vec : PartVec) {
681 DIEBlder.buildCompileUnits(Vec);
682 for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
683 processUnitDIE(CU, &DIEBlder);
684 finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
685 DIEBlder.getProcessedCUs());
687 } else {
688 // Update unit debug info in parallel
689 ThreadPool &ThreadPool = ParallelUtilities::getThreadPool();
690 for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
691 ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder);
692 ThreadPool.wait();
695 if (opts::WriteDWP)
696 finalizeDWP(State);
698 finalizeDebugSections(DIEBlder, *Streamer, *ObjOS, OffsetMap);
699 updateGdbIndexSection(OffsetMap, CUIndex);
702 void DWARFRewriter::updateUnitDebugInfo(
703 DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
704 DebugRangesSectionWriter &RangesSectionWriter,
705 std::optional<uint64_t> RangesBase) {
706 // Cache debug ranges so that the offset for identical ranges could be reused.
707 std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
709 uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();
710 uint64_t NextCUOffset = Unit.getNextUnitOffset();
711 const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =
712 DIEBldr.getDIEsByUnit(Unit);
714 // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
715 auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,
716 const DIEValue &HighPCVal, uint64_t LowPC,
717 const uint64_t HighPC) {
718 dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;
719 dwarf::Form FormLowPC = dwarf::DW_FORM_addr;
720 dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;
721 dwarf::Form FormHighPC = dwarf::DW_FORM_data4;
722 const uint32_t Size = HighPC - LowPC;
723 // Whatever was generated is not low_pc/high_pc, so will reset to
724 // default for size 1.
725 if (!LowPCVal || !HighPCVal) {
726 if (Unit.getVersion() >= 5)
727 FormLowPC = dwarf::DW_FORM_addrx;
728 else if (Unit.isDWOUnit())
729 FormLowPC = dwarf::DW_FORM_GNU_addr_index;
730 } else {
731 AttrLowPC = LowPCVal.getAttribute();
732 FormLowPC = LowPCVal.getForm();
733 AttrHighPC = HighPCVal.getAttribute();
734 FormHighPC = HighPCVal.getForm();
737 if (FormLowPC == dwarf::DW_FORM_addrx ||
738 FormLowPC == dwarf::DW_FORM_GNU_addr_index)
739 LowPC = AddrWriter->getIndexFromAddress(LowPC, Unit);
741 if (LowPCVal)
742 DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
743 else
744 DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
745 if (HighPCVal) {
746 DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
747 } else {
748 DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges);
749 DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
753 for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {
754 DIE *Die = DI->Die;
755 switch (Die->getTag()) {
756 case dwarf::DW_TAG_compile_unit:
757 case dwarf::DW_TAG_skeleton_unit: {
758 // For dwarf5 section 3.1.3
759 // The following attributes are not part of a split full compilation unit
760 // entry but instead are inherited (if present) from the corresponding
761 // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges,
762 // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base,
763 // DW_AT_addr_base and DW_AT_rnglists_base.
764 if (Unit.getVersion() == 5 && Unit.isDWOUnit())
765 continue;
766 auto ModuleRangesOrError = getDIEAddressRanges(*Die, Unit);
767 if (!ModuleRangesOrError) {
768 consumeError(ModuleRangesOrError.takeError());
769 break;
771 DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;
772 DebugAddressRangesVector OutputRanges =
773 BC.translateModuleAddressRanges(ModuleRanges);
774 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
775 // For a case where LLD GCs only function used in the CU.
776 // If CU doesn't have DW_AT_low_pc we are not going to convert,
777 // so don't need to do anything.
778 if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)
779 OutputRanges.push_back({0, 0});
780 const uint64_t RangesSectionOffset =
781 RangesSectionWriter.addRanges(OutputRanges);
782 if (!Unit.isDWOUnit())
783 ARangesSectionWriter->addCURanges(Unit.getOffset(),
784 std::move(OutputRanges));
785 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset,
786 RangesBase);
787 DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list);
788 if (LineTablePatchMap.count(&Unit))
789 DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list,
790 StmtListAttrVal.getForm(),
791 DIEInteger(LineTablePatchMap[&Unit]));
792 break;
795 case dwarf::DW_TAG_subprogram: {
796 // Get function address either from ranges or [LowPC, HighPC) pair.
797 uint64_t Address = UINT64_MAX;
798 uint64_t SectionIndex, HighPC;
799 DebugAddressRangesVector FunctionRanges;
800 if (!getLowAndHighPC(*Die, Unit, Address, HighPC, SectionIndex)) {
801 Expected<DWARFAddressRangesVector> RangesOrError =
802 getDIEAddressRanges(*Die, Unit);
803 if (!RangesOrError) {
804 consumeError(RangesOrError.takeError());
805 break;
807 DWARFAddressRangesVector Ranges = *RangesOrError;
808 // Not a function definition.
809 if (Ranges.empty())
810 break;
812 for (const DWARFAddressRange &Range : Ranges) {
813 if (const BinaryFunction *Function =
814 BC.getBinaryFunctionAtAddress(Range.LowPC))
815 FunctionRanges.append(Function->getOutputAddressRanges());
817 } else {
818 if (const BinaryFunction *Function =
819 BC.getBinaryFunctionAtAddress(Address))
820 FunctionRanges = Function->getOutputAddressRanges();
823 // Clear cached ranges as the new function will have its own set.
824 CachedRanges.clear();
825 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
826 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
827 if (FunctionRanges.empty()) {
828 if (LowPCVal && HighPCVal) {
829 FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()});
830 } else {
831 // I haven't seen this case, but who knows what other compilers
832 // generate.
833 FunctionRanges.push_back({0, 1});
834 errs() << "BOLT-WARNING: [internal-dwarf-error]: subprogram got GCed "
835 "by the linker, DW_AT_ranges is used\n";
839 if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) {
840 updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC,
841 FunctionRanges.back().HighPC);
842 break;
845 updateDWARFObjectAddressRanges(
846 Unit, DIEBldr, *Die, RangesSectionWriter.addRanges(FunctionRanges));
848 break;
850 case dwarf::DW_TAG_lexical_block:
851 case dwarf::DW_TAG_inlined_subroutine:
852 case dwarf::DW_TAG_try_block:
853 case dwarf::DW_TAG_catch_block: {
854 uint64_t RangesSectionOffset = 0;
855 Expected<DWARFAddressRangesVector> RangesOrError =
856 getDIEAddressRanges(*Die, Unit);
857 const BinaryFunction *Function =
858 RangesOrError && !RangesOrError->empty()
859 ? BC.getBinaryFunctionContainingAddress(
860 RangesOrError->front().LowPC)
861 : nullptr;
862 DebugAddressRangesVector OutputRanges;
863 if (Function) {
864 OutputRanges = Function->translateInputToOutputRanges(*RangesOrError);
865 LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {
866 dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
867 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"
868 << Twine::utohexstr(Unit.getOffset()) << '\n';
870 if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {
871 RangesSectionOffset = RangesSectionWriter.addRanges(
872 std::move(OutputRanges), CachedRanges);
873 OutputRanges.clear();
874 } else if (OutputRanges.empty()) {
875 OutputRanges.push_back({RangesOrError.get().front().LowPC,
876 RangesOrError.get().front().HighPC});
878 } else if (!RangesOrError) {
879 consumeError(RangesOrError.takeError());
880 } else {
881 OutputRanges.push_back({0, !RangesOrError->empty()
882 ? RangesOrError.get().front().HighPC
883 : 0});
885 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
886 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
887 if (OutputRanges.size() == 1) {
888 updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,
889 OutputRanges.back().HighPC);
890 break;
892 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset);
893 break;
895 case dwarf::DW_TAG_call_site: {
896 auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void {
897 std::optional<uint64_t> Address = getAsAddress(Unit, AttrVal);
898 const BinaryFunction *Function =
899 BC.getBinaryFunctionContainingAddress(*Address);
900 uint64_t UpdatedAddress = *Address;
901 if (Function)
902 UpdatedAddress =
903 Function->translateInputToOutputAddress(UpdatedAddress);
905 if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {
906 const uint32_t Index =
907 AddrWriter->getIndexFromAddress(UpdatedAddress, Unit);
908 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
909 DIEInteger(Index));
910 } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {
911 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
912 DIEInteger(UpdatedAddress));
913 } else {
914 errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";
917 DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc);
918 if (CallPcAttrVal)
919 patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");
921 DIEValue CallRetPcAttrVal =
922 Die->findAttribute(dwarf::DW_AT_call_return_pc);
923 if (CallRetPcAttrVal)
924 patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc");
926 break;
928 default: {
929 // Handle any tag that can have DW_AT_location attribute.
930 DIEValue LocAttrInfo = Die->findAttribute(dwarf::DW_AT_location);
931 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
932 if (LocAttrInfo) {
933 if (doesFormBelongToClass(LocAttrInfo.getForm(),
934 DWARFFormValue::FC_Constant,
935 Unit.getVersion()) ||
936 doesFormBelongToClass(LocAttrInfo.getForm(),
937 DWARFFormValue::FC_SectionOffset,
938 Unit.getVersion())) {
939 uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx
940 ? LocAttrInfo.getDIELocList().getValue()
941 : LocAttrInfo.getDIEInteger().getValue();
942 DebugLocationsVector InputLL;
944 std::optional<object::SectionedAddress> SectionAddress =
945 Unit.getBaseAddress();
946 uint64_t BaseAddress = 0;
947 if (SectionAddress)
948 BaseAddress = SectionAddress->Address;
950 if (Unit.getVersion() >= 5 &&
951 LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) {
952 std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset);
953 assert(LocOffset && "Location Offset is invalid.");
954 Offset = *LocOffset;
957 Error E = Unit.getLocationTable().visitLocationList(
958 &Offset, [&](const DWARFLocationEntry &Entry) {
959 switch (Entry.Kind) {
960 default:
961 llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
962 case dwarf::DW_LLE_end_of_list:
963 return false;
964 case dwarf::DW_LLE_base_address: {
965 assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
966 "absolute address expected");
967 BaseAddress = Entry.Value0;
968 break;
970 case dwarf::DW_LLE_offset_pair:
971 assert(
972 (Entry.SectionIndex == SectionedAddress::UndefSection &&
973 (!Unit.isDWOUnit() || Unit.getVersion() == 5)) &&
974 "absolute address expected");
975 InputLL.emplace_back(DebugLocationEntry{
976 BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,
977 Entry.Loc});
978 break;
979 case dwarf::DW_LLE_start_length:
980 InputLL.emplace_back(DebugLocationEntry{
981 Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});
982 break;
983 case dwarf::DW_LLE_base_addressx: {
984 std::optional<object::SectionedAddress> EntryAddress =
985 Unit.getAddrOffsetSectionItem(Entry.Value0);
986 assert(EntryAddress && "base Address not found.");
987 BaseAddress = EntryAddress->Address;
988 break;
990 case dwarf::DW_LLE_startx_length: {
991 std::optional<object::SectionedAddress> EntryAddress =
992 Unit.getAddrOffsetSectionItem(Entry.Value0);
993 assert(EntryAddress && "Address does not exist.");
994 InputLL.emplace_back(DebugLocationEntry{
995 EntryAddress->Address,
996 EntryAddress->Address + Entry.Value1, Entry.Loc});
997 break;
999 case dwarf::DW_LLE_startx_endx: {
1000 std::optional<object::SectionedAddress> StartAddress =
1001 Unit.getAddrOffsetSectionItem(Entry.Value0);
1002 assert(StartAddress && "Start Address does not exist.");
1003 std::optional<object::SectionedAddress> EndAddress =
1004 Unit.getAddrOffsetSectionItem(Entry.Value1);
1005 assert(EndAddress && "Start Address does not exist.");
1006 InputLL.emplace_back(DebugLocationEntry{
1007 StartAddress->Address, EndAddress->Address, Entry.Loc});
1008 break;
1011 return true;
1014 if (E || InputLL.empty()) {
1015 consumeError(std::move(E));
1016 errs() << "BOLT-WARNING: empty location list detected at 0x"
1017 << Twine::utohexstr(Offset) << " for DIE at 0x" << Die
1018 << " in CU at 0x" << Twine::utohexstr(Unit.getOffset())
1019 << '\n';
1020 } else {
1021 const uint64_t Address = InputLL.front().LowPC;
1022 DebugLocationsVector OutputLL;
1023 if (const BinaryFunction *Function =
1024 BC.getBinaryFunctionContainingAddress(Address)) {
1025 OutputLL = Function->translateInputToOutputLocationList(InputLL);
1026 LLVM_DEBUG(if (OutputLL.empty()) {
1027 dbgs() << "BOLT-DEBUG: location list translated to an empty "
1028 "one at 0x"
1029 << Die << " in CU at 0x"
1030 << Twine::utohexstr(Unit.getOffset()) << '\n';
1032 } else {
1033 // It's possible for a subprogram to be removed and to have
1034 // address of 0. Adding this entry to output to preserve debug
1035 // information.
1036 OutputLL = InputLL;
1038 DebugLocWriter.addList(DIEBldr, *Die, LocAttrInfo, OutputLL);
1040 } else {
1041 assert((doesFormBelongToClass(LocAttrInfo.getForm(),
1042 DWARFFormValue::FC_Exprloc,
1043 Unit.getVersion()) ||
1044 doesFormBelongToClass(LocAttrInfo.getForm(),
1045 DWARFFormValue::FC_Block,
1046 Unit.getVersion())) &&
1047 "unexpected DW_AT_location form");
1048 if (Unit.isDWOUnit() || Unit.getVersion() >= 5) {
1049 std::vector<uint8_t> Sblock;
1050 DIEValueList *AttrLocValList;
1051 if (doesFormBelongToClass(LocAttrInfo.getForm(),
1052 DWARFFormValue::FC_Exprloc,
1053 Unit.getVersion())) {
1054 for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {
1055 Sblock.push_back(Val.getDIEInteger().getValue());
1057 DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc());
1058 AttrLocValList = static_cast<DIEValueList *>(LocAttr);
1059 } else {
1060 for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) {
1061 Sblock.push_back(Val.getDIEInteger().getValue());
1063 DIEBlock *BlockAttr =
1064 const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock());
1065 AttrLocValList = static_cast<DIEValueList *>(BlockAttr);
1067 ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);
1068 DataExtractor Data(
1069 StringRef((const char *)Expr.data(), Expr.size()),
1070 Unit.getContext().isLittleEndian(), 0);
1071 DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
1072 Unit.getFormParams().Format);
1073 uint32_t PrevOffset = 0;
1074 DIEValueList *NewAttr;
1075 DIEValue Value;
1076 uint32_t NewExprSize = 0;
1077 DIELoc *Loc = nullptr;
1078 DIEBlock *Block = nullptr;
1079 if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) {
1080 Loc = DIEBldr.allocateDIEValue<DIELoc>();
1081 NewAttr = Loc;
1082 Value = DIEValue(LocAttrInfo.getAttribute(),
1083 LocAttrInfo.getForm(), Loc);
1084 } else if (doesFormBelongToClass(LocAttrInfo.getForm(),
1085 DWARFFormValue::FC_Block,
1086 Unit.getVersion())) {
1087 Block = DIEBldr.allocateDIEValue<DIEBlock>();
1088 NewAttr = Block;
1089 Value = DIEValue(LocAttrInfo.getAttribute(),
1090 LocAttrInfo.getForm(), Block);
1091 } else {
1092 errs() << "BOLT-WARNING: Unexpected Form value in Updating "
1093 "DW_AT_Location\n";
1094 continue;
1097 for (const DWARFExpression::Operation &Expr : LocExpr) {
1098 uint32_t CurEndOffset = PrevOffset + 1;
1099 if (Expr.getDescription().Op.size() == 1)
1100 CurEndOffset = Expr.getOperandEndOffset(0);
1101 if (Expr.getDescription().Op.size() == 2)
1102 CurEndOffset = Expr.getOperandEndOffset(1);
1103 if (Expr.getDescription().Op.size() > 2)
1104 errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "
1105 "number of operands.\n";
1106 // not addr index, just copy.
1107 if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
1108 Expr.getCode() == dwarf::DW_OP_addrx)) {
1109 auto Itr = AttrLocValList->values().begin();
1110 std::advance(Itr, PrevOffset);
1111 uint32_t CopyNum = CurEndOffset - PrevOffset;
1112 NewExprSize += CopyNum;
1113 while (CopyNum--) {
1114 DIEBldr.addValue(NewAttr, *Itr);
1115 std::advance(Itr, 1);
1117 } else {
1118 const uint64_t Index = Expr.getRawOperand(0);
1119 std::optional<object::SectionedAddress> EntryAddress =
1120 Unit.getAddrOffsetSectionItem(Index);
1121 assert(EntryAddress && "Address is not found.");
1122 assert(Index <= std::numeric_limits<uint32_t>::max() &&
1123 "Invalid Operand Index.");
1124 const uint32_t AddrIndex = AddrWriter->getIndexFromAddress(
1125 EntryAddress->Address, Unit);
1126 // update Index into .debug_address section for DW_AT_location.
1127 // The Size field is not stored in IR, we need to minus 1 in
1128 // offset for each expr.
1129 SmallString<8> Tmp;
1130 raw_svector_ostream OSE(Tmp);
1131 encodeULEB128(AddrIndex, OSE);
1133 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1134 dwarf::DW_FORM_data1,
1135 DIEInteger(Expr.getCode()));
1136 NewExprSize += 1;
1137 for (uint8_t Byte : Tmp) {
1138 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1139 dwarf::DW_FORM_data1, DIEInteger(Byte));
1140 NewExprSize += 1;
1143 PrevOffset = CurEndOffset;
1146 // update the size since the index might be changed
1147 if (Loc)
1148 Loc->setSize(NewExprSize);
1149 else
1150 Block->setSize(NewExprSize);
1151 DIEBldr.replaceValue(Die, LocAttrInfo.getAttribute(),
1152 LocAttrInfo.getForm(), Value);
1155 } else if (LowPCAttrInfo) {
1156 const std::optional<uint64_t> Result =
1157 LowPCAttrInfo.getDIEInteger().getValue();
1158 if (Result.has_value()) {
1159 const uint64_t Address = Result.value();
1160 uint64_t NewAddress = 0;
1161 if (const BinaryFunction *Function =
1162 BC.getBinaryFunctionContainingAddress(Address)) {
1163 NewAddress = Function->translateInputToOutputAddress(Address);
1164 LLVM_DEBUG(dbgs()
1165 << "BOLT-DEBUG: Fixing low_pc 0x"
1166 << Twine::utohexstr(Address) << " for DIE with tag "
1167 << Die->getTag() << " to 0x"
1168 << Twine::utohexstr(NewAddress) << '\n');
1171 dwarf::Form Form = LowPCAttrInfo.getForm();
1172 assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&
1173 "DW_FORM_LLVM_addrx_offset is not supported");
1174 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
1175 if (Form == dwarf::DW_FORM_addrx ||
1176 Form == dwarf::DW_FORM_GNU_addr_index) {
1177 const uint32_t Index = AddrWriter->getIndexFromAddress(
1178 NewAddress ? NewAddress : Address, Unit);
1179 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1180 LowPCAttrInfo.getForm(), DIEInteger(Index));
1181 } else {
1182 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1183 LowPCAttrInfo.getForm(),
1184 DIEInteger(NewAddress));
1186 } else if (opts::Verbosity >= 1) {
1187 errs() << "BOLT-WARNING: unexpected form value for attribute "
1188 "LowPCAttrInfo\n";
1194 if (DIEOffset > NextCUOffset)
1195 errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"
1196 << Twine::utohexstr(Unit.getOffset()) << '\n';
1199 void DWARFRewriter::updateDWARFObjectAddressRanges(
1200 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
1201 std::optional<uint64_t> RangesBase) {
1203 if (RangesBase) {
1204 // If DW_AT_GNU_ranges_base is present, update it. No further modifications
1205 // are needed for ranges base.
1207 DIEValue RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_GNU_ranges_base);
1208 if (!RangesBaseInfo) {
1209 RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_rnglists_base);
1212 if (RangesBaseInfo) {
1213 DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(),
1214 RangesBaseInfo.getForm(),
1215 DIEInteger(static_cast<uint32_t>(*RangesBase)));
1216 RangesBase = std::nullopt;
1220 DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc);
1221 DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges);
1222 if (RangesAttrInfo) {
1223 // Case 1: The object was already non-contiguous and had DW_AT_ranges.
1224 // In this case we simply need to update the value of DW_AT_ranges
1225 // and introduce DW_AT_GNU_ranges_base if required.
1226 // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
1227 bool NeedConverted = false;
1229 if (Unit.getVersion() >= 5 &&
1230 RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset)
1231 NeedConverted = true;
1233 uint64_t CurRangeBase = 0;
1234 if (Unit.isDWOUnit()) {
1235 if (std::optional<uint64_t> DWOId = Unit.getDWOId())
1236 CurRangeBase = getDwoRangesBase(*DWOId);
1237 else
1238 errs() << "BOLT-WARNING: [internal-dwarf-error]: DWOId is not found "
1239 "for DWO Unit.";
1241 if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx)
1242 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx,
1243 DIEInteger(DebugRangesOffset));
1244 else
1245 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(),
1246 DIEInteger(DebugRangesOffset - CurRangeBase));
1248 if (!RangesBase) {
1249 if (LowPCAttrInfo &&
1250 LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index &&
1251 LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx)
1252 DIEBldr.replaceValue(&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(),
1253 DIEInteger(0));
1254 return;
1257 if (!(Die.getTag() == dwarf::DW_TAG_compile_unit ||
1258 Die.getTag() == dwarf::DW_TAG_skeleton_unit))
1259 return;
1261 // If we are at this point we are in the CU/Skeleton CU, and
1262 // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist.
1263 if (Unit.getVersion() <= 4)
1264 DIEBldr.addValue(&Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
1265 DIEInteger(*RangesBase));
1266 else if (Unit.getVersion() == 5)
1267 DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
1268 dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
1269 else
1270 DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
1271 dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
1272 return;
1275 // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
1276 // to back. Replace with new attributes and patch the DIE.
1277 DIEValue HighPCAttrInfo = Die.findAttribute(dwarf::DW_AT_high_pc);
1278 if (LowPCAttrInfo && HighPCAttrInfo) {
1280 convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset,
1281 LowPCAttrInfo, HighPCAttrInfo, RangesBase);
1282 } else if (!(Unit.isDWOUnit() &&
1283 Die.getTag() == dwarf::DW_TAG_compile_unit)) {
1284 if (opts::Verbosity >= 1)
1285 errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
1286 << Unit.getOffset() << '\n';
1290 void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
1291 ErrorOr<BinarySection &> DbgInfoSection =
1292 BC.getUniqueSectionByName(".debug_info");
1293 ErrorOr<BinarySection &> TypeInfoSection =
1294 BC.getUniqueSectionByName(".debug_types");
1295 assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||
1296 BC.DwCtx->getNumTypeUnits() == 0) &&
1297 "Was not able to retrieve Debug Types section.");
1299 // There is no direct connection between CU and TU, but same offsets,
1300 // encoded in DW_AT_stmt_list, into .debug_line get modified.
1301 // We take advantage of that to map original CU line table offsets to new
1302 // ones.
1303 std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;
1305 auto GetStatementListValue = [](DWARFUnit *Unit) {
1306 std::optional<DWARFFormValue> StmtList =
1307 Unit->getUnitDIE().find(dwarf::DW_AT_stmt_list);
1308 std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);
1309 assert(Offset && "Was not able to retreive value of DW_AT_stmt_list.");
1310 return *Offset;
1313 for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
1314 const unsigned CUID = CU->getOffset();
1315 MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
1316 if (!Label)
1317 continue;
1319 std::optional<AttrInfo> AttrVal =
1320 findAttributeInfo(CU.get()->getUnitDIE(), dwarf::DW_AT_stmt_list);
1321 if (!AttrVal)
1322 continue;
1324 const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
1325 DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset;
1326 assert(DbgInfoSection && ".debug_info section must exist");
1327 LineTablePatchMap[CU.get()] = LineTableOffset;
1330 for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units()) {
1331 DWARFUnit *Unit = TU.get();
1332 std::optional<AttrInfo> AttrVal =
1333 findAttributeInfo(TU.get()->getUnitDIE(), dwarf::DW_AT_stmt_list);
1334 if (!AttrVal)
1335 continue;
1336 auto Iter = DebugLineOffsetMap.find(GetStatementListValue(Unit));
1337 assert(Iter != DebugLineOffsetMap.end() &&
1338 "Type Unit Updated Line Number Entry does not exist.");
1339 TypeUnitRelocMap[Unit] = Iter->second;
1342 // Set .debug_info as finalized so it won't be skipped over when
1343 // we process sections while writing out the new binary. This ensures
1344 // that the pending relocations will be processed and not ignored.
1345 if (DbgInfoSection)
1346 DbgInfoSection->setIsFinalized();
1348 if (TypeInfoSection)
1349 TypeInfoSection->setIsFinalized();
1352 CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
1353 DIEStreamer &Streamer) {
1354 // update TypeUnit DW_AT_stmt_list with new .debug_line information.
1355 for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units()) {
1356 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*TU.get());
1357 DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);
1358 if (!StmtAttrInfo || !TypeUnitRelocMap.count(TU.get()))
1359 continue;
1360 DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,
1361 StmtAttrInfo.getForm(),
1362 DIEInteger(TypeUnitRelocMap[TU.get()]));
1365 // generate and populate abbrevs here
1366 DIEBlder.generateAbbrevs();
1367 DIEBlder.finish();
1368 SmallVector<char, 20> OutBuffer;
1369 std::shared_ptr<raw_svector_ostream> ObjOS =
1370 std::make_shared<raw_svector_ostream>(OutBuffer);
1371 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1372 auto TheTriple = std::make_unique<Triple>(File->makeTriple());
1373 std::unique_ptr<DIEStreamer> TypeStreamer =
1374 createDIEStreamer(*TheTriple, *ObjOS, "TypeStreamer", DIEBlder, *this);
1376 // generate debug_info and CUMap
1377 CUOffsetMap CUMap;
1378 for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1379 if (!CU->isTypeUnit())
1380 continue;
1381 emitUnit(DIEBlder, Streamer, *CU.get());
1382 uint32_t StartOffset = CUOffset;
1383 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get());
1384 CUOffset += CU.get()->getHeaderSize();
1385 CUOffset += UnitDIE->getSize();
1386 CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
1389 // Emit Type Unit of DWARF 4 to .debug_type section
1390 for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector())
1391 emitUnit(DIEBlder, *TypeStreamer, *TU);
1393 TypeStreamer->finish();
1395 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1396 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
1397 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1398 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1399 "error creating in-memory object");
1401 for (const SectionRef &Section : Obj->sections()) {
1402 StringRef Contents = cantFail(Section.getContents());
1403 StringRef Name = cantFail(Section.getName());
1404 if (Name.equals(".debug_types"))
1405 BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents),
1406 Contents.size());
1408 return CUMap;
1411 void DWARFRewriter::finalizeDebugSections(DIEBuilder &DIEBlder,
1412 DIEStreamer &Streamer,
1413 raw_svector_ostream &ObjOS,
1414 CUOffsetMap &CUMap) {
1415 if (StrWriter->isInitialized()) {
1416 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
1417 std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
1418 StrWriter->releaseBuffer();
1419 BC.registerOrUpdateNoteSection(".debug_str",
1420 copyByteArray(*DebugStrSectionContents),
1421 DebugStrSectionContents->size());
1424 if (StrOffstsWriter->isFinalized()) {
1425 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");
1426 std::unique_ptr<DebugStrOffsetsBufferVector>
1427 DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();
1428 BC.registerOrUpdateNoteSection(
1429 ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents),
1430 DebugStrOffsetsSectionContents->size());
1433 if (BC.isDWARFLegacyUsed()) {
1434 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1435 LegacyRangesSectionWriter->releaseBuffer();
1436 BC.registerOrUpdateNoteSection(".debug_ranges",
1437 copyByteArray(*RangesSectionContents),
1438 RangesSectionContents->size());
1441 if (BC.isDWARF5Used()) {
1442 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1443 RangeListsSectionWriter->releaseBuffer();
1444 BC.registerOrUpdateNoteSection(".debug_rnglists",
1445 copyByteArray(*RangesSectionContents),
1446 RangesSectionContents->size());
1449 if (BC.isDWARF5Used()) {
1450 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1451 makeFinalLocListsSection(DWARFVersion::DWARF5);
1452 if (!LocationListSectionContents->empty())
1453 BC.registerOrUpdateNoteSection(
1454 ".debug_loclists", copyByteArray(*LocationListSectionContents),
1455 LocationListSectionContents->size());
1458 if (BC.isDWARFLegacyUsed()) {
1459 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1460 makeFinalLocListsSection(DWARFVersion::DWARFLegacy);
1461 if (!LocationListSectionContents->empty())
1462 BC.registerOrUpdateNoteSection(
1463 ".debug_loc", copyByteArray(*LocationListSectionContents),
1464 LocationListSectionContents->size());
1467 // AddrWriter should be finalized after debug_loc since more addresses can be
1468 // added there.
1469 if (AddrWriter->isInitialized()) {
1470 AddressSectionBuffer AddressSectionContents = AddrWriter->finalize();
1471 BC.registerOrUpdateNoteSection(".debug_addr",
1472 copyByteArray(AddressSectionContents),
1473 AddressSectionContents.size());
1476 Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion());
1477 Streamer.finish();
1479 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1480 MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false);
1481 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1482 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1483 "error creating in-memory object");
1485 for (const SectionRef &Secs : Obj->sections()) {
1486 StringRef Contents = cantFail(Secs.getContents());
1487 StringRef Name = cantFail(Secs.getName());
1488 if (Name.equals(".debug_abbrev")) {
1489 BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents),
1490 Contents.size());
1491 } else if (Name.equals(".debug_info")) {
1492 BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents),
1493 Contents.size());
1497 // Skip .debug_aranges if we are re-generating .gdb_index.
1498 if (opts::KeepARanges || !BC.getGdbIndexSection()) {
1499 SmallVector<char, 16> ARangesBuffer;
1500 raw_svector_ostream OS(ARangesBuffer);
1502 auto MAB = std::unique_ptr<MCAsmBackend>(
1503 BC.TheTarget->createMCAsmBackend(*BC.STI, *BC.MRI, MCTargetOptions()));
1505 ARangesSectionWriter->writeARangesSection(OS, CUMap);
1506 const StringRef &ARangesContents = OS.str();
1508 BC.registerOrUpdateNoteSection(".debug_aranges",
1509 copyByteArray(ARangesContents),
1510 ARangesContents.size());
1514 void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
1515 DIEStreamer &Streamer,
1516 CUOffsetMap &CUMap,
1517 const std::list<DWARFUnit *> &CUs) {
1518 DIEBlder.generateAbbrevs();
1519 DIEBlder.finish();
1520 // generate debug_info and CUMap
1521 for (DWARFUnit *CU : CUs) {
1522 emitUnit(DIEBlder, Streamer, *CU);
1523 const uint32_t StartOffset = CUOffset;
1524 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);
1525 CUOffset += CU->getHeaderSize();
1526 CUOffset += UnitDIE->getSize();
1527 CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
1531 // Creates all the data structures necessary for creating MCStreamer.
1532 // They are passed by reference because they need to be kept around.
1533 // Also creates known debug sections. These are sections handled by
1534 // handleDebugDataPatching.
1535 namespace {
1537 std::unique_ptr<BinaryContext>
1538 createDwarfOnlyBC(const object::ObjectFile &File) {
1539 return cantFail(BinaryContext::createBinaryContext(
1540 &File, false,
1541 DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,
1542 nullptr, "", WithColor::defaultErrorHandler,
1543 WithColor::defaultWarningHandler)));
1546 StringMap<DWARFRewriter::KnownSectionsEntry>
1547 createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {
1548 StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {
1549 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
1550 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
1551 {"debug_str_offsets.dwo",
1552 {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},
1553 {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},
1554 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
1555 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
1556 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
1557 {"debug_loclists.dwo",
1558 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
1559 {"debug_rnglists.dwo",
1560 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};
1561 return KnownSectionsTemp;
1564 StringRef getSectionName(const SectionRef &Section) {
1565 Expected<StringRef> SectionName = Section.getName();
1566 assert(SectionName && "Invalid section name.");
1567 StringRef Name = *SectionName;
1568 Name = Name.substr(Name.find_first_not_of("._"));
1569 return Name;
1572 // Exctracts an appropriate slice if input is DWP.
1573 // Applies patches or overwrites the section.
1574 std::optional<StringRef> updateDebugData(
1575 DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
1576 const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
1577 MCStreamer &Streamer, DWARFRewriter &Writer,
1578 const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
1579 std::unique_ptr<DebugBufferVector> &OutputBuffer,
1580 DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
1581 const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {
1583 using DWOSectionContribution =
1584 const DWARFUnitIndex::Entry::SectionContribution;
1585 auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,
1586 StringRef OutData, DWARFSectionKind Sec,
1587 uint64_t &DWPOffset) -> StringRef {
1588 if (DWOEntry) {
1589 DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);
1590 DWPOffset = DWOContrubution->getOffset();
1591 OutData = OutData.substr(DWPOffset, DWOContrubution->getLength());
1593 return OutData;
1596 auto SectionIter = KnownSections.find(SectionName);
1597 if (SectionIter == KnownSections.end())
1598 return std::nullopt;
1599 Streamer.switchSection(SectionIter->second.first);
1600 uint64_t DWPOffset = 0;
1602 auto getOverridenSection =
1603 [&](DWARFSectionKind Kind) -> std::optional<StringRef> {
1604 auto Iter = OverridenSections.find(Kind);
1605 if (Iter == OverridenSections.end()) {
1606 errs()
1607 << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
1608 "section for: "
1609 << Twine::utohexstr(DWOId) << ".\n";
1610 return std::nullopt;
1612 return Iter->second;
1614 switch (SectionIter->second.second) {
1615 default: {
1616 if (!SectionName.equals("debug_str.dwo"))
1617 errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
1618 << "\n";
1619 return SectionContents;
1621 case DWARFSectionKind::DW_SECT_INFO: {
1622 return getOverridenSection(DWARFSectionKind::DW_SECT_INFO);
1624 case DWARFSectionKind::DW_SECT_EXT_TYPES: {
1625 return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);
1627 case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
1628 return getSliceData(CUDWOEntry, SectionContents,
1629 DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
1631 case DWARFSectionKind::DW_SECT_ABBREV: {
1632 return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV);
1634 case DWARFSectionKind::DW_SECT_EXT_LOC:
1635 case DWARFSectionKind::DW_SECT_LOCLISTS: {
1636 OutputBuffer = LocWriter.getBuffer();
1637 // Creating explicit StringRef here, otherwise
1638 // with impicit conversion it will take null byte as end of
1639 // string.
1640 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1641 OutputBuffer->size());
1643 case DWARFSectionKind::DW_SECT_LINE: {
1644 return getSliceData(CUDWOEntry, SectionContents,
1645 DWARFSectionKind::DW_SECT_LINE, DWPOffset);
1647 case DWARFSectionKind::DW_SECT_RNGLISTS: {
1648 assert(RangeListsWriter && "RangeListsWriter was not created.");
1649 OutputBuffer = RangeListsWriter->releaseBuffer();
1650 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1651 OutputBuffer->size());
1656 } // namespace
1658 void DWARFRewriter::initDWPState(DWPState &State) {
1659 SmallString<0> OutputNameStr;
1660 StringRef OutputName;
1661 if (opts::DwarfOutputPath.empty()) {
1662 OutputName =
1663 Twine(opts::OutputFilename).concat(".dwp").toStringRef(OutputNameStr);
1664 } else {
1665 StringRef ExeFileName = llvm::sys::path::filename(opts::OutputFilename);
1666 OutputName = Twine(opts::DwarfOutputPath)
1667 .concat("/")
1668 .concat(ExeFileName)
1669 .concat(".dwp")
1670 .toStringRef(OutputNameStr);
1671 errs() << "BOLT-WARNING: dwarf-output-path is in effect and .dwp file will "
1672 "possibly be written to another location that is not the same as "
1673 "the executable\n";
1675 std::error_code EC;
1676 State.Out =
1677 std::make_unique<ToolOutputFile>(OutputName, EC, sys::fs::OF_None);
1678 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1679 State.TmpBC = createDwarfOnlyBC(*File);
1680 State.Streamer = State.TmpBC->createStreamer(State.Out->os());
1681 State.MCOFI = State.Streamer->getContext().getObjectFileInfo();
1682 State.KnownSections = createKnownSectionsMap(*State.MCOFI);
1683 MCSection *const StrSection = State.MCOFI->getDwarfStrDWOSection();
1685 // Data Structures for DWP book keeping
1686 // Size of array corresponds to the number of sections supported by DWO format
1687 // in DWARF4/5.
1689 State.Strings = std::make_unique<DWPStringPool>(*State.Streamer, StrSection);
1691 // Setup DWP code once.
1692 DWARFContext *DWOCtx = BC.getDWOContext();
1694 if (DWOCtx) {
1695 State.CUIndex = &DWOCtx->getCUIndex();
1696 State.IsDWP = !State.CUIndex->getRows().empty();
1700 void DWARFRewriter::finalizeDWP(DWPState &State) {
1701 if (State.Version < 5) {
1702 // Lie about there being no info contributions so the TU index only includes
1703 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
1704 // contribution to the info section, so we do not want to lie about it.
1705 State.ContributionOffsets[0] = 0;
1707 writeIndex(*State.Streamer.get(), State.MCOFI->getDwarfTUIndexSection(),
1708 State.ContributionOffsets, State.TypeIndexEntries,
1709 State.IndexVersion);
1711 if (State.Version < 5) {
1712 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
1713 // section does not exist, so no need to do anything about this.
1714 State.ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
1715 // Unlie about the info contribution
1716 State.ContributionOffsets[0] = 1;
1718 writeIndex(*State.Streamer.get(), State.MCOFI->getDwarfCUIndexSection(),
1719 State.ContributionOffsets, State.IndexEntries, State.IndexVersion);
1721 State.Streamer->finish();
1722 State.Out->keep();
1725 void DWARFRewriter::updateDWP(DWARFUnit &CU,
1726 const OverriddenSectionsMap &OverridenSections,
1727 const DWARFRewriter::UnitMeta &CUMI,
1728 DWARFRewriter::UnitMetaVectorType &TUMetaVector,
1729 DWPState &State, DebugLocWriter &LocWriter) {
1730 const uint64_t DWOId = *CU.getDWOId();
1731 MCSection *const StrOffsetSection = State.MCOFI->getDwarfStrOffDWOSection();
1732 assert(StrOffsetSection && "StrOffsetSection does not exist.");
1733 // Skipping CUs that we failed to load.
1734 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
1735 if (!DWOCU)
1736 return;
1738 if (State.Version == 0) {
1739 State.Version = CU.getVersion();
1740 State.IndexVersion = State.Version < 5 ? 2 : 5;
1741 } else if (State.Version != CU.getVersion()) {
1742 errs() << "BOLT-ERROR: incompatible DWARF compile unit versions\n";
1743 exit(1);
1746 UnitIndexEntry CurEntry = {};
1747 CurEntry.DWOName = dwarf::toString(
1748 CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
1749 "");
1750 const char *Name = CU.getUnitDIE().getShortName();
1751 if (Name)
1752 CurEntry.Name = Name;
1753 StringRef CurStrSection;
1754 StringRef CurStrOffsetSection;
1756 // This maps each section contained in this file to its length.
1757 // This information is later on used to calculate the contributions,
1758 // i.e. offset and length, of each compile/type unit to a section.
1759 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
1761 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
1762 if (State.IsDWP)
1763 CUDWOEntry = State.CUIndex->getFromHash(DWOId);
1765 bool StrSectionWrittenOut = false;
1766 const object::ObjectFile *DWOFile =
1767 (*DWOCU)->getContext().getDWARFObj().getFile();
1769 DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
1770 if (CU.getVersion() == 5) {
1771 assert(RangeListsWritersByCU.count(DWOId) != 0 &&
1772 "No RangeListsWriter for DWO ID.");
1773 RangeListssWriter = RangeListsWritersByCU[DWOId].get();
1775 auto AddType = [&](unsigned int Index, uint32_t IndexVersion, uint64_t Offset,
1776 uint64_t Length, uint64_t Hash) -> void {
1777 UnitIndexEntry TUEntry = CurEntry;
1778 if (IndexVersion < 5)
1779 TUEntry.Contributions[0] = {};
1780 TUEntry.Contributions[Index].setOffset(Offset);
1781 TUEntry.Contributions[Index].setLength(Length);
1782 State.ContributionOffsets[Index] +=
1783 TUEntry.Contributions[Index].getLength32();
1784 State.TypeIndexEntries.insert(std::make_pair(Hash, TUEntry));
1786 for (const SectionRef &Section : DWOFile->sections()) {
1787 std::unique_ptr<DebugBufferVector> OutputData;
1788 StringRef SectionName = getSectionName(Section);
1789 Expected<StringRef> ContentsExp = Section.getContents();
1790 assert(ContentsExp && "Invalid contents.");
1791 std::optional<StringRef> TOutData = updateDebugData(
1792 (*DWOCU)->getContext(), SectionName, *ContentsExp, State.KnownSections,
1793 *State.Streamer, *this, CUDWOEntry, DWOId, OutputData,
1794 RangeListssWriter, LocWriter, OverridenSections);
1795 if (!TOutData)
1796 continue;
1798 StringRef OutData = *TOutData;
1799 if (SectionName == "debug_types.dwo") {
1800 State.Streamer->emitBytes(OutData);
1801 continue;
1804 if (SectionName.equals("debug_str.dwo")) {
1805 CurStrSection = OutData;
1806 } else {
1807 // Since handleDebugDataPatching returned true, we already know this is
1808 // a known section.
1809 auto SectionIter = State.KnownSections.find(SectionName);
1810 if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
1811 CurStrOffsetSection = OutData;
1812 else
1813 State.Streamer->emitBytes(OutData);
1814 unsigned int Index =
1815 getContributionIndex(SectionIter->second.second, State.IndexVersion);
1816 uint64_t Offset = State.ContributionOffsets[Index];
1817 uint64_t Length = OutData.size();
1818 if (CU.getVersion() >= 5 &&
1819 SectionIter->second.second == DWARFSectionKind::DW_SECT_INFO) {
1820 for (UnitMeta &MI : TUMetaVector)
1821 MI.Offset += State.DebugInfoSize;
1823 Offset = State.DebugInfoSize + CUMI.Offset;
1824 Length = CUMI.Length;
1825 State.DebugInfoSize += OutData.size();
1827 CurEntry.Contributions[Index].setOffset(Offset);
1828 CurEntry.Contributions[Index].setLength(Length);
1829 State.ContributionOffsets[Index] +=
1830 CurEntry.Contributions[Index].getLength32();
1833 // Strings are combined in to a new string section, and de-duplicated
1834 // based on hash.
1835 if (!StrSectionWrittenOut && !CurStrOffsetSection.empty() &&
1836 !CurStrSection.empty()) {
1837 writeStringsAndOffsets(*State.Streamer.get(), *State.Strings.get(),
1838 StrOffsetSection, CurStrSection,
1839 CurStrOffsetSection, CU.getVersion());
1840 StrSectionWrittenOut = true;
1843 CompileUnitIdentifiers CUI{DWOId, CurEntry.Name.c_str(),
1844 CurEntry.DWOName.c_str()};
1845 auto P = State.IndexEntries.insert(std::make_pair(CUI.Signature, CurEntry));
1846 if (!P.second) {
1847 Error Err = buildDuplicateError(*P.first, CUI, "");
1848 errs() << "BOLT-ERROR: " << toString(std::move(Err)) << "\n";
1849 return;
1852 // Handling TU
1853 const unsigned Index = getContributionIndex(
1854 State.IndexVersion < 5 ? DW_SECT_EXT_TYPES : DW_SECT_INFO,
1855 State.IndexVersion);
1856 for (UnitMeta &MI : TUMetaVector)
1857 AddType(Index, State.IndexVersion, MI.Offset, MI.Length, MI.TUHash);
1860 void DWARFRewriter::writeDWOFiles(
1861 DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
1862 const std::string &DWOName, DebugLocWriter &LocWriter) {
1863 // Setup DWP code once.
1864 DWARFContext *DWOCtx = BC.getDWOContext();
1865 const uint64_t DWOId = *CU.getDWOId();
1866 const DWARFUnitIndex *CUIndex = nullptr;
1867 bool IsDWP = false;
1868 if (DWOCtx) {
1869 CUIndex = &DWOCtx->getCUIndex();
1870 IsDWP = !CUIndex->getRows().empty();
1873 // Skipping CUs that we failed to load.
1874 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
1875 if (!DWOCU) {
1876 errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "
1877 << Twine::utohexstr(DWOId) << " is not found.\n";
1878 return;
1881 std::string CompDir = opts::DwarfOutputPath.empty()
1882 ? CU.getCompilationDir()
1883 : opts::DwarfOutputPath.c_str();
1884 auto FullPath = CompDir.append("/").append(DWOName);
1886 std::error_code EC;
1887 std::unique_ptr<ToolOutputFile> TempOut =
1888 std::make_unique<ToolOutputFile>(FullPath, EC, sys::fs::OF_None);
1890 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
1891 if (IsDWP)
1892 CUDWOEntry = CUIndex->getFromHash(DWOId);
1894 const object::ObjectFile *File =
1895 (*DWOCU)->getContext().getDWARFObj().getFile();
1896 std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
1897 std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
1898 const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
1899 StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
1901 DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
1902 if (CU.getVersion() == 5) {
1903 assert(RangeListsWritersByCU.count(DWOId) != 0 &&
1904 "No RangeListsWriter for DWO ID.");
1905 RangeListssWriter = RangeListsWritersByCU[DWOId].get();
1907 // Handling .debug_rnglists.dwo seperatly. The original .o/.dwo might not
1908 // have .debug_rnglists so won't be part of the loop below.
1909 if (!RangeListssWriter->empty()) {
1910 std::unique_ptr<DebugBufferVector> OutputData;
1911 if (std::optional<StringRef> OutData = updateDebugData(
1912 (*DWOCU)->getContext(), "debug_rnglists.dwo", "", KnownSections,
1913 *Streamer, *this, CUDWOEntry, DWOId, OutputData,
1914 RangeListssWriter, LocWriter, OverridenSections))
1915 Streamer->emitBytes(*OutData);
1919 for (const SectionRef &Section : File->sections()) {
1920 std::unique_ptr<DebugBufferVector> OutputData;
1921 StringRef SectionName = getSectionName(Section);
1922 if (SectionName == "debug_rnglists.dwo")
1923 continue;
1924 Expected<StringRef> ContentsExp = Section.getContents();
1925 assert(ContentsExp && "Invalid contents.");
1926 if (std::optional<StringRef> OutData = updateDebugData(
1927 (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
1928 *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
1929 LocWriter, OverridenSections))
1930 Streamer->emitBytes(*OutData);
1932 Streamer->finish();
1933 TempOut->keep();
1936 void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
1937 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
1938 if (!BC.getGdbIndexSection())
1939 return;
1940 GDBIndexTUEntryVector.emplace_back(Entry);
1943 void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) {
1944 if (!BC.getGdbIndexSection())
1945 return;
1947 // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
1948 // for .gdb_index section format.
1950 StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
1952 const char *Data = GdbIndexContents.data();
1954 // Parse the header.
1955 const uint32_t Version = read32le(Data);
1956 if (Version != 7 && Version != 8) {
1957 errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
1958 exit(1);
1961 // Some .gdb_index generators use file offsets while others use section
1962 // offsets. Hence we can only rely on offsets relative to each other,
1963 // and ignore their absolute values.
1964 const uint32_t CUListOffset = read32le(Data + 4);
1965 const uint32_t CUTypesOffset = read32le(Data + 8);
1966 const uint32_t AddressTableOffset = read32le(Data + 12);
1967 const uint32_t SymbolTableOffset = read32le(Data + 16);
1968 const uint32_t ConstantPoolOffset = read32le(Data + 20);
1969 Data += 24;
1971 // Map CUs offsets to indices and verify existing index table.
1972 std::map<uint32_t, uint32_t> OffsetToIndexMap;
1973 const uint32_t CUListSize = CUTypesOffset - CUListOffset;
1974 const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
1975 const unsigned NUmCUsEncoded = CUListSize / 16;
1976 unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
1977 unsigned NumDWARF5TUs =
1978 getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
1979 bool SkipTypeUnits = false;
1980 // For DWARF5 Types are in .debug_info.
1981 // LLD doesn't generate Types CU List, and in CU list offset
1982 // only includes CUs.
1983 // GDB 11+ includes only CUs in CU list and generates Types
1984 // list.
1985 // GDB 9 includes CUs and TUs in CU list and generates TYpes
1986 // list. The NumCUs is CUs + TUs, so need to modify the check.
1987 // For split-dwarf
1988 // GDB-11, DWARF5: TU units from dwo are not included.
1989 // GDB-11, DWARF4: TU units from dwo are included.
1990 if (MaxDWARFVersion >= 5)
1991 SkipTypeUnits = !TUListSize ? true
1992 : ((NUmCUsEncoded + NumDWARF5TUs) ==
1993 BC.DwCtx->getNumCompileUnits());
1995 if (!((CUListSize == NumCUs * 16) ||
1996 (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
1997 errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
1998 exit(1);
2000 DenseSet<uint64_t> OriginalOffsets;
2001 for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
2002 Index < Units; ++Index) {
2003 const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
2004 if (SkipTypeUnits && CU->isTypeUnit())
2005 continue;
2006 const uint64_t Offset = read64le(Data);
2007 Data += 16;
2008 if (CU->getOffset() != Offset) {
2009 errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
2010 exit(1);
2013 OriginalOffsets.insert(Offset);
2014 OffsetToIndexMap[Offset] = Index;
2017 // Ignore old address table.
2018 const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
2019 // Move Data to the beginning of symbol table.
2020 Data += SymbolTableOffset - CUTypesOffset;
2022 // Calculate the size of the new address table.
2023 uint32_t NewAddressTableSize = 0;
2024 for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
2025 const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
2026 NewAddressTableSize += Ranges.size() * 20;
2029 // Difference between old and new table (and section) sizes.
2030 // Could be negative.
2031 int32_t Delta = NewAddressTableSize - OldAddressTableSize;
2033 size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
2035 // Free'd by ExecutableFileMemoryManager.
2036 auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
2037 uint8_t *Buffer = NewGdbIndexContents;
2039 write32le(Buffer, Version);
2040 write32le(Buffer + 4, CUListOffset);
2041 write32le(Buffer + 8, CUTypesOffset);
2042 write32le(Buffer + 12, AddressTableOffset);
2043 write32le(Buffer + 16, SymbolTableOffset + Delta);
2044 write32le(Buffer + 20, ConstantPoolOffset + Delta);
2045 Buffer += 24;
2047 using MapEntry = std::pair<uint32_t, CUInfo>;
2048 std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
2049 // Need to sort since we write out all of TUs in .debug_info before CUs.
2050 std::sort(CUVector.begin(), CUVector.end(),
2051 [](const MapEntry &E1, const MapEntry &E2) -> bool {
2052 return E1.second.Offset < E2.second.Offset;
2054 // Writing out CU List <Offset, Size>
2055 for (auto &CUInfo : CUVector) {
2056 // Skipping TU for DWARF5 when they are not included in CU list.
2057 if (!OriginalOffsets.count(CUInfo.first))
2058 continue;
2059 write64le(Buffer, CUInfo.second.Offset);
2060 // Length encoded in CU doesn't contain first 4 bytes that encode length.
2061 write64le(Buffer + 8, CUInfo.second.Length + 4);
2062 Buffer += 16;
2065 // Rewrite TU CU List, since abbrevs can be different.
2066 // Entry example:
2067 // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
2068 // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
2069 // the second value is the type offset in the CU, and the third value is the
2070 // type signature" Looking at what is being generated by gdb-add-index. The
2071 // first entry is TU offset, second entry is offset from it, and third entry
2072 // is the type signature.
2073 if (TUListSize)
2074 for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
2075 write64le(Buffer, Entry.UnitOffset);
2076 write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
2077 write64le(Buffer + 16, Entry.TypeHash);
2078 Buffer += sizeof(GDBIndexTUEntry);
2081 // Generate new address table.
2082 for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
2083 ARangesSectionWriter->getCUAddressRanges()) {
2084 const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
2085 const DebugAddressRangesVector &Ranges = CURangesPair.second;
2086 for (const DebugAddressRange &Range : Ranges) {
2087 write64le(Buffer, Range.LowPC);
2088 write64le(Buffer + 8, Range.HighPC);
2089 write32le(Buffer + 16, CUIndex);
2090 Buffer += 20;
2094 const size_t TrailingSize =
2095 GdbIndexContents.data() + GdbIndexContents.size() - Data;
2096 assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
2097 "size calculation error");
2099 // Copy over the rest of the original data.
2100 memcpy(Buffer, Data, TrailingSize);
2102 // Register the new section.
2103 BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
2104 NewGdbIndexSize);
2107 std::unique_ptr<DebugBufferVector>
2108 DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
2109 auto LocBuffer = std::make_unique<DebugBufferVector>();
2110 auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
2111 auto Writer =
2112 std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));
2114 for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :
2115 LocListWritersByCU) {
2116 DebugLocWriter *LocWriter = Loc.second.get();
2117 auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter);
2119 // Filter out DWARF4, writing out DWARF5
2120 if (Version == DWARFVersion::DWARF5 &&
2121 (!LocListWriter || LocListWriter->getDwarfVersion() <= 4))
2122 continue;
2124 // Filter out DWARF5, writing out DWARF4
2125 if (Version == DWARFVersion::DWARFLegacy &&
2126 (LocListWriter && LocListWriter->getDwarfVersion() >= 5))
2127 continue;
2129 // Skipping DWARF4/5 split dwarf.
2130 if (LocListWriter && LocListWriter->getDwarfVersion() <= 4)
2131 continue;
2132 std::unique_ptr<DebugBufferVector> CurrCULocationLists =
2133 LocWriter->getBuffer();
2134 *LocStream << *CurrCULocationLists;
2137 return LocBuffer;
2140 void DWARFRewriter::convertToRangesPatchDebugInfo(
2141 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
2142 uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
2143 DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {
2144 uint32_t BaseOffset = 0;
2145 dwarf::Form LowForm = LowPCAttrInfo.getForm();
2146 dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
2147 dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;
2149 if (Unit.getVersion() >= 5) {
2150 RangeBaseAttribute = dwarf::DW_AT_rnglists_base;
2151 RangesForm = dwarf::DW_FORM_rnglistx;
2152 } else if (Unit.getVersion() < 4) {
2153 RangesForm = dwarf::DW_FORM_data4;
2155 bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit ||
2156 Die.getTag() == dwarf::DW_TAG_skeleton_unit;
2157 if (!IsUnitDie)
2158 DIEBldr.deleteValue(&Die, LowPCAttrInfo.getAttribute());
2159 // In DWARF4 for DW_AT_low_pc in binary DW_FORM_addr is used. In the DWO
2160 // section DW_FORM_GNU_addr_index is used. So for if we are converting
2161 // DW_AT_low_pc/DW_AT_high_pc and see DW_FORM_GNU_addr_index. We are
2162 // converting in DWO section, and DW_AT_ranges [DW_FORM_sec_offset] is
2163 // relative to DW_AT_GNU_ranges_base.
2164 if (LowForm == dwarf::DW_FORM_GNU_addr_index) {
2165 // Ranges are relative to DW_AT_GNU_ranges_base.
2166 uint64_t CurRangeBase = 0;
2167 if (std::optional<uint64_t> DWOId = Unit.getDWOId()) {
2168 CurRangeBase = getDwoRangesBase(*DWOId);
2170 BaseOffset = CurRangeBase;
2171 } else {
2172 // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
2173 // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
2174 // when it's absent.
2175 if (IsUnitDie) {
2176 if (LowForm == dwarf::DW_FORM_addrx) {
2177 const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit);
2178 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
2179 LowPCAttrInfo.getForm(), DIEInteger(Index));
2180 } else {
2181 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
2182 LowPCAttrInfo.getForm(), DIEInteger(0));
2185 // Original CU didn't have DW_AT_*_base. We converted it's children (or
2186 // dwo), so need to insert it into CU.
2187 if (RangesBase)
2188 DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
2189 DIEInteger(*RangesBase));
2192 uint64_t RangeAttrVal = RangesSectionOffset - BaseOffset;
2193 if (Unit.getVersion() >= 5)
2194 RangeAttrVal = RangesSectionOffset;
2195 // HighPC was conveted into DW_AT_ranges.
2196 // For DWARF5 we only access ranges through index.
2198 DIEBldr.replaceValue(&Die, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges,
2199 RangesForm, DIEInteger(RangeAttrVal));