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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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