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//===----------------------------------------------------------------------===//
8
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/MCAsmLayout.h"
33#include "llvm/MC/MCObjectWriter.h"
34#include "llvm/MC/MCStreamer.h"
35#include "llvm/Object/ObjectFile.h"
36#include "llvm/Support/Casting.h"
37#include "llvm/Support/CommandLine.h"
38#include "llvm/Support/Debug.h"
39#include "llvm/Support/Endian.h"
40#include "llvm/Support/Error.h"
41#include "llvm/Support/FileSystem.h"
42#include "llvm/Support/LEB128.h"
43#include "llvm/Support/ThreadPool.h"
44#include "llvm/Support/raw_ostream.h"
45#include <algorithm>
46#include <cstdint>
47#include <functional>
48#include <iterator>
49#include <memory>
50#include <optional>
51#include <string>
52#include <unordered_map>
53#include <utility>
54#include <vector>
55
56#undef DEBUG_TYPE
57#define DEBUG_TYPE "bolt"
58
59static void printDie(const DWARFDie &DIE) {
60 DIDumpOptions DumpOpts;
61 DumpOpts.ShowForm = true;
62 DumpOpts.Verbose = true;
63 DumpOpts.ChildRecurseDepth = 0;
64 DumpOpts.ShowChildren = false;
65 DIE.dump(OS&: dbgs(), indent: 0, DumpOpts);
66}
67
68/// Lazily parse DWARF DIE and print it out.
69LLVM_ATTRIBUTE_UNUSED
70static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {
71 uint64_t OriginalOffsets = DIEOffset;
72 uint64_t NextCUOffset = DU.getNextUnitOffset();
73 DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
74 DWARFDebugInfoEntry DIEEntry;
75 if (DIEEntry.extractFast(U: DU, OffsetPtr: &DIEOffset, DebugInfoData, UEndOffset: NextCUOffset, ParentIdx: 0)) {
76 if (const DWARFAbbreviationDeclaration *AbbrDecl =
77 DIEEntry.getAbbreviationDeclarationPtr()) {
78 DWARFDie DDie(&DU, &DIEEntry);
79 printDie(DIE: DDie);
80 } else {
81 dbgs() << "Failed to extract abbreviation for"
82 << Twine::utohexstr(Val: OriginalOffsets) << "\n";
83 }
84 } else {
85 dbgs() << "Failed to extract DIE for " << Twine::utohexstr(Val: OriginalOffsets)
86 << " \n";
87 }
88}
89
90using namespace bolt;
91
92/// Take a set of DWARF address ranges corresponding to the input binary and
93/// translate them to a set of address ranges in the output binary.
94static DebugAddressRangesVector
95translateInputToOutputRanges(const BinaryFunction &BF,
96 const DWARFAddressRangesVector &InputRanges) {
97 DebugAddressRangesVector OutputRanges;
98
99 // If the function hasn't changed return the same ranges.
100 if (!BF.isEmitted()) {
101 OutputRanges.resize(N: InputRanges.size());
102 llvm::transform(Range: InputRanges, d_first: OutputRanges.begin(),
103 F: [](const DWARFAddressRange &Range) {
104 return DebugAddressRange(Range.LowPC, Range.HighPC);
105 });
106 return OutputRanges;
107 }
108
109 for (const DWARFAddressRange &Range : InputRanges)
110 llvm::append_range(C&: OutputRanges, R: BF.translateInputToOutputRange(
111 InRange: {Range.LowPC, Range.HighPC}));
112
113 // Post-processing pass to sort and merge ranges.
114 llvm::sort(C&: OutputRanges);
115 DebugAddressRangesVector MergedRanges;
116 uint64_t PrevHighPC = 0;
117 for (const DebugAddressRange &Range : OutputRanges) {
118 if (Range.LowPC <= PrevHighPC) {
119 MergedRanges.back().HighPC =
120 std::max(a: MergedRanges.back().HighPC, b: Range.HighPC);
121 } else {
122 MergedRanges.emplace_back(Args: Range.LowPC, Args: Range.HighPC);
123 }
124 PrevHighPC = MergedRanges.back().HighPC;
125 }
126
127 return MergedRanges;
128}
129
130/// Similar to translateInputToOutputRanges() but operates on location lists.
131static DebugLocationsVector
132translateInputToOutputLocationList(const BinaryFunction &BF,
133 const DebugLocationsVector &InputLL) {
134 DebugLocationsVector OutputLL;
135
136 // If the function hasn't changed - there's nothing to update.
137 if (!BF.isEmitted())
138 return InputLL;
139
140 for (const DebugLocationEntry &Entry : InputLL) {
141 DebugAddressRangesVector OutRanges =
142 BF.translateInputToOutputRange(InRange: {Entry.LowPC, Entry.HighPC});
143 if (!OutRanges.empty() && !OutputLL.empty()) {
144 if (OutRanges.front().LowPC == OutputLL.back().HighPC &&
145 Entry.Expr == OutputLL.back().Expr) {
146 OutputLL.back().HighPC =
147 std::max(a: OutputLL.back().HighPC, b: OutRanges.front().HighPC);
148 OutRanges.erase(CI: OutRanges.begin());
149 }
150 }
151 llvm::transform(Range&: OutRanges, d_first: std::back_inserter(x&: OutputLL),
152 F: [&Entry](const DebugAddressRange &R) {
153 return DebugLocationEntry{.LowPC: R.LowPC, .HighPC: R.HighPC, .Expr: Entry.Expr};
154 });
155 }
156
157 // Sort and merge adjacent entries with identical locations.
158 llvm::stable_sort(
159 Range&: OutputLL, C: [](const DebugLocationEntry &A, const DebugLocationEntry &B) {
160 return A.LowPC < B.LowPC;
161 });
162 DebugLocationsVector MergedLL;
163 uint64_t PrevHighPC = 0;
164 const SmallVectorImpl<uint8_t> *PrevExpr = nullptr;
165 for (const DebugLocationEntry &Entry : OutputLL) {
166 if (Entry.LowPC <= PrevHighPC && *PrevExpr == Entry.Expr) {
167 MergedLL.back().HighPC = std::max(a: Entry.HighPC, b: MergedLL.back().HighPC);
168 } else {
169 const uint64_t Begin = std::max(a: Entry.LowPC, b: PrevHighPC);
170 const uint64_t End = std::max(a: Begin, b: Entry.HighPC);
171 MergedLL.emplace_back(Args: DebugLocationEntry{.LowPC: Begin, .HighPC: End, .Expr: Entry.Expr});
172 }
173 PrevHighPC = MergedLL.back().HighPC;
174 PrevExpr = &MergedLL.back().Expr;
175 }
176
177 return MergedLL;
178}
179
180using namespace dwarf_linker;
181using namespace dwarf_linker::classic;
182
183namespace llvm {
184namespace bolt {
185/// Emits debug information into .debug_info or .debug_types section.
186class DIEStreamer : public DwarfStreamer {
187 DIEBuilder *DIEBldr;
188 DWARFRewriter &Rewriter;
189
190private:
191 /// Emit the compilation unit header for \p Unit in the debug_info
192 /// section.
193 ///
194 /// A Dwarf 4 section header is encoded as:
195 /// uint32_t Unit length (omitting this field)
196 /// uint16_t Version
197 /// uint32_t Abbreviation table offset
198 /// uint8_t Address size
199 /// Leading to a total of 11 bytes.
200 ///
201 /// A Dwarf 5 section header is encoded as:
202 /// uint32_t Unit length (omitting this field)
203 /// uint16_t Version
204 /// uint8_t Unit type
205 /// uint8_t Address size
206 /// uint32_t Abbreviation table offset
207 /// Leading to a total of 12 bytes.
208 void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
209 unsigned DwarfVersion) {
210
211 AsmPrinter &Asm = getAsmPrinter();
212 switchToDebugInfoSection(DwarfVersion);
213
214 emitCommonHeader(Unit, UnitDIE, Version: DwarfVersion);
215
216 if (DwarfVersion >= 5 &&
217 Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) {
218 std::optional<uint64_t> DWOId = Unit.getDWOId();
219 assert(DWOId &&
220 "DWOId does not exist and this is not a DW_UT_compile Unit");
221 Asm.emitInt64(Value: *DWOId);
222 }
223 }
224
225 void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) {
226 dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType());
227 llvm::AsmPrinter &Asm = getAsmPrinter();
228
229 // Emit size of content not including length itself
230 Asm.emitInt32(Value: Unit.getHeaderSize() + UnitDIE.getSize() - 4);
231 Asm.emitInt16(Value: Version);
232
233 // DWARF v5 reorders the address size and adds a unit type.
234 if (Version >= 5) {
235 Asm.emitInt8(Value: UT);
236 Asm.emitInt8(Value: Asm.MAI->getCodePointerSize());
237 }
238
239 Asm.emitInt32(Value: 0);
240 if (Version <= 4) {
241 Asm.emitInt8(Value: Asm.MAI->getCodePointerSize());
242 }
243 }
244
245 void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
246 unsigned DwarfVersion) {
247 AsmPrinter &Asm = getAsmPrinter();
248 const uint64_t TypeSignature = cast<DWARFTypeUnit>(Val&: Unit).getTypeHash();
249 DIE *TypeDIE = DIEBldr->getTypeDIE(DU&: Unit);
250 const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(DwarfUnit: Unit);
251 Rewriter.addGDBTypeUnitEntry(
252 Entry: {.UnitOffset: UI.UnitOffset, .TypeHash: TypeSignature, .TypeDIERelativeOffset: TypeDIE->getOffset()});
253 if (Unit.getVersion() < 5) {
254 // Switch the section to .debug_types section.
255 std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;
256 llvm::MCContext &MC = Asm.OutContext;
257 const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();
258
259 MS->switchSection(Section: MOFI->getDwarfTypesSection(Hash: 0));
260 MC.setDwarfVersion(DwarfVersion);
261 } else
262 switchToDebugInfoSection(DwarfVersion);
263
264 emitCommonHeader(Unit, UnitDIE, Version: DwarfVersion);
265 Asm.OutStreamer->emitIntValue(Value: TypeSignature, Size: sizeof(TypeSignature));
266 Asm.emitDwarfLengthOrOffset(Value: TypeDIE ? TypeDIE->getOffset() : 0);
267 }
268
269 void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {
270 if (Unit.isTypeUnit())
271 emitTypeUnitHeader(Unit, UnitDIE, DwarfVersion: Unit.getVersion());
272 else
273 emitCompileUnitHeader(Unit, UnitDIE, DwarfVersion: Unit.getVersion());
274 }
275
276 void emitDIE(DIE &Die) override {
277 AsmPrinter &Asm = getAsmPrinter();
278 Asm.emitDwarfDIE(Die);
279 }
280
281public:
282 DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter,
283 DWARFLinkerBase::OutputFileType OutFileType,
284 raw_pwrite_stream &OutFile,
285 DWARFLinkerBase::MessageHandlerTy Warning)
286 : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr),
287 Rewriter(Rewriter){};
288
289 using DwarfStreamer::emitCompileUnitHeader;
290
291 void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
292 emitUnitHeader(Unit, UnitDIE);
293 emitDIE(Die&: UnitDIE);
294 }
295};
296
297/// Finds attributes FormValue and Offset.
298///
299/// \param DIE die to look up in.
300/// \param Attrs finds the first attribute that matches and extracts it.
301/// \return an optional AttrInfo with DWARFFormValue and Offset.
302std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
303 std::vector<dwarf::Attribute> Attrs) {
304 for (dwarf::Attribute &Attr : Attrs)
305 if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))
306 return Info;
307 return std::nullopt;
308}
309
310} // namespace bolt
311} // namespace llvm
312
313using namespace llvm;
314using namespace llvm::support::endian;
315using namespace object;
316using namespace bolt;
317
318namespace opts {
319
320extern cl::OptionCategory BoltCategory;
321extern cl::opt<unsigned> Verbosity;
322extern cl::opt<std::string> OutputFilename;
323
324static cl::opt<bool> KeepARanges(
325 "keep-aranges",
326 cl::desc(
327 "keep or generate .debug_aranges section if .gdb_index is written"),
328 cl::Hidden, cl::cat(BoltCategory));
329
330static cl::opt<bool>
331DeterministicDebugInfo("deterministic-debuginfo",
332 cl::desc("disables parallel execution of tasks that may produce "
333 "nondeterministic debug info"),
334 cl::init(Val: true),
335 cl::cat(BoltCategory));
336
337static cl::opt<std::string> DwarfOutputPath(
338 "dwarf-output-path",
339 cl::desc("Path to where .dwo files or dwp file will be written out to."),
340 cl::init(Val: ""), cl::cat(BoltCategory));
341
342static cl::opt<bool>
343 WriteDWP("write-dwp",
344 cl::desc("output a single dwarf package file (dwp) instead of "
345 "multiple non-relocatable dwarf object files (dwo)."),
346 cl::init(Val: false), cl::cat(BoltCategory));
347
348static cl::opt<bool> CreateDebugNames(
349 "create-debug-names-section",
350 cl::desc("Creates .debug_names section, if the input binary doesn't have "
351 "it already, for DWARF5 CU/TUs."),
352 cl::init(Val: false), cl::cat(BoltCategory));
353
354static cl::opt<bool>
355 DebugSkeletonCu("debug-skeleton-cu",
356 cl::desc("prints out offsetrs for abbrev and debu_info of "
357 "Skeleton CUs that get patched."),
358 cl::ZeroOrMore, cl::Hidden, cl::init(Val: false),
359 cl::cat(BoltCategory));
360
361static cl::opt<unsigned> BatchSize(
362 "cu-processing-batch-size",
363 cl::desc(
364 "Specifies the size of batches for processing CUs. Higher number has "
365 "better performance, but more memory usage. Default value is 1."),
366 cl::Hidden, cl::init(Val: 1), cl::cat(BoltCategory));
367
368static cl::opt<bool> AlwaysConvertToRanges(
369 "always-convert-to-ranges",
370 cl::desc("This option is for testing purposes only. It forces BOLT to "
371 "convert low_pc/high_pc to ranges always."),
372 cl::ReallyHidden, cl::init(Val: false), cl::cat(BoltCategory));
373
374extern cl::opt<std::string> CompDirOverride;
375} // namespace opts
376
377/// If DW_AT_low_pc exists sets LowPC and returns true.
378static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
379 uint64_t &SectionIndex) {
380 DIEValue DvalLowPc = Die.findAttribute(Attribute: dwarf::DW_AT_low_pc);
381 if (!DvalLowPc)
382 return false;
383
384 dwarf::Form Form = DvalLowPc.getForm();
385 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
386 uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue();
387 if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx ||
388 AddrOffset) {
389
390 uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue;
391 std::optional<object::SectionedAddress> SA =
392 DU.getAddrOffsetSectionItem(Index);
393 if (!SA)
394 return false;
395 if (AddrOffset)
396 SA->Address += (LowPcValue & 0xffffffff);
397
398 LowPC = SA->Address;
399 SectionIndex = SA->SectionIndex;
400 } else {
401 LowPC = LowPcValue;
402 SectionIndex = 0;
403 }
404 return true;
405}
406
407/// If DW_AT_high_pc exists sets HighPC and returns true.
408static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {
409 DIEValue DvalHighPc = Die.findAttribute(Attribute: dwarf::DW_AT_high_pc);
410 if (!DvalHighPc)
411 return false;
412 if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
413 HighPC = DvalHighPc.getDIEInteger().getValue();
414 else
415 HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
416 return true;
417}
418
419/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
420/// true.
421static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
422 uint64_t &LowPC, uint64_t &HighPC,
423 uint64_t &SectionIndex) {
424 uint64_t TempLowPC = LowPC;
425 uint64_t TempHighPC = HighPC;
426 uint64_t TempSectionIndex = SectionIndex;
427 if (getLowPC(Die, DU, LowPC&: TempLowPC, SectionIndex&: TempSectionIndex) &&
428 getHighPC(Die, LowPC: TempLowPC, HighPC&: TempHighPC)) {
429 LowPC = TempLowPC;
430 HighPC = TempHighPC;
431 SectionIndex = TempSectionIndex;
432 return true;
433 }
434 return false;
435}
436
437static Expected<llvm::DWARFAddressRangesVector>
438getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
439 uint64_t LowPC, HighPC, Index;
440 if (getLowAndHighPC(Die, DU, LowPC, HighPC, SectionIndex&: Index))
441 return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
442 if (DIEValue Dval = Die.findAttribute(Attribute: dwarf::DW_AT_ranges)) {
443 if (Dval.getForm() == dwarf::DW_FORM_rnglistx)
444 return DU.findRnglistFromIndex(Index: Dval.getDIEInteger().getValue());
445
446 return DU.findRnglistFromOffset(Offset: Dval.getDIEInteger().getValue());
447 }
448
449 return DWARFAddressRangesVector();
450}
451
452static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
453 const DIEValue &AttrVal) {
454 DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());
455 if (std::optional<object::SectionedAddress> SA =
456 DWARFFormValue::getAsSectionedAddress(Val: Value, Form: AttrVal.getForm(), U: &DU))
457 return SA->Address;
458 return std::nullopt;
459}
460
461/// Returns DWO Name to be used. Handles case where user specifies output DWO
462/// directory, and there are duplicate names. Assumes DWO ID is unique.
463static std::string
464getDWOName(llvm::DWARFUnit &CU,
465 std::unordered_map<std::string, uint32_t> &NameToIndexMap) {
466 std::optional<uint64_t> DWOId = CU.getDWOId();
467 assert(DWOId && "DWO ID not found.");
468 (void)DWOId;
469
470 std::string DWOName = dwarf::toString(
471 V: CU.getUnitDIE().find(Attrs: {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
472 Default: "");
473 assert(!DWOName.empty() &&
474 "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exists.");
475 if (!opts::DwarfOutputPath.empty()) {
476 DWOName = std::string(sys::path::filename(path: DWOName));
477 auto Iter = NameToIndexMap.find(x: DWOName);
478 if (Iter == NameToIndexMap.end())
479 Iter = NameToIndexMap.insert(x: {DWOName, 0}).first;
480 DWOName.append(str: std::to_string(val: Iter->second));
481 ++Iter->second;
482 }
483 DWOName.append(s: ".dwo");
484 return DWOName;
485}
486
487static std::unique_ptr<DIEStreamer>
488createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
489 StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
490 DWARFRewriter &Rewriter) {
491
492 std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
493 args: &DIEBldr, args&: Rewriter, args: DWARFLinkerBase::OutputFileType::Object, args&: OutFile,
494 args: [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
495 Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
496 if (Err)
497 errs()
498 << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
499 << toString(E: std::move(Err)) << "\n";
500 return Streamer;
501}
502
503static DWARFRewriter::UnitMeta
504emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer, DWARFUnit &Unit) {
505 DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(DU: Unit);
506 const DIEBuilder::DWARFUnitInfo &U = DIEBldr.getUnitInfoByDwarfUnit(DwarfUnit: Unit);
507 Streamer.emitUnit(Unit, UnitDIE&: *UnitDIE);
508 uint64_t TypeHash = 0;
509 if (DWARFTypeUnit *DTU = dyn_cast_or_null<DWARFTypeUnit>(Val: &Unit))
510 TypeHash = DTU->getTypeHash();
511 return {.Offset: U.UnitOffset, .Length: U.UnitLength, .TUHash: TypeHash};
512}
513
514static void emitDWOBuilder(const std::string &DWOName,
515 DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
516 DWARFUnit &SplitCU, DWARFUnit &CU,
517 DWARFRewriter::DWPState &State,
518 DebugLocWriter &LocWriter) {
519 // Populate debug_info and debug_abbrev for current dwo into StringRef.
520 DWODIEBuilder.generateAbbrevs();
521 DWODIEBuilder.finish();
522
523 SmallVector<char, 20> OutBuffer;
524 std::shared_ptr<raw_svector_ostream> ObjOS =
525 std::make_shared<raw_svector_ostream>(args&: OutBuffer);
526 const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();
527 auto TheTriple = std::make_unique<Triple>(args: File->makeTriple());
528 std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(
529 TheTriple: *TheTriple, OutFile&: *ObjOS, Swift5ReflectionSegmentName: "DwoStreamerInitAug2", DIEBldr&: DWODIEBuilder, Rewriter);
530 DWARFRewriter::UnitMetaVectorType TUMetaVector;
531 DWARFRewriter::UnitMeta CUMI = {.Offset: 0, .Length: 0, .TUHash: 0};
532 if (SplitCU.getContext().getMaxDWOVersion() >= 5) {
533 for (std::unique_ptr<llvm::DWARFUnit> &CU :
534 SplitCU.getContext().dwo_info_section_units()) {
535 if (!CU->isTypeUnit())
536 continue;
537 DWARFRewriter::UnitMeta MI =
538 emitUnit(DIEBldr&: DWODIEBuilder, Streamer&: *Streamer, Unit&: *CU.get());
539 TUMetaVector.emplace_back(args&: MI);
540 }
541 CUMI = emitUnit(DIEBldr&: DWODIEBuilder, Streamer&: *Streamer, Unit&: SplitCU);
542 } else {
543 for (std::unique_ptr<llvm::DWARFUnit> &CU :
544 SplitCU.getContext().dwo_compile_units())
545 emitUnit(DIEBldr&: DWODIEBuilder, Streamer&: *Streamer, Unit&: *CU.get());
546
547 // emit debug_types sections for dwarf4
548 for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector()) {
549 DWARFRewriter::UnitMeta MI = emitUnit(DIEBldr&: DWODIEBuilder, Streamer&: *Streamer, Unit&: *CU);
550 TUMetaVector.emplace_back(args&: MI);
551 }
552 }
553
554 Streamer->emitAbbrevs(Abbrevs: DWODIEBuilder.getAbbrevs(),
555 DwarfVersion: SplitCU.getContext().getMaxVersion());
556 Streamer->finish();
557
558 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
559 MemoryBuffer::getMemBuffer(InputData: ObjOS->str(), BufferName: "in-memory object file", RequiresNullTerminator: false);
560 std::unique_ptr<object::ObjectFile> Obj = cantFail(
561 ValOrErr: object::ObjectFile::createObjectFile(Object: ObjectMemBuffer->getMemBufferRef()),
562 Msg: "error creating in-memory object");
563
564 DWARFRewriter::OverriddenSectionsMap OverriddenSections;
565 for (const SectionRef &Secs : Obj->sections()) {
566 StringRef Contents = cantFail(ValOrErr: Secs.getContents());
567 StringRef Name = cantFail(ValOrErr: Secs.getName());
568 DWARFSectionKind Kind =
569 StringSwitch<DWARFSectionKind>(Name)
570 .Case(S: ".debug_abbrev", Value: DWARFSectionKind::DW_SECT_ABBREV)
571 .Case(S: ".debug_info", Value: DWARFSectionKind::DW_SECT_INFO)
572 .Case(S: ".debug_types", Value: DWARFSectionKind::DW_SECT_EXT_TYPES)
573 .Default(Value: DWARFSectionKind::DW_SECT_EXT_unknown);
574 if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)
575 continue;
576 OverriddenSections[Kind] = Contents;
577 }
578 if (opts::WriteDWP)
579 Rewriter.updateDWP(CU, OverriddenSections, CUMI, TUMetaVector, State,
580 LocWriter);
581 else
582 Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter);
583}
584
585void DWARFRewriter::addStringHelper(DIEBuilder &DIEBldr, DIE &Die,
586 const DWARFUnit &Unit,
587 DIEValue &DIEAttrInfo, StringRef Str) {
588 uint32_t NewOffset = StrWriter->addString(Str);
589 if (Unit.getVersion() >= 5) {
590 StrOffstsWriter->updateAddressMap(Index: DIEAttrInfo.getDIEInteger().getValue(),
591 Address: NewOffset);
592 return;
593 }
594 DIEBldr.replaceValue(Die: &Die, Attribute: DIEAttrInfo.getAttribute(), Form: DIEAttrInfo.getForm(),
595 NewValue: DIEInteger(NewOffset));
596}
597
598using DWARFUnitVec = std::vector<DWARFUnit *>;
599using CUPartitionVector = std::vector<DWARFUnitVec>;
600/// Partitions CUs in to buckets. Bucket size is controlled by
601/// cu-processing-batch-size. All the CUs that have cross CU reference reference
602/// as a source are put in to the same initial bucket.
603static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {
604 CUPartitionVector Vec(2);
605 unsigned Counter = 0;
606 const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();
607 for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {
608 Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =
609 Abbr->getAbbreviationDeclarationSet(CUAbbrOffset: CU->getAbbreviationsOffset());
610 if (!AbbrDeclSet) {
611 consumeError(Err: AbbrDeclSet.takeError());
612 return Vec;
613 }
614 bool CrossCURefFound = false;
615 for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) {
616 for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr :
617 Decl.attributes()) {
618 if (Attr.Form == dwarf::DW_FORM_ref_addr) {
619 CrossCURefFound = true;
620 break;
621 }
622 }
623 if (CrossCURefFound)
624 break;
625 }
626 if (CrossCURefFound) {
627 Vec[0].push_back(x: CU.get());
628 } else {
629 ++Counter;
630 Vec.back().push_back(x: CU.get());
631 }
632 if (Counter % opts::BatchSize == 0 && !Vec.back().empty())
633 Vec.push_back(x: {});
634 }
635 return Vec;
636}
637
638void DWARFRewriter::updateDebugInfo() {
639 ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(SectionName: ".debug_info");
640 if (!DebugInfo)
641 return;
642
643 ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
644 StrWriter = std::make_unique<DebugStrWriter>(args&: BC);
645
646 StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>();
647
648 if (!opts::DeterministicDebugInfo) {
649 opts::DeterministicDebugInfo = true;
650 errs() << "BOLT-WARNING: --deterministic-debuginfo is being deprecated\n";
651 }
652
653 if (BC.isDWARF5Used()) {
654 AddrWriter = std::make_unique<DebugAddrWriterDwarf5>(args: &BC);
655 RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();
656 DebugRangeListsSectionWriter::setAddressWriter(AddrWriter.get());
657 } else {
658 AddrWriter = std::make_unique<DebugAddrWriter>(args: &BC);
659 }
660
661 if (BC.isDWARFLegacyUsed())
662 LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
663
664 DebugLoclistWriter::setAddressWriter(AddrWriter.get());
665
666 uint32_t CUIndex = 0;
667 std::mutex AccessMutex;
668 // Needs to be invoked in the same order as CUs are processed.
669 auto createRangeLocList = [&](DWARFUnit &CU) -> DebugLocWriter * {
670 std::lock_guard<std::mutex> Lock(AccessMutex);
671 const uint16_t DwarfVersion = CU.getVersion();
672 if (DwarfVersion >= 5) {
673 LocListWritersByCU[CUIndex] =
674 std::make_unique<DebugLoclistWriter>(args&: CU, args: DwarfVersion, args: false);
675
676 if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
677 assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
678 "RangeLists writer for DWO unit already exists.");
679 auto RangeListsSectionWriter =
680 std::make_unique<DebugRangeListsSectionWriter>();
681 RangeListsSectionWriter->initSection(CU);
682 RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter);
683 }
684
685 } else {
686 LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
687 }
688 return LocListWritersByCU[CUIndex++].get();
689 };
690
691 // Unordered maps to handle name collision if output DWO directory is
692 // specified.
693 std::unordered_map<std::string, uint32_t> NameToIndexMap;
694
695 auto updateDWONameCompDir = [&](DWARFUnit &Unit, DIEBuilder &DIEBldr,
696 DIE &UnitDIE) -> std::string {
697 DIEValue DWONameAttrInfo = UnitDIE.findAttribute(Attribute: dwarf::DW_AT_dwo_name);
698 if (!DWONameAttrInfo)
699 DWONameAttrInfo = UnitDIE.findAttribute(Attribute: dwarf::DW_AT_GNU_dwo_name);
700 assert(DWONameAttrInfo && "DW_AT_dwo_name is not in Skeleton CU.");
701 std::string ObjectName;
702
703 {
704 std::lock_guard<std::mutex> Lock(AccessMutex);
705 ObjectName = getDWOName(CU&: Unit, NameToIndexMap);
706 }
707 addStringHelper(DIEBldr, Die&: UnitDIE, Unit, DIEAttrInfo&: DWONameAttrInfo,
708 Str: ObjectName.c_str());
709
710 DIEValue CompDirAttrInfo = UnitDIE.findAttribute(Attribute: dwarf::DW_AT_comp_dir);
711 assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU.");
712
713 if (!opts::DwarfOutputPath.empty()) {
714 if (!sys::fs::exists(Path: opts::DwarfOutputPath))
715 sys::fs::create_directory(path: opts::DwarfOutputPath);
716 addStringHelper(DIEBldr, Die&: UnitDIE, Unit, DIEAttrInfo&: CompDirAttrInfo,
717 Str: opts::DwarfOutputPath.c_str());
718 }
719 return ObjectName;
720 };
721
722 DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
723 *StrWriter);
724 DWPState State;
725 if (opts::WriteDWP)
726 initDWPState(State);
727 auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) {
728 // Check if the unit is a skeleton and we need special updates for it and
729 // its matching split/DWO CU.
730 std::optional<DWARFUnit *> SplitCU;
731 std::optional<uint64_t> RangesBase;
732 std::optional<uint64_t> DWOId = Unit->getDWOId();
733 if (DWOId)
734 SplitCU = BC.getDWOCU(DWOId: *DWOId);
735 DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit);
736 DebugRangesSectionWriter *RangesSectionWriter =
737 Unit->getVersion() >= 5 ? RangeListsSectionWriter.get()
738 : LegacyRangesSectionWriter.get();
739 // Skipping CUs that failed to load.
740 if (SplitCU) {
741 DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
742 Unit);
743 DWODIEBuilder.buildDWOUnit(U&: **SplitCU);
744 std::string DWOName = updateDWONameCompDir(
745 *Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(DU: *Unit));
746
747 DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true);
748 DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
749 if (Unit->getVersion() >= 5) {
750 TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
751 } else {
752 RangesBase = RangesSectionWriter->getSectionOffset();
753 setDwoRangesBase(DWOId: *DWOId, RangesBase: *RangesBase);
754 }
755
756 updateUnitDebugInfo(Unit&: *(*SplitCU), DIEBldr&: DWODIEBuilder, DebugLocWriter&: DebugLocDWoWriter,
757 RangesSectionWriter&: *TempRangesSectionWriter);
758 DebugLocDWoWriter.finalize(DIEBldr&: DWODIEBuilder,
759 Die&: *DWODIEBuilder.getUnitDIEbyUnit(DU: **SplitCU));
760 if (Unit->getVersion() >= 5)
761 TempRangesSectionWriter->finalizeSection();
762
763 emitDWOBuilder(DWOName, DWODIEBuilder, Rewriter&: *this, SplitCU&: **SplitCU, CU&: *Unit, State,
764 LocWriter&: DebugLocDWoWriter);
765 }
766
767 if (Unit->getVersion() >= 5) {
768 RangesBase = RangesSectionWriter->getSectionOffset() +
769 getDWARF5RngListLocListHeaderSize();
770 RangesSectionWriter->initSection(CU&: *Unit);
771 StrOffstsWriter->finalizeSection(Unit&: *Unit, DIEBldr&: *DIEBlder);
772 }
773
774 updateUnitDebugInfo(Unit&: *Unit, DIEBldr&: *DIEBlder, DebugLocWriter&: *DebugLocWriter, RangesSectionWriter&: *RangesSectionWriter,
775 RangesBase);
776 DebugLocWriter->finalize(DIEBldr&: *DIEBlder, Die&: *DIEBlder->getUnitDIEbyUnit(DU: *Unit));
777 if (Unit->getVersion() >= 5)
778 RangesSectionWriter->finalizeSection();
779 AddrWriter->update(DIEBlder&: *DIEBlder, CUs&: *Unit);
780 };
781
782 DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
783 DIEBlder.buildTypeUnits(StrOffsetWriter: StrOffstsWriter.get());
784 SmallVector<char, 20> OutBuffer;
785 std::unique_ptr<raw_svector_ostream> ObjOS =
786 std::make_unique<raw_svector_ostream>(args&: OutBuffer);
787 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
788 auto TheTriple = std::make_unique<Triple>(args: File->makeTriple());
789 std::unique_ptr<DIEStreamer> Streamer =
790 createDIEStreamer(TheTriple: *TheTriple, OutFile&: *ObjOS, Swift5ReflectionSegmentName: "TypeStreamer", DIEBldr&: DIEBlder, Rewriter&: *this);
791 CUOffsetMap OffsetMap = finalizeTypeSections(DIEBlder, Streamer&: *Streamer);
792
793 const bool SingleThreadedMode =
794 opts::NoThreads || opts::DeterministicDebugInfo;
795 if (!SingleThreadedMode)
796 DIEBlder.buildCompileUnits();
797 if (SingleThreadedMode) {
798 CUPartitionVector PartVec = partitionCUs(DwCtx&: *BC.DwCtx);
799 for (std::vector<DWARFUnit *> &Vec : PartVec) {
800 DIEBlder.buildCompileUnits(CUs: Vec);
801 for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
802 processUnitDIE(CU, &DIEBlder);
803 finalizeCompileUnits(DIEBlder, Streamer&: *Streamer, CUMap&: OffsetMap,
804 CUs: DIEBlder.getProcessedCUs());
805 }
806 } else {
807 // Update unit debug info in parallel
808 ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool();
809 for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
810 ThreadPool.async(F&: processUnitDIE, ArgList: CU.get(), ArgList: &DIEBlder);
811 ThreadPool.wait();
812 }
813
814 DebugNamesTable.emitAccelTable();
815
816 if (opts::WriteDWP)
817 finalizeDWP(State);
818
819 finalizeDebugSections(DIEBlder, DebugNamesTable, Streamer&: *Streamer, ObjOS&: *ObjOS,
820 CUMap&: OffsetMap);
821 updateGdbIndexSection(CUMap&: OffsetMap, NumCUs: CUIndex);
822}
823
824void DWARFRewriter::updateUnitDebugInfo(
825 DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
826 DebugRangesSectionWriter &RangesSectionWriter,
827 std::optional<uint64_t> RangesBase) {
828 // Cache debug ranges so that the offset for identical ranges could be reused.
829 std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
830
831 uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();
832 uint64_t NextCUOffset = Unit.getNextUnitOffset();
833 const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =
834 DIEBldr.getDIEsByUnit(DU&: Unit);
835
836 // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
837 auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,
838 const DIEValue &HighPCVal, uint64_t LowPC,
839 const uint64_t HighPC) {
840 dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;
841 dwarf::Form FormLowPC = dwarf::DW_FORM_addr;
842 dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;
843 dwarf::Form FormHighPC = dwarf::DW_FORM_data4;
844 const uint32_t Size = HighPC - LowPC;
845 // Whatever was generated is not low_pc/high_pc, so will reset to
846 // default for size 1.
847 if (!LowPCVal || !HighPCVal) {
848 if (Unit.getVersion() >= 5)
849 FormLowPC = dwarf::DW_FORM_addrx;
850 else if (Unit.isDWOUnit())
851 FormLowPC = dwarf::DW_FORM_GNU_addr_index;
852 } else {
853 AttrLowPC = LowPCVal.getAttribute();
854 FormLowPC = LowPCVal.getForm();
855 AttrHighPC = HighPCVal.getAttribute();
856 FormHighPC = HighPCVal.getForm();
857 }
858
859 if (FormLowPC == dwarf::DW_FORM_addrx ||
860 FormLowPC == dwarf::DW_FORM_GNU_addr_index)
861 LowPC = AddrWriter->getIndexFromAddress(Address: LowPC, CU&: Unit);
862
863 if (LowPCVal)
864 DIEBldr.replaceValue(Die, Attribute: AttrLowPC, Form: FormLowPC, NewValue: DIEInteger(LowPC));
865 else
866 DIEBldr.addValue(Die, Attribute: AttrLowPC, Form: FormLowPC, Value: DIEInteger(LowPC));
867 if (HighPCVal) {
868 DIEBldr.replaceValue(Die, Attribute: AttrHighPC, Form: FormHighPC, NewValue: DIEInteger(Size));
869 } else {
870 DIEBldr.deleteValue(Die, Attribute: dwarf::DW_AT_ranges);
871 DIEBldr.addValue(Die, Attribute: AttrHighPC, Form: FormHighPC, Value: DIEInteger(Size));
872 }
873 };
874
875 for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {
876 DIE *Die = DI->Die;
877 switch (Die->getTag()) {
878 case dwarf::DW_TAG_compile_unit:
879 case dwarf::DW_TAG_skeleton_unit: {
880 // For dwarf5 section 3.1.3
881 // The following attributes are not part of a split full compilation unit
882 // entry but instead are inherited (if present) from the corresponding
883 // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges,
884 // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base,
885 // DW_AT_addr_base and DW_AT_rnglists_base.
886 if (Unit.getVersion() == 5 && Unit.isDWOUnit())
887 continue;
888 auto ModuleRangesOrError = getDIEAddressRanges(Die: *Die, DU&: Unit);
889 if (!ModuleRangesOrError) {
890 consumeError(Err: ModuleRangesOrError.takeError());
891 break;
892 }
893 DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;
894 DebugAddressRangesVector OutputRanges =
895 BC.translateModuleAddressRanges(InputRanges: ModuleRanges);
896 DIEValue LowPCAttrInfo = Die->findAttribute(Attribute: dwarf::DW_AT_low_pc);
897 // For a case where LLD GCs only function used in the CU.
898 // If CU doesn't have DW_AT_low_pc we are not going to convert,
899 // so don't need to do anything.
900 if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)
901 OutputRanges.push_back(Elt: {0, 0});
902 const uint64_t RangesSectionOffset =
903 RangesSectionWriter.addRanges(Ranges&: OutputRanges);
904 // Don't emit the zero low_pc arange.
905 if (!Unit.isDWOUnit() && !OutputRanges.empty() &&
906 OutputRanges.back().LowPC)
907 ARangesSectionWriter->addCURanges(CUOffset: Unit.getOffset(),
908 Ranges: std::move(OutputRanges));
909 updateDWARFObjectAddressRanges(Unit, DIEBldr, Die&: *Die, DebugRangesOffset: RangesSectionOffset,
910 RangesBase);
911 DIEValue StmtListAttrVal = Die->findAttribute(Attribute: dwarf::DW_AT_stmt_list);
912 if (LineTablePatchMap.count(x: &Unit))
913 DIEBldr.replaceValue(Die, Attribute: dwarf::DW_AT_stmt_list,
914 Form: StmtListAttrVal.getForm(),
915 NewValue: DIEInteger(LineTablePatchMap[&Unit]));
916 break;
917 }
918
919 case dwarf::DW_TAG_subprogram: {
920 // Get function address either from ranges or [LowPC, HighPC) pair.
921 uint64_t Address = UINT64_MAX;
922 uint64_t SectionIndex, HighPC;
923 DebugAddressRangesVector FunctionRanges;
924 if (!getLowAndHighPC(Die: *Die, DU: Unit, LowPC&: Address, HighPC, SectionIndex)) {
925 Expected<DWARFAddressRangesVector> RangesOrError =
926 getDIEAddressRanges(Die: *Die, DU&: Unit);
927 if (!RangesOrError) {
928 consumeError(Err: RangesOrError.takeError());
929 break;
930 }
931 DWARFAddressRangesVector Ranges = *RangesOrError;
932 // Not a function definition.
933 if (Ranges.empty())
934 break;
935
936 for (const DWARFAddressRange &Range : Ranges) {
937 if (const BinaryFunction *Function =
938 BC.getBinaryFunctionAtAddress(Address: Range.LowPC))
939 FunctionRanges.append(RHS: Function->getOutputAddressRanges());
940 }
941 } else {
942 if (const BinaryFunction *Function =
943 BC.getBinaryFunctionAtAddress(Address))
944 FunctionRanges = Function->getOutputAddressRanges();
945 }
946
947 // Clear cached ranges as the new function will have its own set.
948 CachedRanges.clear();
949 DIEValue LowPCVal = Die->findAttribute(Attribute: dwarf::DW_AT_low_pc);
950 DIEValue HighPCVal = Die->findAttribute(Attribute: dwarf::DW_AT_high_pc);
951 if (FunctionRanges.empty()) {
952 if (LowPCVal && HighPCVal)
953 FunctionRanges.push_back(Elt: {0, HighPCVal.getDIEInteger().getValue()});
954 else
955 FunctionRanges.push_back(Elt: {0, 1});
956 }
957
958 if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) {
959 updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC,
960 FunctionRanges.back().HighPC);
961 break;
962 }
963
964 updateDWARFObjectAddressRanges(
965 Unit, DIEBldr, Die&: *Die, DebugRangesOffset: RangesSectionWriter.addRanges(Ranges&: FunctionRanges));
966
967 break;
968 }
969 case dwarf::DW_TAG_lexical_block:
970 case dwarf::DW_TAG_inlined_subroutine:
971 case dwarf::DW_TAG_try_block:
972 case dwarf::DW_TAG_catch_block: {
973 uint64_t RangesSectionOffset = 0;
974 Expected<DWARFAddressRangesVector> RangesOrError =
975 getDIEAddressRanges(Die: *Die, DU&: Unit);
976 const BinaryFunction *Function =
977 RangesOrError && !RangesOrError->empty()
978 ? BC.getBinaryFunctionContainingAddress(
979 Address: RangesOrError->front().LowPC)
980 : nullptr;
981 DebugAddressRangesVector OutputRanges;
982 if (Function) {
983 OutputRanges = translateInputToOutputRanges(BF: *Function, InputRanges: *RangesOrError);
984 LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {
985 dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
986 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"
987 << Twine::utohexstr(Unit.getOffset()) << '\n';
988 });
989 if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {
990 RangesSectionOffset = RangesSectionWriter.addRanges(
991 Ranges: std::move(OutputRanges), CachedRanges);
992 OutputRanges.clear();
993 } else if (OutputRanges.empty()) {
994 OutputRanges.push_back(Elt: {0, RangesOrError.get().front().HighPC});
995 }
996 } else if (!RangesOrError) {
997 consumeError(Err: RangesOrError.takeError());
998 } else {
999 OutputRanges.push_back(Elt: {0, !RangesOrError->empty()
1000 ? RangesOrError.get().front().HighPC
1001 : 0});
1002 }
1003 DIEValue LowPCVal = Die->findAttribute(Attribute: dwarf::DW_AT_low_pc);
1004 DIEValue HighPCVal = Die->findAttribute(Attribute: dwarf::DW_AT_high_pc);
1005 if (OutputRanges.size() == 1) {
1006 updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,
1007 OutputRanges.back().HighPC);
1008 break;
1009 }
1010 updateDWARFObjectAddressRanges(Unit, DIEBldr, Die&: *Die, DebugRangesOffset: RangesSectionOffset);
1011 break;
1012 }
1013 case dwarf::DW_TAG_call_site: {
1014 auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void {
1015 std::optional<uint64_t> Address = getAsAddress(DU: Unit, AttrVal);
1016 const BinaryFunction *Function =
1017 BC.getBinaryFunctionContainingAddress(Address: *Address);
1018 uint64_t UpdatedAddress = *Address;
1019 if (Function)
1020 UpdatedAddress =
1021 Function->translateInputToOutputAddress(Address: UpdatedAddress);
1022
1023 if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {
1024 const uint32_t Index =
1025 AddrWriter->getIndexFromAddress(Address: UpdatedAddress, CU&: Unit);
1026 DIEBldr.replaceValue(Die, Attribute: AttrVal.getAttribute(), Form: AttrVal.getForm(),
1027 NewValue: DIEInteger(Index));
1028 } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {
1029 DIEBldr.replaceValue(Die, Attribute: AttrVal.getAttribute(), Form: AttrVal.getForm(),
1030 NewValue: DIEInteger(UpdatedAddress));
1031 } else {
1032 errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";
1033 }
1034 };
1035 DIEValue CallPcAttrVal = Die->findAttribute(Attribute: dwarf::DW_AT_call_pc);
1036 if (CallPcAttrVal)
1037 patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");
1038
1039 DIEValue CallRetPcAttrVal =
1040 Die->findAttribute(Attribute: dwarf::DW_AT_call_return_pc);
1041 if (CallRetPcAttrVal)
1042 patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc");
1043
1044 break;
1045 }
1046 default: {
1047 // Handle any tag that can have DW_AT_location attribute.
1048 DIEValue LocAttrInfo = Die->findAttribute(Attribute: dwarf::DW_AT_location);
1049 DIEValue LowPCAttrInfo = Die->findAttribute(Attribute: dwarf::DW_AT_low_pc);
1050 if (LocAttrInfo) {
1051 if (doesFormBelongToClass(Form: LocAttrInfo.getForm(),
1052 FC: DWARFFormValue::FC_Constant,
1053 DwarfVersion: Unit.getVersion()) ||
1054 doesFormBelongToClass(Form: LocAttrInfo.getForm(),
1055 FC: DWARFFormValue::FC_SectionOffset,
1056 DwarfVersion: Unit.getVersion())) {
1057 uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx
1058 ? LocAttrInfo.getDIELocList().getValue()
1059 : LocAttrInfo.getDIEInteger().getValue();
1060 DebugLocationsVector InputLL;
1061
1062 std::optional<object::SectionedAddress> SectionAddress =
1063 Unit.getBaseAddress();
1064 uint64_t BaseAddress = 0;
1065 if (SectionAddress)
1066 BaseAddress = SectionAddress->Address;
1067
1068 if (Unit.getVersion() >= 5 &&
1069 LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) {
1070 std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Index: Offset);
1071 assert(LocOffset && "Location Offset is invalid.");
1072 Offset = *LocOffset;
1073 }
1074
1075 Error E = Unit.getLocationTable().visitLocationList(
1076 Offset: &Offset, Callback: [&](const DWARFLocationEntry &Entry) {
1077 switch (Entry.Kind) {
1078 default:
1079 llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
1080 case dwarf::DW_LLE_end_of_list:
1081 return false;
1082 case dwarf::DW_LLE_base_address: {
1083 assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
1084 "absolute address expected");
1085 BaseAddress = Entry.Value0;
1086 break;
1087 }
1088 case dwarf::DW_LLE_offset_pair:
1089 assert(
1090 (Entry.SectionIndex == SectionedAddress::UndefSection &&
1091 (!Unit.isDWOUnit() || Unit.getVersion() == 5)) &&
1092 "absolute address expected");
1093 InputLL.emplace_back(Args: DebugLocationEntry{
1094 .LowPC: BaseAddress + Entry.Value0, .HighPC: BaseAddress + Entry.Value1,
1095 .Expr: Entry.Loc});
1096 break;
1097 case dwarf::DW_LLE_start_length:
1098 InputLL.emplace_back(Args: DebugLocationEntry{
1099 .LowPC: Entry.Value0, .HighPC: Entry.Value0 + Entry.Value1, .Expr: Entry.Loc});
1100 break;
1101 case dwarf::DW_LLE_base_addressx: {
1102 std::optional<object::SectionedAddress> EntryAddress =
1103 Unit.getAddrOffsetSectionItem(Index: Entry.Value0);
1104 assert(EntryAddress && "base Address not found.");
1105 BaseAddress = EntryAddress->Address;
1106 break;
1107 }
1108 case dwarf::DW_LLE_startx_length: {
1109 std::optional<object::SectionedAddress> EntryAddress =
1110 Unit.getAddrOffsetSectionItem(Index: Entry.Value0);
1111 assert(EntryAddress && "Address does not exist.");
1112 InputLL.emplace_back(Args: DebugLocationEntry{
1113 .LowPC: EntryAddress->Address,
1114 .HighPC: EntryAddress->Address + Entry.Value1, .Expr: Entry.Loc});
1115 break;
1116 }
1117 case dwarf::DW_LLE_startx_endx: {
1118 std::optional<object::SectionedAddress> StartAddress =
1119 Unit.getAddrOffsetSectionItem(Index: Entry.Value0);
1120 assert(StartAddress && "Start Address does not exist.");
1121 std::optional<object::SectionedAddress> EndAddress =
1122 Unit.getAddrOffsetSectionItem(Index: Entry.Value1);
1123 assert(EndAddress && "Start Address does not exist.");
1124 InputLL.emplace_back(Args: DebugLocationEntry{
1125 .LowPC: StartAddress->Address, .HighPC: EndAddress->Address, .Expr: Entry.Loc});
1126 break;
1127 }
1128 }
1129 return true;
1130 });
1131
1132 if (E || InputLL.empty()) {
1133 consumeError(Err: std::move(E));
1134 errs() << "BOLT-WARNING: empty location list detected at 0x"
1135 << Twine::utohexstr(Val: Offset) << " for DIE at 0x" << Die
1136 << " in CU at 0x" << Twine::utohexstr(Val: Unit.getOffset())
1137 << '\n';
1138 } else {
1139 const uint64_t Address = InputLL.front().LowPC;
1140 DebugLocationsVector OutputLL;
1141 if (const BinaryFunction *Function =
1142 BC.getBinaryFunctionContainingAddress(Address)) {
1143 OutputLL = translateInputToOutputLocationList(BF: *Function, InputLL);
1144 LLVM_DEBUG(if (OutputLL.empty()) {
1145 dbgs() << "BOLT-DEBUG: location list translated to an empty "
1146 "one at 0x"
1147 << Die << " in CU at 0x"
1148 << Twine::utohexstr(Unit.getOffset()) << '\n';
1149 });
1150 } else {
1151 // It's possible for a subprogram to be removed and to have
1152 // address of 0. Adding this entry to output to preserve debug
1153 // information.
1154 OutputLL = InputLL;
1155 }
1156 DebugLocWriter.addList(DIEBldr, Die&: *Die, AttrInfo&: LocAttrInfo, LocList&: OutputLL);
1157 }
1158 } else {
1159 assert((doesFormBelongToClass(LocAttrInfo.getForm(),
1160 DWARFFormValue::FC_Exprloc,
1161 Unit.getVersion()) ||
1162 doesFormBelongToClass(LocAttrInfo.getForm(),
1163 DWARFFormValue::FC_Block,
1164 Unit.getVersion())) &&
1165 "unexpected DW_AT_location form");
1166 if (Unit.isDWOUnit() || Unit.getVersion() >= 5) {
1167 std::vector<uint8_t> Sblock;
1168 DIEValueList *AttrLocValList;
1169 if (doesFormBelongToClass(Form: LocAttrInfo.getForm(),
1170 FC: DWARFFormValue::FC_Exprloc,
1171 DwarfVersion: Unit.getVersion())) {
1172 for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {
1173 Sblock.push_back(x: Val.getDIEInteger().getValue());
1174 }
1175 DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc());
1176 AttrLocValList = static_cast<DIEValueList *>(LocAttr);
1177 } else {
1178 for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) {
1179 Sblock.push_back(x: Val.getDIEInteger().getValue());
1180 }
1181 DIEBlock *BlockAttr =
1182 const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock());
1183 AttrLocValList = static_cast<DIEValueList *>(BlockAttr);
1184 }
1185 ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);
1186 DataExtractor Data(
1187 StringRef((const char *)Expr.data(), Expr.size()),
1188 Unit.getContext().isLittleEndian(), 0);
1189 DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
1190 Unit.getFormParams().Format);
1191 uint32_t PrevOffset = 0;
1192 DIEValueList *NewAttr;
1193 DIEValue Value;
1194 uint32_t NewExprSize = 0;
1195 DIELoc *Loc = nullptr;
1196 DIEBlock *Block = nullptr;
1197 if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) {
1198 Loc = DIEBldr.allocateDIEValue<DIELoc>();
1199 NewAttr = Loc;
1200 Value = DIEValue(LocAttrInfo.getAttribute(),
1201 LocAttrInfo.getForm(), Loc);
1202 } else if (doesFormBelongToClass(Form: LocAttrInfo.getForm(),
1203 FC: DWARFFormValue::FC_Block,
1204 DwarfVersion: Unit.getVersion())) {
1205 Block = DIEBldr.allocateDIEValue<DIEBlock>();
1206 NewAttr = Block;
1207 Value = DIEValue(LocAttrInfo.getAttribute(),
1208 LocAttrInfo.getForm(), Block);
1209 } else {
1210 errs() << "BOLT-WARNING: Unexpected Form value in Updating "
1211 "DW_AT_Location\n";
1212 continue;
1213 }
1214
1215 for (const DWARFExpression::Operation &Expr : LocExpr) {
1216 uint32_t CurEndOffset = PrevOffset + 1;
1217 if (Expr.getDescription().Op.size() == 1)
1218 CurEndOffset = Expr.getOperandEndOffset(Idx: 0);
1219 if (Expr.getDescription().Op.size() == 2)
1220 CurEndOffset = Expr.getOperandEndOffset(Idx: 1);
1221 if (Expr.getDescription().Op.size() > 2)
1222 errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "
1223 "number of operands.\n";
1224 // not addr index, just copy.
1225 if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
1226 Expr.getCode() == dwarf::DW_OP_addrx)) {
1227 auto Itr = AttrLocValList->values().begin();
1228 std::advance(i&: Itr, n: PrevOffset);
1229 uint32_t CopyNum = CurEndOffset - PrevOffset;
1230 NewExprSize += CopyNum;
1231 while (CopyNum--) {
1232 DIEBldr.addValue(Die: NewAttr, V: *Itr);
1233 std::advance(i&: Itr, n: 1);
1234 }
1235 } else {
1236 const uint64_t Index = Expr.getRawOperand(Idx: 0);
1237 std::optional<object::SectionedAddress> EntryAddress =
1238 Unit.getAddrOffsetSectionItem(Index);
1239 assert(EntryAddress && "Address is not found.");
1240 assert(Index <= std::numeric_limits<uint32_t>::max() &&
1241 "Invalid Operand Index.");
1242 const uint32_t AddrIndex = AddrWriter->getIndexFromAddress(
1243 Address: EntryAddress->Address, CU&: Unit);
1244 // update Index into .debug_address section for DW_AT_location.
1245 // The Size field is not stored in IR, we need to minus 1 in
1246 // offset for each expr.
1247 SmallString<8> Tmp;
1248 raw_svector_ostream OSE(Tmp);
1249 encodeULEB128(Value: AddrIndex, OS&: OSE);
1250
1251 DIEBldr.addValue(Die: NewAttr, Attribute: static_cast<dwarf::Attribute>(0),
1252 Form: dwarf::DW_FORM_data1,
1253 Value: DIEInteger(Expr.getCode()));
1254 NewExprSize += 1;
1255 for (uint8_t Byte : Tmp) {
1256 DIEBldr.addValue(Die: NewAttr, Attribute: static_cast<dwarf::Attribute>(0),
1257 Form: dwarf::DW_FORM_data1, Value: DIEInteger(Byte));
1258 NewExprSize += 1;
1259 }
1260 }
1261 PrevOffset = CurEndOffset;
1262 }
1263
1264 // update the size since the index might be changed
1265 if (Loc)
1266 Loc->setSize(NewExprSize);
1267 else
1268 Block->setSize(NewExprSize);
1269 DIEBldr.replaceValue(Die, Attribute: LocAttrInfo.getAttribute(),
1270 Form: LocAttrInfo.getForm(), NewValue&: Value);
1271 }
1272 }
1273 } else if (LowPCAttrInfo) {
1274 uint64_t Address = 0;
1275 uint64_t SectionIndex = 0;
1276 if (getLowPC(Die: *Die, DU: Unit, LowPC&: Address, SectionIndex)) {
1277 uint64_t NewAddress = 0;
1278 if (const BinaryFunction *Function =
1279 BC.getBinaryFunctionContainingAddress(Address)) {
1280 NewAddress = Function->translateInputToOutputAddress(Address);
1281 LLVM_DEBUG(dbgs()
1282 << "BOLT-DEBUG: Fixing low_pc 0x"
1283 << Twine::utohexstr(Address) << " for DIE with tag "
1284 << Die->getTag() << " to 0x"
1285 << Twine::utohexstr(NewAddress) << '\n');
1286 }
1287
1288 dwarf::Form Form = LowPCAttrInfo.getForm();
1289 assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&
1290 "DW_FORM_LLVM_addrx_offset is not supported");
1291 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
1292 if (Form == dwarf::DW_FORM_addrx ||
1293 Form == dwarf::DW_FORM_GNU_addr_index) {
1294 const uint32_t Index = AddrWriter->getIndexFromAddress(
1295 Address: NewAddress ? NewAddress : Address, CU&: Unit);
1296 DIEBldr.replaceValue(Die, Attribute: LowPCAttrInfo.getAttribute(),
1297 Form: LowPCAttrInfo.getForm(), NewValue: DIEInteger(Index));
1298 } else {
1299 DIEBldr.replaceValue(Die, Attribute: LowPCAttrInfo.getAttribute(),
1300 Form: LowPCAttrInfo.getForm(),
1301 NewValue: DIEInteger(NewAddress));
1302 }
1303 } else if (opts::Verbosity >= 1) {
1304 errs() << "BOLT-WARNING: unexpected form value for attribute "
1305 "LowPCAttrInfo\n";
1306 }
1307 }
1308 }
1309 }
1310 }
1311 if (DIEOffset > NextCUOffset)
1312 errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"
1313 << Twine::utohexstr(Val: Unit.getOffset()) << '\n';
1314}
1315
1316void DWARFRewriter::updateDWARFObjectAddressRanges(
1317 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
1318 std::optional<uint64_t> RangesBase) {
1319
1320 if (RangesBase) {
1321 // If DW_AT_GNU_ranges_base is present, update it. No further modifications
1322 // are needed for ranges base.
1323
1324 DIEValue RangesBaseInfo = Die.findAttribute(Attribute: dwarf::DW_AT_GNU_ranges_base);
1325 if (!RangesBaseInfo) {
1326 RangesBaseInfo = Die.findAttribute(Attribute: dwarf::DW_AT_rnglists_base);
1327 }
1328
1329 if (RangesBaseInfo) {
1330 DIEBldr.replaceValue(Die: &Die, Attribute: RangesBaseInfo.getAttribute(),
1331 Form: RangesBaseInfo.getForm(),
1332 NewValue: DIEInteger(static_cast<uint32_t>(*RangesBase)));
1333 RangesBase = std::nullopt;
1334 }
1335 }
1336
1337 DIEValue LowPCAttrInfo = Die.findAttribute(Attribute: dwarf::DW_AT_low_pc);
1338 DIEValue RangesAttrInfo = Die.findAttribute(Attribute: dwarf::DW_AT_ranges);
1339 if (RangesAttrInfo) {
1340 // Case 1: The object was already non-contiguous and had DW_AT_ranges.
1341 // In this case we simply need to update the value of DW_AT_ranges
1342 // and introduce DW_AT_GNU_ranges_base if required.
1343 // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
1344 bool NeedConverted = false;
1345
1346 if (Unit.getVersion() >= 5 &&
1347 RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset)
1348 NeedConverted = true;
1349
1350 uint64_t CurRangeBase = 0;
1351 if (Unit.isDWOUnit()) {
1352 if (std::optional<uint64_t> DWOId = Unit.getDWOId())
1353 CurRangeBase = getDwoRangesBase(DWOId: *DWOId);
1354 else
1355 errs() << "BOLT-WARNING: [internal-dwarf-error]: DWOId is not found "
1356 "for DWO Unit.";
1357 }
1358 if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx)
1359 DIEBldr.replaceValue(Die: &Die, Attribute: dwarf::DW_AT_ranges, Form: dwarf::DW_FORM_rnglistx,
1360 NewValue: DIEInteger(DebugRangesOffset));
1361 else
1362 DIEBldr.replaceValue(Die: &Die, Attribute: dwarf::DW_AT_ranges, Form: RangesAttrInfo.getForm(),
1363 NewValue: DIEInteger(DebugRangesOffset - CurRangeBase));
1364
1365 if (!RangesBase) {
1366 if (LowPCAttrInfo &&
1367 LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index &&
1368 LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx)
1369 DIEBldr.replaceValue(Die: &Die, Attribute: dwarf::DW_AT_low_pc, Form: LowPCAttrInfo.getForm(),
1370 NewValue: DIEInteger(0));
1371 return;
1372 }
1373
1374 if (!(Die.getTag() == dwarf::DW_TAG_compile_unit ||
1375 Die.getTag() == dwarf::DW_TAG_skeleton_unit))
1376 return;
1377
1378 // If we are at this point we are in the CU/Skeleton CU, and
1379 // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist.
1380 if (Unit.getVersion() <= 4)
1381 DIEBldr.addValue(Die: &Die, Attribute: dwarf::DW_AT_GNU_ranges_base, Form: dwarf::DW_FORM_data4,
1382 Value: DIEInteger(*RangesBase));
1383 else if (Unit.getVersion() == 5)
1384 DIEBldr.addValue(Die: &Die, Attribute: dwarf::DW_AT_rnglists_base,
1385 Form: dwarf::DW_FORM_sec_offset, Value: DIEInteger(*RangesBase));
1386 else
1387 DIEBldr.addValue(Die: &Die, Attribute: dwarf::DW_AT_rnglists_base,
1388 Form: dwarf::DW_FORM_sec_offset, Value: DIEInteger(*RangesBase));
1389 return;
1390 }
1391
1392 // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
1393 // to back. Replace with new attributes and patch the DIE.
1394 DIEValue HighPCAttrInfo = Die.findAttribute(Attribute: dwarf::DW_AT_high_pc);
1395 if (LowPCAttrInfo && HighPCAttrInfo) {
1396
1397 convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, RangesSectionOffset: DebugRangesOffset,
1398 LowPCAttrInfo, HighPCAttrInfo, RangesBase);
1399 } else if (!(Unit.isDWOUnit() &&
1400 Die.getTag() == dwarf::DW_TAG_compile_unit)) {
1401 if (opts::Verbosity >= 1)
1402 errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
1403 << Unit.getOffset() << '\n';
1404 }
1405}
1406
1407void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
1408 ErrorOr<BinarySection &> DbgInfoSection =
1409 BC.getUniqueSectionByName(SectionName: ".debug_info");
1410 ErrorOr<BinarySection &> TypeInfoSection =
1411 BC.getUniqueSectionByName(SectionName: ".debug_types");
1412 assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||
1413 BC.DwCtx->getNumTypeUnits() == 0) &&
1414 "Was not able to retrieve Debug Types section.");
1415
1416 // There is no direct connection between CU and TU, but same offsets,
1417 // encoded in DW_AT_stmt_list, into .debug_line get modified.
1418 // We take advantage of that to map original CU line table offsets to new
1419 // ones.
1420 std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;
1421
1422 auto GetStatementListValue =
1423 [](const DWARFDie &DIE) -> std::optional<uint64_t> {
1424 std::optional<DWARFFormValue> StmtList = DIE.find(Attr: dwarf::DW_AT_stmt_list);
1425 if (!StmtList)
1426 return std::nullopt;
1427 std::optional<uint64_t> Offset = dwarf::toSectionOffset(V: StmtList);
1428 assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");
1429 return *Offset;
1430 };
1431
1432 SmallVector<DWARFUnit *, 1> TUs;
1433 for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1434 if (CU->isTypeUnit()) {
1435 TUs.push_back(Elt: CU.get());
1436 continue;
1437 }
1438 const unsigned CUID = CU->getOffset();
1439 MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
1440 if (!Label)
1441 continue;
1442
1443 std::optional<uint64_t> StmtOffset =
1444 GetStatementListValue(CU.get()->getUnitDIE());
1445 if (!StmtOffset)
1446 continue;
1447
1448 const uint64_t LineTableOffset = Layout.getSymbolOffset(S: *Label);
1449 DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
1450 assert(DbgInfoSection && ".debug_info section must exist");
1451 LineTablePatchMap[CU.get()] = LineTableOffset;
1452 }
1453
1454 for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())
1455 TUs.push_back(Elt: TU.get());
1456
1457 for (DWARFUnit *TU : TUs) {
1458 std::optional<uint64_t> StmtOffset =
1459 GetStatementListValue(TU->getUnitDIE());
1460 if (!StmtOffset)
1461 continue;
1462 auto Iter = DebugLineOffsetMap.find(x: *StmtOffset);
1463 if (Iter == DebugLineOffsetMap.end()) {
1464 // Implementation depends on TU sharing DW_AT_stmt_list with a CU.
1465 // Only case that it hasn't been true was for manually modified assembly
1466 // file. Adding this warning in case assumption is false.
1467 errs()
1468 << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"
1469 << Twine::utohexstr(Val: TU->getOffset())
1470 << " is not sharing "
1471 ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "
1472 "updated.\n";
1473 continue;
1474 }
1475 TypeUnitRelocMap[TU] = Iter->second;
1476 }
1477
1478 // Set .debug_info as finalized so it won't be skipped over when
1479 // we process sections while writing out the new binary. This ensures
1480 // that the pending relocations will be processed and not ignored.
1481 if (DbgInfoSection)
1482 DbgInfoSection->setIsFinalized();
1483
1484 if (TypeInfoSection)
1485 TypeInfoSection->setIsFinalized();
1486}
1487
1488CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
1489 DIEStreamer &Streamer) {
1490 // update TypeUnit DW_AT_stmt_list with new .debug_line information.
1491 auto updateLineTable = [&](const DWARFUnit &Unit) -> void {
1492 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(DU: Unit);
1493 DIEValue StmtAttrInfo = UnitDIE->findAttribute(Attribute: dwarf::DW_AT_stmt_list);
1494 if (!StmtAttrInfo || !TypeUnitRelocMap.count(x: &Unit))
1495 return;
1496 DIEBlder.replaceValue(Die: UnitDIE, Attribute: dwarf::DW_AT_stmt_list,
1497 Form: StmtAttrInfo.getForm(),
1498 NewValue: DIEInteger(TypeUnitRelocMap[&Unit]));
1499 };
1500
1501 // generate and populate abbrevs here
1502 DIEBlder.generateAbbrevs();
1503 DIEBlder.finish();
1504 SmallVector<char, 20> OutBuffer;
1505 std::shared_ptr<raw_svector_ostream> ObjOS =
1506 std::make_shared<raw_svector_ostream>(args&: OutBuffer);
1507 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1508 auto TheTriple = std::make_unique<Triple>(args: File->makeTriple());
1509 std::unique_ptr<DIEStreamer> TypeStreamer =
1510 createDIEStreamer(TheTriple: *TheTriple, OutFile&: *ObjOS, Swift5ReflectionSegmentName: "TypeStreamer", DIEBldr&: DIEBlder, Rewriter&: *this);
1511
1512 // generate debug_info and CUMap
1513 CUOffsetMap CUMap;
1514 for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
1515 if (!CU->isTypeUnit())
1516 continue;
1517 updateLineTable(*CU.get());
1518 emitUnit(DIEBldr&: DIEBlder, Streamer, Unit&: *CU.get());
1519 uint32_t StartOffset = CUOffset;
1520 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(DU: *CU.get());
1521 CUOffset += CU.get()->getHeaderSize();
1522 CUOffset += UnitDIE->getSize();
1523 CUMap[CU.get()->getOffset()] = {.Offset: StartOffset, .Length: CUOffset - StartOffset - 4};
1524 }
1525
1526 // Emit Type Unit of DWARF 4 to .debug_type section
1527 for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {
1528 updateLineTable(*TU);
1529 emitUnit(DIEBldr&: DIEBlder, Streamer&: *TypeStreamer, Unit&: *TU);
1530 }
1531
1532 TypeStreamer->finish();
1533
1534 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1535 MemoryBuffer::getMemBuffer(InputData: ObjOS->str(), BufferName: "in-memory object file", RequiresNullTerminator: false);
1536 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1537 ValOrErr: object::ObjectFile::createObjectFile(Object: ObjectMemBuffer->getMemBufferRef()),
1538 Msg: "error creating in-memory object");
1539
1540 for (const SectionRef &Section : Obj->sections()) {
1541 StringRef Contents = cantFail(ValOrErr: Section.getContents());
1542 StringRef Name = cantFail(ValOrErr: Section.getName());
1543 if (Name.equals(RHS: ".debug_types"))
1544 BC.registerOrUpdateNoteSection(Name: ".debug_types", Data: copyByteArray(Buffer: Contents),
1545 Size: Contents.size());
1546 }
1547 return CUMap;
1548}
1549
1550void DWARFRewriter::finalizeDebugSections(
1551 DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
1552 DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap) {
1553 if (StrWriter->isInitialized()) {
1554 RewriteInstance::addToDebugSectionsToOverwrite(Section: ".debug_str");
1555 std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
1556 StrWriter->releaseBuffer();
1557 BC.registerOrUpdateNoteSection(Name: ".debug_str",
1558 Data: copyByteArray(Buffer: *DebugStrSectionContents),
1559 Size: DebugStrSectionContents->size());
1560 }
1561
1562 if (StrOffstsWriter->isFinalized()) {
1563 RewriteInstance::addToDebugSectionsToOverwrite(Section: ".debug_str_offsets");
1564 std::unique_ptr<DebugStrOffsetsBufferVector>
1565 DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();
1566 BC.registerOrUpdateNoteSection(
1567 Name: ".debug_str_offsets", Data: copyByteArray(Buffer: *DebugStrOffsetsSectionContents),
1568 Size: DebugStrOffsetsSectionContents->size());
1569 }
1570
1571 if (BC.isDWARFLegacyUsed()) {
1572 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1573 LegacyRangesSectionWriter->releaseBuffer();
1574 BC.registerOrUpdateNoteSection(Name: ".debug_ranges",
1575 Data: copyByteArray(Buffer: *RangesSectionContents),
1576 Size: RangesSectionContents->size());
1577 }
1578
1579 if (BC.isDWARF5Used()) {
1580 std::unique_ptr<DebugBufferVector> RangesSectionContents =
1581 RangeListsSectionWriter->releaseBuffer();
1582 BC.registerOrUpdateNoteSection(Name: ".debug_rnglists",
1583 Data: copyByteArray(Buffer: *RangesSectionContents),
1584 Size: RangesSectionContents->size());
1585 }
1586
1587 if (BC.isDWARF5Used()) {
1588 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1589 makeFinalLocListsSection(Version: DWARFVersion::DWARF5);
1590 if (!LocationListSectionContents->empty())
1591 BC.registerOrUpdateNoteSection(
1592 Name: ".debug_loclists", Data: copyByteArray(Buffer: *LocationListSectionContents),
1593 Size: LocationListSectionContents->size());
1594 }
1595
1596 if (BC.isDWARFLegacyUsed()) {
1597 std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1598 makeFinalLocListsSection(Version: DWARFVersion::DWARFLegacy);
1599 if (!LocationListSectionContents->empty())
1600 BC.registerOrUpdateNoteSection(
1601 Name: ".debug_loc", Data: copyByteArray(Buffer: *LocationListSectionContents),
1602 Size: LocationListSectionContents->size());
1603 }
1604
1605 // AddrWriter should be finalized after debug_loc since more addresses can be
1606 // added there.
1607 if (AddrWriter->isInitialized()) {
1608 AddressSectionBuffer AddressSectionContents = AddrWriter->finalize();
1609 BC.registerOrUpdateNoteSection(Name: ".debug_addr",
1610 Data: copyByteArray(Buffer: AddressSectionContents),
1611 Size: AddressSectionContents.size());
1612 }
1613
1614 Streamer.emitAbbrevs(Abbrevs: DIEBlder.getAbbrevs(), DwarfVersion: BC.DwCtx->getMaxVersion());
1615 Streamer.finish();
1616
1617 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1618 MemoryBuffer::getMemBuffer(InputData: ObjOS.str(), BufferName: "in-memory object file", RequiresNullTerminator: false);
1619 std::unique_ptr<object::ObjectFile> Obj = cantFail(
1620 ValOrErr: object::ObjectFile::createObjectFile(Object: ObjectMemBuffer->getMemBufferRef()),
1621 Msg: "error creating in-memory object");
1622
1623 for (const SectionRef &Secs : Obj->sections()) {
1624 StringRef Contents = cantFail(ValOrErr: Secs.getContents());
1625 StringRef Name = cantFail(ValOrErr: Secs.getName());
1626 if (Name.equals(RHS: ".debug_abbrev")) {
1627 BC.registerOrUpdateNoteSection(Name: ".debug_abbrev", Data: copyByteArray(Buffer: Contents),
1628 Size: Contents.size());
1629 } else if (Name.equals(RHS: ".debug_info")) {
1630 BC.registerOrUpdateNoteSection(Name: ".debug_info", Data: copyByteArray(Buffer: Contents),
1631 Size: Contents.size());
1632 }
1633 }
1634
1635 // Skip .debug_aranges if we are re-generating .gdb_index.
1636 if (opts::KeepARanges || !BC.getGdbIndexSection()) {
1637 SmallVector<char, 16> ARangesBuffer;
1638 raw_svector_ostream OS(ARangesBuffer);
1639
1640 auto MAB = std::unique_ptr<MCAsmBackend>(
1641 BC.TheTarget->createMCAsmBackend(STI: *BC.STI, MRI: *BC.MRI, Options: MCTargetOptions()));
1642
1643 ARangesSectionWriter->writeARangesSection(RangesStream&: OS, CUMap);
1644 const StringRef &ARangesContents = OS.str();
1645
1646 BC.registerOrUpdateNoteSection(Name: ".debug_aranges",
1647 Data: copyByteArray(Buffer: ARangesContents),
1648 Size: ARangesContents.size());
1649 }
1650
1651 if (DebugNamesTable.isCreated()) {
1652 RewriteInstance::addToDebugSectionsToOverwrite(Section: ".debug_names");
1653 std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =
1654 DebugNamesTable.releaseBuffer();
1655 BC.registerOrUpdateNoteSection(Name: ".debug_names",
1656 Data: copyByteArray(Buffer: *DebugNamesSectionContents),
1657 Size: DebugNamesSectionContents->size());
1658 }
1659}
1660
1661void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
1662 DIEStreamer &Streamer,
1663 CUOffsetMap &CUMap,
1664 const std::list<DWARFUnit *> &CUs) {
1665 DIEBlder.generateAbbrevs();
1666 DIEBlder.finish();
1667 // generate debug_info and CUMap
1668 for (DWARFUnit *CU : CUs) {
1669 emitUnit(DIEBldr&: DIEBlder, Streamer, Unit&: *CU);
1670 const uint32_t StartOffset = CUOffset;
1671 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(DU: *CU);
1672 CUOffset += CU->getHeaderSize();
1673 CUOffset += UnitDIE->getSize();
1674 CUMap[CU->getOffset()] = {.Offset: StartOffset, .Length: CUOffset - StartOffset - 4};
1675 }
1676}
1677
1678// Creates all the data structures necessary for creating MCStreamer.
1679// They are passed by reference because they need to be kept around.
1680// Also creates known debug sections. These are sections handled by
1681// handleDebugDataPatching.
1682namespace {
1683
1684std::unique_ptr<BinaryContext>
1685createDwarfOnlyBC(const object::ObjectFile &File) {
1686 return cantFail(ValOrErr: BinaryContext::createBinaryContext(
1687 TheTriple: File.makeTriple(), InputFileName: File.getFileName(), Features: nullptr, IsPIC: false,
1688 DwCtx: DWARFContext::create(Obj: File, RelocAction: DWARFContext::ProcessDebugRelocations::Ignore,
1689 L: nullptr, DWPName: "", RecoverableErrorHandler: WithColor::defaultErrorHandler,
1690 WarningHandler: WithColor::defaultWarningHandler),
1691 Logger: {.Out: llvm::outs(), .Err: llvm::errs()}));
1692}
1693
1694StringMap<DWARFRewriter::KnownSectionsEntry>
1695createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {
1696 StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {
1697 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
1698 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
1699 {"debug_str_offsets.dwo",
1700 {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},
1701 {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},
1702 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
1703 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
1704 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
1705 {"debug_loclists.dwo",
1706 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
1707 {"debug_rnglists.dwo",
1708 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};
1709 return KnownSectionsTemp;
1710}
1711
1712StringRef getSectionName(const SectionRef &Section) {
1713 Expected<StringRef> SectionName = Section.getName();
1714 assert(SectionName && "Invalid section name.");
1715 StringRef Name = *SectionName;
1716 Name = Name.substr(Start: Name.find_first_not_of(Chars: "._"));
1717 return Name;
1718}
1719
1720// Exctracts an appropriate slice if input is DWP.
1721// Applies patches or overwrites the section.
1722std::optional<StringRef> updateDebugData(
1723 DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
1724 const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
1725 MCStreamer &Streamer, DWARFRewriter &Writer,
1726 const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
1727 std::unique_ptr<DebugBufferVector> &OutputBuffer,
1728 DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
1729 const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {
1730
1731 using DWOSectionContribution =
1732 const DWARFUnitIndex::Entry::SectionContribution;
1733 auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,
1734 StringRef OutData, DWARFSectionKind Sec,
1735 uint64_t &DWPOffset) -> StringRef {
1736 if (DWOEntry) {
1737 DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);
1738 DWPOffset = DWOContrubution->getOffset();
1739 OutData = OutData.substr(Start: DWPOffset, N: DWOContrubution->getLength());
1740 }
1741 return OutData;
1742 };
1743
1744 auto SectionIter = KnownSections.find(Key: SectionName);
1745 if (SectionIter == KnownSections.end())
1746 return std::nullopt;
1747 Streamer.switchSection(Section: SectionIter->second.first);
1748 uint64_t DWPOffset = 0;
1749
1750 auto getOverridenSection =
1751 [&](DWARFSectionKind Kind) -> std::optional<StringRef> {
1752 auto Iter = OverridenSections.find(x: Kind);
1753 if (Iter == OverridenSections.end()) {
1754 errs()
1755 << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
1756 "section for: "
1757 << Twine::utohexstr(Val: DWOId) << ".\n";
1758 return std::nullopt;
1759 }
1760 return Iter->second;
1761 };
1762 switch (SectionIter->second.second) {
1763 default: {
1764 if (!SectionName.equals(RHS: "debug_str.dwo"))
1765 errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
1766 << "\n";
1767 return SectionContents;
1768 }
1769 case DWARFSectionKind::DW_SECT_INFO: {
1770 return getOverridenSection(DWARFSectionKind::DW_SECT_INFO);
1771 }
1772 case DWARFSectionKind::DW_SECT_EXT_TYPES: {
1773 return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);
1774 }
1775 case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
1776 return getSliceData(CUDWOEntry, SectionContents,
1777 DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
1778 }
1779 case DWARFSectionKind::DW_SECT_ABBREV: {
1780 return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV);
1781 }
1782 case DWARFSectionKind::DW_SECT_EXT_LOC:
1783 case DWARFSectionKind::DW_SECT_LOCLISTS: {
1784 OutputBuffer = LocWriter.getBuffer();
1785 // Creating explicit StringRef here, otherwise
1786 // with implicit conversion it will take null byte as end of
1787 // string.
1788 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1789 OutputBuffer->size());
1790 }
1791 case DWARFSectionKind::DW_SECT_LINE: {
1792 return getSliceData(CUDWOEntry, SectionContents,
1793 DWARFSectionKind::DW_SECT_LINE, DWPOffset);
1794 }
1795 case DWARFSectionKind::DW_SECT_RNGLISTS: {
1796 assert(RangeListsWriter && "RangeListsWriter was not created.");
1797 OutputBuffer = RangeListsWriter->releaseBuffer();
1798 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
1799 OutputBuffer->size());
1800 }
1801 }
1802}
1803
1804} // namespace
1805
1806void DWARFRewriter::initDWPState(DWPState &State) {
1807 SmallString<0> OutputNameStr;
1808 StringRef OutputName;
1809 if (opts::DwarfOutputPath.empty()) {
1810 OutputName =
1811 Twine(opts::OutputFilename).concat(Suffix: ".dwp").toStringRef(Out&: OutputNameStr);
1812 } else {
1813 StringRef ExeFileName = llvm::sys::path::filename(path: opts::OutputFilename);
1814 OutputName = Twine(opts::DwarfOutputPath)
1815 .concat(Suffix: "/")
1816 .concat(Suffix: ExeFileName)
1817 .concat(Suffix: ".dwp")
1818 .toStringRef(Out&: OutputNameStr);
1819 errs() << "BOLT-WARNING: dwarf-output-path is in effect and .dwp file will "
1820 "possibly be written to another location that is not the same as "
1821 "the executable\n";
1822 }
1823 std::error_code EC;
1824 State.Out =
1825 std::make_unique<ToolOutputFile>(args&: OutputName, args&: EC, args: sys::fs::OF_None);
1826 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1827 State.TmpBC = createDwarfOnlyBC(File: *File);
1828 State.Streamer = State.TmpBC->createStreamer(OS&: State.Out->os());
1829 State.MCOFI = State.Streamer->getContext().getObjectFileInfo();
1830 State.KnownSections = createKnownSectionsMap(MCOFI: *State.MCOFI);
1831 MCSection *const StrSection = State.MCOFI->getDwarfStrDWOSection();
1832
1833 // Data Structures for DWP book keeping
1834 // Size of array corresponds to the number of sections supported by DWO format
1835 // in DWARF4/5.
1836
1837 State.Strings = std::make_unique<DWPStringPool>(args&: *State.Streamer, args: StrSection);
1838
1839 // Setup DWP code once.
1840 DWARFContext *DWOCtx = BC.getDWOContext();
1841
1842 if (DWOCtx) {
1843 State.CUIndex = &DWOCtx->getCUIndex();
1844 State.IsDWP = !State.CUIndex->getRows().empty();
1845 }
1846}
1847
1848void DWARFRewriter::finalizeDWP(DWPState &State) {
1849 if (State.Version < 5) {
1850 // Lie about there being no info contributions so the TU index only includes
1851 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
1852 // contribution to the info section, so we do not want to lie about it.
1853 State.ContributionOffsets[0] = 0;
1854 }
1855 writeIndex(Out&: *State.Streamer.get(), Section: State.MCOFI->getDwarfTUIndexSection(),
1856 ContributionOffsets: State.ContributionOffsets, IndexEntries: State.TypeIndexEntries,
1857 IndexVersion: State.IndexVersion);
1858
1859 if (State.Version < 5) {
1860 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
1861 // section does not exist, so no need to do anything about this.
1862 State.ContributionOffsets[getContributionIndex(Kind: DW_SECT_EXT_TYPES, IndexVersion: 2)] = 0;
1863 // Unlie about the info contribution
1864 State.ContributionOffsets[0] = 1;
1865 }
1866 writeIndex(Out&: *State.Streamer.get(), Section: State.MCOFI->getDwarfCUIndexSection(),
1867 ContributionOffsets: State.ContributionOffsets, IndexEntries: State.IndexEntries, IndexVersion: State.IndexVersion);
1868
1869 State.Streamer->finish();
1870 State.Out->keep();
1871}
1872
1873void DWARFRewriter::updateDWP(DWARFUnit &CU,
1874 const OverriddenSectionsMap &OverridenSections,
1875 const DWARFRewriter::UnitMeta &CUMI,
1876 DWARFRewriter::UnitMetaVectorType &TUMetaVector,
1877 DWPState &State, DebugLocWriter &LocWriter) {
1878 const uint64_t DWOId = *CU.getDWOId();
1879 MCSection *const StrOffsetSection = State.MCOFI->getDwarfStrOffDWOSection();
1880 assert(StrOffsetSection && "StrOffsetSection does not exist.");
1881 // Skipping CUs that we failed to load.
1882 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
1883 if (!DWOCU)
1884 return;
1885
1886 if (State.Version == 0) {
1887 State.Version = CU.getVersion();
1888 State.IndexVersion = State.Version < 5 ? 2 : 5;
1889 } else if (State.Version != CU.getVersion()) {
1890 errs() << "BOLT-ERROR: incompatible DWARF compile unit versions\n";
1891 exit(status: 1);
1892 }
1893
1894 UnitIndexEntry CurEntry = {};
1895 CurEntry.DWOName = dwarf::toString(
1896 V: CU.getUnitDIE().find(Attrs: {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
1897 Default: "");
1898 const char *Name = CU.getUnitDIE().getShortName();
1899 if (Name)
1900 CurEntry.Name = Name;
1901 StringRef CurStrSection;
1902 StringRef CurStrOffsetSection;
1903
1904 // This maps each section contained in this file to its length.
1905 // This information is later on used to calculate the contributions,
1906 // i.e. offset and length, of each compile/type unit to a section.
1907 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
1908
1909 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
1910 if (State.IsDWP)
1911 CUDWOEntry = State.CUIndex->getFromHash(Offset: DWOId);
1912
1913 bool StrSectionWrittenOut = false;
1914 const object::ObjectFile *DWOFile =
1915 (*DWOCU)->getContext().getDWARFObj().getFile();
1916
1917 DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
1918 if (CU.getVersion() == 5) {
1919 assert(RangeListsWritersByCU.count(DWOId) != 0 &&
1920 "No RangeListsWriter for DWO ID.");
1921 RangeListssWriter = RangeListsWritersByCU[DWOId].get();
1922 }
1923 auto AddType = [&](unsigned int Index, uint32_t IndexVersion, uint64_t Offset,
1924 uint64_t Length, uint64_t Hash) -> void {
1925 UnitIndexEntry TUEntry = CurEntry;
1926 if (IndexVersion < 5)
1927 TUEntry.Contributions[0] = {};
1928 TUEntry.Contributions[Index].setOffset(Offset);
1929 TUEntry.Contributions[Index].setLength(Length);
1930 State.ContributionOffsets[Index] +=
1931 TUEntry.Contributions[Index].getLength32();
1932 State.TypeIndexEntries.insert(KV: std::make_pair(x&: Hash, y&: TUEntry));
1933 };
1934 for (const SectionRef &Section : DWOFile->sections()) {
1935 std::unique_ptr<DebugBufferVector> OutputData;
1936 StringRef SectionName = getSectionName(Section);
1937 Expected<StringRef> ContentsExp = Section.getContents();
1938 assert(ContentsExp && "Invalid contents.");
1939 std::optional<StringRef> TOutData = updateDebugData(
1940 DWCtx&: (*DWOCU)->getContext(), SectionName, SectionContents: *ContentsExp, KnownSections: State.KnownSections,
1941 Streamer&: *State.Streamer, Writer&: *this, CUDWOEntry, DWOId, OutputBuffer&: OutputData,
1942 RangeListsWriter: RangeListssWriter, LocWriter, OverridenSections);
1943 if (!TOutData)
1944 continue;
1945
1946 StringRef OutData = *TOutData;
1947 if (SectionName == "debug_types.dwo") {
1948 State.Streamer->emitBytes(Data: OutData);
1949 continue;
1950 }
1951
1952 if (SectionName.equals(RHS: "debug_str.dwo")) {
1953 CurStrSection = OutData;
1954 } else {
1955 // Since handleDebugDataPatching returned true, we already know this is
1956 // a known section.
1957 auto SectionIter = State.KnownSections.find(Key: SectionName);
1958 if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
1959 CurStrOffsetSection = OutData;
1960 else
1961 State.Streamer->emitBytes(Data: OutData);
1962 unsigned int Index =
1963 getContributionIndex(Kind: SectionIter->second.second, IndexVersion: State.IndexVersion);
1964 uint64_t Offset = State.ContributionOffsets[Index];
1965 uint64_t Length = OutData.size();
1966 if (CU.getVersion() >= 5 &&
1967 SectionIter->second.second == DWARFSectionKind::DW_SECT_INFO) {
1968 for (UnitMeta &MI : TUMetaVector)
1969 MI.Offset += State.DebugInfoSize;
1970
1971 Offset = State.DebugInfoSize + CUMI.Offset;
1972 Length = CUMI.Length;
1973 State.DebugInfoSize += OutData.size();
1974 }
1975 CurEntry.Contributions[Index].setOffset(Offset);
1976 CurEntry.Contributions[Index].setLength(Length);
1977 State.ContributionOffsets[Index] +=
1978 CurEntry.Contributions[Index].getLength32();
1979 }
1980
1981 // Strings are combined in to a new string section, and de-duplicated
1982 // based on hash.
1983 if (!StrSectionWrittenOut && !CurStrOffsetSection.empty() &&
1984 !CurStrSection.empty()) {
1985 writeStringsAndOffsets(Out&: *State.Streamer.get(), Strings&: *State.Strings.get(),
1986 StrOffsetSection, CurStrSection,
1987 CurStrOffsetSection, Version: CU.getVersion());
1988 StrSectionWrittenOut = true;
1989 }
1990 }
1991 CompileUnitIdentifiers CUI{.Signature: DWOId, .Name: CurEntry.Name.c_str(),
1992 .DWOName: CurEntry.DWOName.c_str()};
1993 auto P = State.IndexEntries.insert(KV: std::make_pair(x&: CUI.Signature, y&: CurEntry));
1994 if (!P.second) {
1995 Error Err = buildDuplicateError(PrevE: *P.first, ID: CUI, DWPName: "");
1996 errs() << "BOLT-ERROR: " << toString(E: std::move(Err)) << "\n";
1997 return;
1998 }
1999
2000 // Handling TU
2001 const unsigned Index = getContributionIndex(
2002 Kind: State.IndexVersion < 5 ? DW_SECT_EXT_TYPES : DW_SECT_INFO,
2003 IndexVersion: State.IndexVersion);
2004 for (UnitMeta &MI : TUMetaVector)
2005 AddType(Index, State.IndexVersion, MI.Offset, MI.Length, MI.TUHash);
2006}
2007
2008void DWARFRewriter::writeDWOFiles(
2009 DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
2010 const std::string &DWOName, DebugLocWriter &LocWriter) {
2011 // Setup DWP code once.
2012 DWARFContext *DWOCtx = BC.getDWOContext();
2013 const uint64_t DWOId = *CU.getDWOId();
2014 const DWARFUnitIndex *CUIndex = nullptr;
2015 bool IsDWP = false;
2016 if (DWOCtx) {
2017 CUIndex = &DWOCtx->getCUIndex();
2018 IsDWP = !CUIndex->getRows().empty();
2019 }
2020
2021 // Skipping CUs that we failed to load.
2022 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
2023 if (!DWOCU) {
2024 errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "
2025 << Twine::utohexstr(Val: DWOId) << " is not found.\n";
2026 return;
2027 }
2028
2029 std::string CompDir = CU.getCompilationDir();
2030
2031 if (!opts::DwarfOutputPath.empty())
2032 CompDir = opts::DwarfOutputPath.c_str();
2033 else if (!opts::CompDirOverride.empty())
2034 CompDir = opts::CompDirOverride;
2035
2036 SmallString<16> AbsolutePath;
2037 sys::path::append(path&: AbsolutePath, a: CompDir);
2038 sys::path::append(path&: AbsolutePath, a: DWOName);
2039
2040 std::error_code EC;
2041 std::unique_ptr<ToolOutputFile> TempOut =
2042 std::make_unique<ToolOutputFile>(args&: AbsolutePath, args&: EC, args: sys::fs::OF_None);
2043
2044 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
2045 if (IsDWP)
2046 CUDWOEntry = CUIndex->getFromHash(Offset: DWOId);
2047
2048 const object::ObjectFile *File =
2049 (*DWOCU)->getContext().getDWARFObj().getFile();
2050 std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(File: *File);
2051 std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(OS&: TempOut->os());
2052 const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
2053 StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
2054
2055 DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
2056 if (CU.getVersion() == 5) {
2057 assert(RangeListsWritersByCU.count(DWOId) != 0 &&
2058 "No RangeListsWriter for DWO ID.");
2059 RangeListssWriter = RangeListsWritersByCU[DWOId].get();
2060
2061 // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not
2062 // have .debug_rnglists so won't be part of the loop below.
2063 if (!RangeListssWriter->empty()) {
2064 std::unique_ptr<DebugBufferVector> OutputData;
2065 if (std::optional<StringRef> OutData = updateDebugData(
2066 DWCtx&: (*DWOCU)->getContext(), SectionName: "debug_rnglists.dwo", SectionContents: "", KnownSections,
2067 Streamer&: *Streamer, Writer&: *this, CUDWOEntry, DWOId, OutputBuffer&: OutputData,
2068 RangeListsWriter: RangeListssWriter, LocWriter, OverridenSections))
2069 Streamer->emitBytes(Data: *OutData);
2070 }
2071 }
2072
2073 for (const SectionRef &Section : File->sections()) {
2074 std::unique_ptr<DebugBufferVector> OutputData;
2075 StringRef SectionName = getSectionName(Section);
2076 if (SectionName == "debug_rnglists.dwo")
2077 continue;
2078 Expected<StringRef> ContentsExp = Section.getContents();
2079 assert(ContentsExp && "Invalid contents.");
2080 if (std::optional<StringRef> OutData = updateDebugData(
2081 DWCtx&: (*DWOCU)->getContext(), SectionName, SectionContents: *ContentsExp, KnownSections,
2082 Streamer&: *Streamer, Writer&: *this, CUDWOEntry, DWOId, OutputBuffer&: OutputData, RangeListsWriter: RangeListssWriter,
2083 LocWriter, OverridenSections))
2084 Streamer->emitBytes(Data: *OutData);
2085 }
2086 Streamer->finish();
2087 TempOut->keep();
2088}
2089
2090void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
2091 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
2092 if (!BC.getGdbIndexSection())
2093 return;
2094 GDBIndexTUEntryVector.emplace_back(args: Entry);
2095}
2096
2097void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) {
2098 if (!BC.getGdbIndexSection())
2099 return;
2100
2101 // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
2102 // for .gdb_index section format.
2103
2104 StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
2105
2106 const char *Data = GdbIndexContents.data();
2107
2108 // Parse the header.
2109 const uint32_t Version = read32le(P: Data);
2110 if (Version != 7 && Version != 8) {
2111 errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
2112 exit(status: 1);
2113 }
2114
2115 // Some .gdb_index generators use file offsets while others use section
2116 // offsets. Hence we can only rely on offsets relative to each other,
2117 // and ignore their absolute values.
2118 const uint32_t CUListOffset = read32le(P: Data + 4);
2119 const uint32_t CUTypesOffset = read32le(P: Data + 8);
2120 const uint32_t AddressTableOffset = read32le(P: Data + 12);
2121 const uint32_t SymbolTableOffset = read32le(P: Data + 16);
2122 const uint32_t ConstantPoolOffset = read32le(P: Data + 20);
2123 Data += 24;
2124
2125 // Map CUs offsets to indices and verify existing index table.
2126 std::map<uint32_t, uint32_t> OffsetToIndexMap;
2127 const uint32_t CUListSize = CUTypesOffset - CUListOffset;
2128 const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
2129 const unsigned NUmCUsEncoded = CUListSize / 16;
2130 unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
2131 unsigned NumDWARF5TUs =
2132 getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
2133 bool SkipTypeUnits = false;
2134 // For DWARF5 Types are in .debug_info.
2135 // LLD doesn't generate Types CU List, and in CU list offset
2136 // only includes CUs.
2137 // GDB 11+ includes only CUs in CU list and generates Types
2138 // list.
2139 // GDB 9 includes CUs and TUs in CU list and generates TYpes
2140 // list. The NumCUs is CUs + TUs, so need to modify the check.
2141 // For split-dwarf
2142 // GDB-11, DWARF5: TU units from dwo are not included.
2143 // GDB-11, DWARF4: TU units from dwo are included.
2144 if (MaxDWARFVersion >= 5)
2145 SkipTypeUnits = !TUListSize ? true
2146 : ((NUmCUsEncoded + NumDWARF5TUs) ==
2147 BC.DwCtx->getNumCompileUnits());
2148
2149 if (!((CUListSize == NumCUs * 16) ||
2150 (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
2151 errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
2152 exit(status: 1);
2153 }
2154 DenseSet<uint64_t> OriginalOffsets;
2155 for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
2156 Index < Units; ++Index) {
2157 const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(index: Index);
2158 if (SkipTypeUnits && CU->isTypeUnit())
2159 continue;
2160 const uint64_t Offset = read64le(P: Data);
2161 Data += 16;
2162 if (CU->getOffset() != Offset) {
2163 errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
2164 exit(status: 1);
2165 }
2166
2167 OriginalOffsets.insert(V: Offset);
2168 OffsetToIndexMap[Offset] = Index;
2169 }
2170
2171 // Ignore old address table.
2172 const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
2173 // Move Data to the beginning of symbol table.
2174 Data += SymbolTableOffset - CUTypesOffset;
2175
2176 // Calculate the size of the new address table.
2177 uint32_t NewAddressTableSize = 0;
2178 for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
2179 const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
2180 NewAddressTableSize += Ranges.size() * 20;
2181 }
2182
2183 // Difference between old and new table (and section) sizes.
2184 // Could be negative.
2185 int32_t Delta = NewAddressTableSize - OldAddressTableSize;
2186
2187 size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
2188
2189 // Free'd by ExecutableFileMemoryManager.
2190 auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
2191 uint8_t *Buffer = NewGdbIndexContents;
2192
2193 write32le(P: Buffer, V: Version);
2194 write32le(P: Buffer + 4, V: CUListOffset);
2195 write32le(P: Buffer + 8, V: CUTypesOffset);
2196 write32le(P: Buffer + 12, V: AddressTableOffset);
2197 write32le(P: Buffer + 16, V: SymbolTableOffset + Delta);
2198 write32le(P: Buffer + 20, V: ConstantPoolOffset + Delta);
2199 Buffer += 24;
2200
2201 using MapEntry = std::pair<uint32_t, CUInfo>;
2202 std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
2203 // Need to sort since we write out all of TUs in .debug_info before CUs.
2204 std::sort(first: CUVector.begin(), last: CUVector.end(),
2205 comp: [](const MapEntry &E1, const MapEntry &E2) -> bool {
2206 return E1.second.Offset < E2.second.Offset;
2207 });
2208 // Writing out CU List <Offset, Size>
2209 for (auto &CUInfo : CUVector) {
2210 // Skipping TU for DWARF5 when they are not included in CU list.
2211 if (!OriginalOffsets.count(V: CUInfo.first))
2212 continue;
2213 write64le(P: Buffer, V: CUInfo.second.Offset);
2214 // Length encoded in CU doesn't contain first 4 bytes that encode length.
2215 write64le(P: Buffer + 8, V: CUInfo.second.Length + 4);
2216 Buffer += 16;
2217 }
2218
2219 // Rewrite TU CU List, since abbrevs can be different.
2220 // Entry example:
2221 // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
2222 // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
2223 // the second value is the type offset in the CU, and the third value is the
2224 // type signature" Looking at what is being generated by gdb-add-index. The
2225 // first entry is TU offset, second entry is offset from it, and third entry
2226 // is the type signature.
2227 if (TUListSize)
2228 for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
2229 write64le(P: Buffer, V: Entry.UnitOffset);
2230 write64le(P: Buffer + 8, V: Entry.TypeDIERelativeOffset);
2231 write64le(P: Buffer + 16, V: Entry.TypeHash);
2232 Buffer += sizeof(GDBIndexTUEntry);
2233 }
2234
2235 // Generate new address table.
2236 for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
2237 ARangesSectionWriter->getCUAddressRanges()) {
2238 const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
2239 const DebugAddressRangesVector &Ranges = CURangesPair.second;
2240 for (const DebugAddressRange &Range : Ranges) {
2241 write64le(P: Buffer, V: Range.LowPC);
2242 write64le(P: Buffer + 8, V: Range.HighPC);
2243 write32le(P: Buffer + 16, V: CUIndex);
2244 Buffer += 20;
2245 }
2246 }
2247
2248 const size_t TrailingSize =
2249 GdbIndexContents.data() + GdbIndexContents.size() - Data;
2250 assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
2251 "size calculation error");
2252
2253 // Copy over the rest of the original data.
2254 memcpy(dest: Buffer, src: Data, n: TrailingSize);
2255
2256 // Register the new section.
2257 BC.registerOrUpdateNoteSection(Name: ".gdb_index", Data: NewGdbIndexContents,
2258 Size: NewGdbIndexSize);
2259}
2260
2261std::unique_ptr<DebugBufferVector>
2262DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
2263 auto LocBuffer = std::make_unique<DebugBufferVector>();
2264 auto LocStream = std::make_unique<raw_svector_ostream>(args&: *LocBuffer);
2265 auto Writer =
2266 std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(OS&: *LocStream));
2267
2268 for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :
2269 LocListWritersByCU) {
2270 DebugLocWriter *LocWriter = Loc.second.get();
2271 auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(Val: LocWriter);
2272
2273 // Filter out DWARF4, writing out DWARF5
2274 if (Version == DWARFVersion::DWARF5 &&
2275 (!LocListWriter || LocListWriter->getDwarfVersion() <= 4))
2276 continue;
2277
2278 // Filter out DWARF5, writing out DWARF4
2279 if (Version == DWARFVersion::DWARFLegacy &&
2280 (LocListWriter && LocListWriter->getDwarfVersion() >= 5))
2281 continue;
2282
2283 // Skipping DWARF4/5 split dwarf.
2284 if (LocListWriter && LocListWriter->getDwarfVersion() <= 4)
2285 continue;
2286 std::unique_ptr<DebugBufferVector> CurrCULocationLists =
2287 LocWriter->getBuffer();
2288 *LocStream << *CurrCULocationLists;
2289 }
2290
2291 return LocBuffer;
2292}
2293
2294void DWARFRewriter::convertToRangesPatchDebugInfo(
2295 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
2296 uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
2297 DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {
2298 uint32_t BaseOffset = 0;
2299 dwarf::Form LowForm = LowPCAttrInfo.getForm();
2300 dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
2301 dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;
2302
2303 if (Unit.getVersion() >= 5) {
2304 RangeBaseAttribute = dwarf::DW_AT_rnglists_base;
2305 RangesForm = dwarf::DW_FORM_rnglistx;
2306 } else if (Unit.getVersion() < 4) {
2307 RangesForm = dwarf::DW_FORM_data4;
2308 }
2309 bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit ||
2310 Die.getTag() == dwarf::DW_TAG_skeleton_unit;
2311 if (!IsUnitDie)
2312 DIEBldr.deleteValue(Die: &Die, Attribute: LowPCAttrInfo.getAttribute());
2313 // In DWARF4 for DW_AT_low_pc in binary DW_FORM_addr is used. In the DWO
2314 // section DW_FORM_GNU_addr_index is used. So for if we are converting
2315 // DW_AT_low_pc/DW_AT_high_pc and see DW_FORM_GNU_addr_index. We are
2316 // converting in DWO section, and DW_AT_ranges [DW_FORM_sec_offset] is
2317 // relative to DW_AT_GNU_ranges_base.
2318 if (LowForm == dwarf::DW_FORM_GNU_addr_index) {
2319 // Ranges are relative to DW_AT_GNU_ranges_base.
2320 uint64_t CurRangeBase = 0;
2321 if (std::optional<uint64_t> DWOId = Unit.getDWOId()) {
2322 CurRangeBase = getDwoRangesBase(DWOId: *DWOId);
2323 }
2324 BaseOffset = CurRangeBase;
2325 } else {
2326 // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
2327 // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
2328 // when it's absent.
2329 if (IsUnitDie) {
2330 if (LowForm == dwarf::DW_FORM_addrx) {
2331 const uint32_t Index = AddrWriter->getIndexFromAddress(Address: 0, CU&: Unit);
2332 DIEBldr.replaceValue(Die: &Die, Attribute: LowPCAttrInfo.getAttribute(),
2333 Form: LowPCAttrInfo.getForm(), NewValue: DIEInteger(Index));
2334 } else {
2335 DIEBldr.replaceValue(Die: &Die, Attribute: LowPCAttrInfo.getAttribute(),
2336 Form: LowPCAttrInfo.getForm(), NewValue: DIEInteger(0));
2337 }
2338 }
2339 // Original CU didn't have DW_AT_*_base. We converted it's children (or
2340 // dwo), so need to insert it into CU.
2341 if (RangesBase)
2342 DIEBldr.addValue(Die: &Die, Attribute: RangeBaseAttribute, Form: dwarf::DW_FORM_sec_offset,
2343 Value: DIEInteger(*RangesBase));
2344 }
2345
2346 uint64_t RangeAttrVal = RangesSectionOffset - BaseOffset;
2347 if (Unit.getVersion() >= 5)
2348 RangeAttrVal = RangesSectionOffset;
2349 // HighPC was conveted into DW_AT_ranges.
2350 // For DWARF5 we only access ranges through index.
2351
2352 DIEBldr.replaceValue(Die: &Die, Attribute: HighPCAttrInfo.getAttribute(), NewAttribute: dwarf::DW_AT_ranges,
2353 Form: RangesForm, NewValue: DIEInteger(RangeAttrVal));
2354}
2355

source code of bolt/lib/Rewrite/DWARFRewriter.cpp