xref: /llvm-project/bolt/lib/Rewrite/DWARFRewriter.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
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 
60 static mc::RegisterMCTargetOptionsFlags MOF;
61 
62 static void printDie(const DWARFDie &DIE) {
63   DIDumpOptions DumpOpts;
64   DumpOpts.ShowForm = true;
65   DumpOpts.Verbose = true;
66   DumpOpts.ChildRecurseDepth = 0;
67   DumpOpts.ShowChildren = false;
68   DIE.dump(dbgs(), 0, DumpOpts);
69 }
70 
71 /// Lazily parse DWARF DIE and print it out.
72 LLVM_ATTRIBUTE_UNUSED
73 static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {
74   uint64_t OriginalOffsets = DIEOffset;
75   uint64_t NextCUOffset = DU.getNextUnitOffset();
76   DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
77   DWARFDebugInfoEntry DIEEntry;
78   if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) {
79     if (DIEEntry.getAbbreviationDeclarationPtr()) {
80       DWARFDie DDie(&DU, &DIEEntry);
81       printDie(DDie);
82     } else {
83       dbgs() << "Failed to extract abbreviation for"
84              << Twine::utohexstr(OriginalOffsets) << "\n";
85     }
86   } else {
87     dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets)
88            << " \n";
89   }
90 }
91 
92 using 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.
96 static DebugAddressRangesVector
97 translateInputToOutputRanges(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(InputRanges.size());
104     llvm::transform(InputRanges, OutputRanges.begin(),
105                     [](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(OutputRanges, BF.translateInputToOutputRange(
113                                          {Range.LowPC, Range.HighPC}));
114 
115   // Post-processing pass to sort and merge ranges.
116   llvm::sort(OutputRanges);
117   DebugAddressRangesVector MergedRanges;
118   uint64_t PrevHighPC = 0;
119   for (const DebugAddressRange &Range : OutputRanges) {
120     if (Range.LowPC <= PrevHighPC) {
121       MergedRanges.back().HighPC =
122           std::max(MergedRanges.back().HighPC, Range.HighPC);
123     } else {
124       MergedRanges.emplace_back(Range.LowPC, Range.HighPC);
125     }
126     PrevHighPC = MergedRanges.back().HighPC;
127   }
128 
129   return MergedRanges;
130 }
131 
132 /// Similar to translateInputToOutputRanges() but operates on location lists.
133 static DebugLocationsVector
134 translateInputToOutputLocationList(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({Entry.LowPC, Entry.HighPC});
145     if (!OutRanges.empty() && !OutputLL.empty()) {
146       if (OutRanges.front().LowPC == OutputLL.back().HighPC &&
147           Entry.Expr == OutputLL.back().Expr) {
148         OutputLL.back().HighPC =
149             std::max(OutputLL.back().HighPC, OutRanges.front().HighPC);
150         OutRanges.erase(OutRanges.begin());
151       }
152     }
153     llvm::transform(OutRanges, std::back_inserter(OutputLL),
154                     [&Entry](const DebugAddressRange &R) {
155                       return DebugLocationEntry{R.LowPC, R.HighPC, Entry.Expr};
156                     });
157   }
158 
159   // Sort and merge adjacent entries with identical locations.
160   llvm::stable_sort(
161       OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) {
162         return A.LowPC < B.LowPC;
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(Entry.HighPC, MergedLL.back().HighPC);
170     } else {
171       const uint64_t Begin = std::max(Entry.LowPC, PrevHighPC);
172       const uint64_t End = std::max(Begin, Entry.HighPC);
173       MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr});
174     }
175     PrevHighPC = MergedLL.back().HighPC;
176     PrevExpr = &MergedLL.back().Expr;
177   }
178 
179   return MergedLL;
180 }
181 
182 using namespace dwarf_linker;
183 using namespace dwarf_linker::classic;
184 
185 namespace llvm {
186 namespace bolt {
187 /// Emits debug information into .debug_info or .debug_types section.
188 class DIEStreamer : public DwarfStreamer {
189   DIEBuilder *DIEBldr;
190   GDBIndex &GDBIndexSection;
191 
192 private:
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, 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(*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(Unit.getHeaderSize() + UnitDIE.getSize() - 4);
233     Asm.emitInt16(Version);
234 
235     // DWARF v5 reorders the address size and adds a unit type.
236     if (Version >= 5) {
237       Asm.emitInt8(UT);
238       Asm.emitInt8(Asm.MAI->getCodePointerSize());
239     }
240 
241     Asm.emitInt32(0);
242     if (Version <= 4) {
243       Asm.emitInt8(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>(Unit).getTypeHash();
251     DIE *TypeDIE = DIEBldr->getTypeDIE(Unit);
252     const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit);
253     GDBIndexSection.addGDBTypeUnitEntry(
254         {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()});
255     if (Unit.getVersion() < 5) {
256       // Switch the section to .debug_types section.
257       std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;
258       llvm::MCContext &MC = Asm.OutContext;
259       const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();
260 
261       MS->switchSection(MOFI->getDwarfTypesSection(0));
262       MC.setDwarfVersion(DwarfVersion);
263     } else
264       switchToDebugInfoSection(DwarfVersion);
265 
266     emitCommonHeader(Unit, UnitDIE, DwarfVersion);
267     Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature));
268     Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0);
269   }
270 
271   void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {
272     if (Unit.isTypeUnit())
273       emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion());
274     else
275       emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());
276   }
277 
278   void emitDIE(DIE &Die) override {
279     AsmPrinter &Asm = getAsmPrinter();
280     Asm.emitDwarfDIE(Die);
281   }
282 
283 public:
284   DIEStreamer(DIEBuilder *DIEBldr, GDBIndex &GDBIndexSection,
285               DWARFLinkerBase::OutputFileType OutFileType,
286               raw_pwrite_stream &OutFile,
287               DWARFLinkerBase::MessageHandlerTy Warning)
288       : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr),
289         GDBIndexSection(GDBIndexSection) {};
290 
291   using DwarfStreamer::emitCompileUnitHeader;
292 
293   void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
294     emitUnitHeader(Unit, UnitDIE);
295     emitDIE(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.
304 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
305                                           std::vector<dwarf::Attribute> Attrs) {
306   for (dwarf::Attribute &Attr : Attrs)
307     if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))
308       return Info;
309   return std::nullopt;
310 }
311 
312 } // namespace bolt
313 } // namespace llvm
314 
315 using namespace llvm;
316 using namespace llvm::support::endian;
317 using namespace object;
318 using namespace bolt;
319 
320 namespace opts {
321 
322 extern cl::OptionCategory BoltCategory;
323 extern cl::opt<unsigned> Verbosity;
324 extern cl::opt<std::string> OutputFilename;
325 
326 static cl::opt<bool> KeepARanges(
327     "keep-aranges",
328     cl::desc(
329         "keep or generate .debug_aranges section if .gdb_index is written"),
330     cl::Hidden, cl::cat(BoltCategory));
331 
332 static cl::opt<unsigned>
333     DebugThreadCount("debug-thread-count",
334                      cl::desc("specifies thread count for the multithreading "
335                               "for updating DWO debug info"),
336                      cl::init(1), cl::cat(BoltCategory));
337 
338 static cl::opt<std::string> DwarfOutputPath(
339     "dwarf-output-path",
340     cl::desc("Path to where .dwo files will be written out to."), cl::init(""),
341     cl::cat(BoltCategory));
342 
343 static cl::opt<bool> CreateDebugNames(
344     "create-debug-names-section",
345     cl::desc("Creates .debug_names section, if the input binary doesn't have "
346              "it already, for DWARF5 CU/TUs."),
347     cl::init(false), cl::cat(BoltCategory));
348 
349 static cl::opt<bool>
350     DebugSkeletonCu("debug-skeleton-cu",
351                     cl::desc("prints out offsets for abbrev and debug_info of "
352                              "Skeleton CUs that get patched."),
353                     cl::ZeroOrMore, cl::Hidden, cl::init(false),
354                     cl::cat(BoltCategory));
355 
356 static cl::opt<unsigned> BatchSize(
357     "cu-processing-batch-size",
358     cl::desc(
359         "Specifies the size of batches for processing CUs. Higher number has "
360         "better performance, but more memory usage. Default value is 1."),
361     cl::Hidden, cl::init(1), cl::cat(BoltCategory));
362 
363 static cl::opt<bool> AlwaysConvertToRanges(
364     "always-convert-to-ranges",
365     cl::desc("This option is for testing purposes only. It forces BOLT to "
366              "convert low_pc/high_pc to ranges always."),
367     cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));
368 
369 extern cl::opt<std::string> CompDirOverride;
370 } // namespace opts
371 
372 /// If DW_AT_low_pc exists sets LowPC and returns true.
373 static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
374                      uint64_t &SectionIndex) {
375   DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);
376   if (!DvalLowPc)
377     return false;
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.
403 static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {
404   DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
405   if (!DvalHighPc)
406     return false;
407   if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
408     HighPC = DvalHighPc.getDIEInteger().getValue();
409   else
410     HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
411   return true;
412 }
413 
414 /// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
415 /// true.
416 static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
417                             uint64_t &LowPC, uint64_t &HighPC,
418                             uint64_t &SectionIndex) {
419   uint64_t TempLowPC = LowPC;
420   uint64_t TempHighPC = HighPC;
421   uint64_t TempSectionIndex = SectionIndex;
422   if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) &&
423       getHighPC(Die, TempLowPC, TempHighPC)) {
424     LowPC = TempLowPC;
425     HighPC = TempHighPC;
426     SectionIndex = TempSectionIndex;
427     return true;
428   }
429   return false;
430 }
431 
432 static Expected<llvm::DWARFAddressRangesVector>
433 getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
434   uint64_t LowPC, HighPC, Index;
435   if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index))
436     return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
437   if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) {
438     if (Dval.getForm() == dwarf::DW_FORM_rnglistx)
439       return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue());
440 
441     return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue());
442   }
443 
444   return DWARFAddressRangesVector();
445 }
446 
447 static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
448                                             const DIEValue &AttrVal) {
449   DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());
450   if (std::optional<object::SectionedAddress> SA =
451           DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU))
452     return SA->Address;
453   return std::nullopt;
454 }
455 
456 static std::unique_ptr<DIEStreamer>
457 createDIEStreamer(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       &DIEBldr, GDBIndexSection, DWARFLinkerBase::OutputFileType::Object,
463       OutFile,
464       [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
465   Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
466   if (Err)
467     errs()
468         << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
469         << toString(std::move(Err)) << "\n";
470   return Streamer;
471 }
472 
473 static void emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer,
474                      DWARFUnit &Unit) {
475   DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit);
476   Streamer.emitUnit(Unit, *UnitDIE);
477 }
478 
479 static void emitDWOBuilder(const std::string &DWOName,
480                            DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
481                            DWARFUnit &SplitCU, DWARFUnit &CU,
482                            DebugLocWriter &LocWriter,
483                            DebugStrOffsetsWriter &StrOffstsWriter,
484                            DebugStrWriter &StrWriter, GDBIndex &GDBIndexSection,
485                            DebugRangesSectionWriter &TempRangesSectionWriter) {
486   // Populate debug_info and debug_abbrev for current dwo into StringRef.
487   DWODIEBuilder.generateAbbrevs();
488   DWODIEBuilder.finish();
489 
490   SmallVector<char, 20> OutBuffer;
491   std::shared_ptr<raw_svector_ostream> ObjOS =
492       std::make_shared<raw_svector_ostream>(OutBuffer);
493   const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();
494   auto TheTriple = std::make_unique<Triple>(File->makeTriple());
495   std::unique_ptr<DIEStreamer> Streamer =
496       createDIEStreamer(*TheTriple, *ObjOS, "DwoStreamerInitAug2",
497                         DWODIEBuilder, GDBIndexSection);
498   if (SplitCU.getContext().getMaxDWOVersion() >= 5) {
499     for (std::unique_ptr<llvm::DWARFUnit> &CU :
500          SplitCU.getContext().dwo_info_section_units()) {
501       if (!CU->isTypeUnit())
502         continue;
503       emitUnit(DWODIEBuilder, *Streamer, *CU.get());
504     }
505     emitUnit(DWODIEBuilder, *Streamer, SplitCU);
506   } else {
507     for (std::unique_ptr<llvm::DWARFUnit> &CU :
508          SplitCU.getContext().dwo_compile_units())
509       emitUnit(DWODIEBuilder, *Streamer, *CU.get());
510 
511     // emit debug_types sections for dwarf4
512     for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector())
513       emitUnit(DWODIEBuilder, *Streamer, *CU);
514   }
515 
516   Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(),
517                         SplitCU.getContext().getMaxVersion());
518   Streamer->finish();
519 
520   std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
521       MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
522   std::unique_ptr<object::ObjectFile> Obj = cantFail(
523       object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
524       "error creating in-memory object");
525 
526   DWARFRewriter::OverriddenSectionsMap OverriddenSections;
527   for (const SectionRef &Secs : Obj->sections()) {
528     StringRef Contents = cantFail(Secs.getContents());
529     StringRef Name = cantFail(Secs.getName());
530     DWARFSectionKind Kind =
531         StringSwitch<DWARFSectionKind>(Name)
532             .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV)
533             .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO)
534             .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES)
535             .Default(DWARFSectionKind::DW_SECT_EXT_unknown);
536     if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)
537       continue;
538     OverriddenSections[Kind] = Contents;
539   }
540   Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter,
541                          StrOffstsWriter, StrWriter, TempRangesSectionWriter);
542 }
543 
544 using DWARFUnitVec = std::vector<DWARFUnit *>;
545 using CUPartitionVector = std::vector<DWARFUnitVec>;
546 /// Partitions CUs in to buckets. Bucket size is controlled by
547 /// cu-processing-batch-size. All the CUs that have cross CU reference reference
548 /// as a source are put in to the same initial bucket.
549 static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {
550   CUPartitionVector Vec(2);
551   unsigned Counter = 0;
552   const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();
553   for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {
554     Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =
555         Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset());
556     if (!AbbrDeclSet) {
557       consumeError(AbbrDeclSet.takeError());
558       return Vec;
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(CU.get());
574     } else {
575       ++Counter;
576       Vec.back().push_back(CU.get());
577     }
578     if (Counter % opts::BatchSize == 0 && !Vec.back().empty())
579       Vec.push_back({});
580   }
581   return Vec;
582 }
583 
584 void DWARFRewriter::updateDebugInfo() {
585   ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
586   if (!DebugInfo)
587     return;
588 
589   ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
590   StrWriter = std::make_unique<DebugStrWriter>(*BC.DwCtx, false);
591   StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>(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>(&BC);
599     RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();
600   } else {
601     FinalAddrWriter = std::make_unique<DebugAddrWriter>(&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           &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase());
619       RangeListsSectionWriter->setAddressWriter(AddrW.get());
620       LocListWritersByCU[CUIndex] =
621           std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *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>(&BC, CU.getAddressByteSize());
636       AddressWritersByCU[CU.getOffset()] = std::move(AddrW);
637       LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
638       if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
639         assert(LegacyRangesWritersByCU.count(*DWOId) == 0 &&
640                "LegacyRangeLists writer for DWO unit already exists.");
641         auto LegacyRangesSectionWriterByCU =
642             std::make_unique<DebugRangesSectionWriter>();
643         LegacyRangesSectionWriterByCU->initSection(CU);
644         LegacyRangesWritersByCU[*DWOId] =
645             std::move(LegacyRangesSectionWriterByCU);
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(SplitCU);
661     DebugStrOffsetsWriter DWOStrOffstsWriter(BC);
662     DebugStrWriter DWOStrWriter((SplitCU).getContext(), true);
663     DWODIEBuilder.updateDWONameCompDirForTypes(
664         DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName);
665     DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true,
666                                          AddressWriter);
667 
668     updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter,
669                         TempRangesSectionWriter, AddressWriter);
670     DebugLocDWoWriter.finalize(DWODIEBuilder,
671                                *DWODIEBuilder.getUnitDIEbyUnit(SplitCU));
672     if (Unit.getVersion() >= 5)
673       TempRangesSectionWriter.finalizeSection();
674 
675     emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit,
676                    DebugLocDWoWriter, DWOStrOffstsWriter, 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);
685     DebugLocWriter &DebugLocWriter =
686         *LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get();
687     DebugRangesSectionWriter &RangesSectionWriter =
688         Unit.getVersion() >= 5 ? *RangeListsSectionWriter.get()
689                                : *LegacyRangesSectionWriter.get();
690     DebugAddrWriter &AddressWriter =
691         *AddressWritersByCU[Unit.getOffset()].get();
692     if (Unit.getVersion() >= 5)
693       RangeListsSectionWriter->setAddressWriter(&AddressWriter);
694     if (Unit.getVersion() >= 5) {
695       RangesBase = RangesSectionWriter.getSectionOffset() +
696                    getDWARF5RngListLocListHeaderSize();
697       RangesSectionWriter.initSection(Unit);
698       if (!SplitCU)
699         StrOffstsWriter->finalizeSection(Unit, DIEBlder);
700     } else if (SplitCU) {
701       RangesBase = LegacyRangesSectionWriter.get()->getSectionOffset();
702     }
703 
704     updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter,
705                         AddressWriter, RangesBase);
706     DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit));
707     if (Unit.getVersion() >= 5)
708       RangesSectionWriter.finalizeSection();
709   };
710 
711   DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
712   DIEBlder.buildTypeUnits(StrOffstsWriter.get());
713   SmallVector<char, 20> OutBuffer;
714   std::unique_ptr<raw_svector_ostream> ObjOS =
715       std::make_unique<raw_svector_ostream>(OutBuffer);
716   const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
717   auto TheTriple = std::make_unique<Triple>(File->makeTriple());
718   std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(
719       *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);
720   CUOffsetMap OffsetMap =
721       finalizeTypeSections(DIEBlder, *Streamer, GDBIndexSection);
722 
723   CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
724   const unsigned int ThreadCount =
725       std::min(opts::DebugThreadCount, opts::ThreadCount);
726   for (std::vector<DWARFUnit *> &Vec : PartVec) {
727     DIEBlder.buildCompileUnits(Vec);
728     llvm::SmallVector<std::unique_ptr<DIEBuilder>, 72> DWODIEBuildersByCU;
729     ThreadPoolInterface &ThreadPool =
730         ParallelUtilities::getThreadPool(ThreadCount);
731     for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) {
732       createRangeLocListAddressWriters(*CU);
733       std::optional<DWARFUnit *> SplitCU;
734       std::optional<uint64_t> DWOId = CU->getDWOId();
735       if (DWOId)
736         SplitCU = BC.getDWOCU(*DWOId);
737       if (!SplitCU)
738         continue;
739       DebugAddrWriter &AddressWriter =
740           *AddressWritersByCU[CU->getOffset()].get();
741       DebugRangesSectionWriter &TempRangesSectionWriter =
742           CU->getVersion() >= 5 ? *RangeListsWritersByCU[*DWOId].get()
743                                 : *LegacyRangesWritersByCU[*DWOId].get();
744       std::optional<std::string> DwarfOutputPath =
745           opts::DwarfOutputPath.empty()
746               ? std::nullopt
747               : std::optional<std::string>(opts::DwarfOutputPath.c_str());
748       std::string DWOName = DIEBlder.updateDWONameCompDir(
749           *StrOffstsWriter, *StrWriter, *CU, DwarfOutputPath, std::nullopt);
750       auto DWODIEBuilderPtr = std::make_unique<DIEBuilder>(
751           BC, &(**SplitCU).getContext(), DebugNamesTable, CU);
752       DIEBuilder &DWODIEBuilder =
753           *DWODIEBuildersByCU.emplace_back(std::move(DWODIEBuilderPtr)).get();
754       if (CU->getVersion() >= 5)
755         StrOffstsWriter->finalizeSection(*CU, DIEBlder);
756       // Important to capture CU and SplitCU by value here, otherwise when the
757       // thread is executed at some point after the current iteration of the
758       // loop, dereferencing CU/SplitCU in the call to processSplitCU means it
759       // will dereference a different variable than the one intended, causing a
760       // seg fault.
761       ThreadPool.async([&, DwarfOutputPath, DWOName, CU, SplitCU] {
762         processSplitCU(*CU, **SplitCU, TempRangesSectionWriter, AddressWriter,
763                        DWOName, DwarfOutputPath, DWODIEBuilder);
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, OffsetMap,
772                          DIEBlder.getProcessedCUs(), *FinalAddrWriter);
773   }
774 
775   DebugNamesTable.emitAccelTable();
776 
777   finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, OffsetMap,
778                         *FinalAddrWriter);
779   GDBIndexSection.updateGdbIndexSection(OffsetMap, CUIndex,
780                                         *ARangesSectionWriter);
781 }
782 
783 void DWARFRewriter::updateUnitDebugInfo(
784     DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
785     DebugRangesSectionWriter &RangesSectionWriter,
786     DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) {
787   // Cache debug ranges so that the offset for identical ranges could be reused.
788   std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
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(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(LowPC, Unit);
821 
822     if (LowPCVal)
823       DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
824     else
825       DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
826     if (HighPCVal) {
827       DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
828     } else {
829       DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges);
830       DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
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, Unit);
848       if (!ModuleRangesOrError) {
849         consumeError(ModuleRangesOrError.takeError());
850         break;
851       }
852       DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;
853       DebugAddressRangesVector OutputRanges =
854           BC.translateModuleAddressRanges(ModuleRanges);
855       DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
856       // For a case where LLD GCs only function used in the CU.
857       // If CU doesn't have DW_AT_low_pc we are not going to convert,
858       // so don't need to do anything.
859       if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)
860         OutputRanges.push_back({0, 0});
861       const uint64_t RangesSectionOffset =
862           RangesSectionWriter.addRanges(OutputRanges);
863       // Don't emit the zero low_pc arange.
864       if (!Unit.isDWOUnit() && !OutputRanges.empty() &&
865           OutputRanges.back().LowPC)
866         ARangesSectionWriter->addCURanges(Unit.getOffset(),
867                                           std::move(OutputRanges));
868       updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset,
869                                      RangesBase);
870       DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list);
871       if (LineTablePatchMap.count(&Unit))
872         DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list,
873                              StmtListAttrVal.getForm(),
874                              DIEInteger(LineTablePatchMap[&Unit]));
875       break;
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, Unit, Address, HighPC, SectionIndex)) {
884         Expected<DWARFAddressRangesVector> RangesOrError =
885             getDIEAddressRanges(*Die, Unit);
886         if (!RangesOrError) {
887           consumeError(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(Range.LowPC))
898             FunctionRanges.append(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(dwarf::DW_AT_low_pc);
909       DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
910       if (FunctionRanges.empty()) {
911         if (LowPCVal && HighPCVal)
912           FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()});
913         else
914           FunctionRanges.push_back({0, 1});
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, RangesSectionWriter.addRanges(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, Unit);
935       const BinaryFunction *Function =
936           RangesOrError && !RangesOrError->empty()
937               ? BC.getBinaryFunctionContainingAddress(
938                     RangesOrError->front().LowPC)
939               : nullptr;
940       DebugAddressRangesVector OutputRanges;
941       if (Function) {
942         OutputRanges = translateInputToOutputRanges(*Function, *RangesOrError);
943         LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {
944           dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
945                  << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"
946                  << Twine::utohexstr(Unit.getOffset()) << '\n';
947         });
948         if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {
949           RangesSectionOffset = RangesSectionWriter.addRanges(
950               std::move(OutputRanges), CachedRanges);
951           OutputRanges.clear();
952         } else if (OutputRanges.empty()) {
953           OutputRanges.push_back({0, RangesOrError.get().front().HighPC});
954         }
955       } else if (!RangesOrError) {
956         consumeError(RangesOrError.takeError());
957       } else {
958         OutputRanges.push_back({0, !RangesOrError->empty()
959                                        ? RangesOrError.get().front().HighPC
960                                        : 0});
961       }
962       DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
963       DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
964       if (OutputRanges.size() == 1) {
965         updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,
966                           OutputRanges.back().HighPC);
967         break;
968       }
969       updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, 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(Unit, AttrVal);
975         const BinaryFunction *Function =
976             BC.getBinaryFunctionContainingAddress(*Address);
977         uint64_t UpdatedAddress = *Address;
978         if (Function)
979           UpdatedAddress =
980               Function->translateInputToOutputAddress(UpdatedAddress);
981 
982         if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {
983           const uint32_t Index =
984               AddressWriter.getIndexFromAddress(UpdatedAddress, Unit);
985           DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
986                                DIEInteger(Index));
987         } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {
988           DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
989                                DIEInteger(UpdatedAddress));
990         } else {
991           errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";
992         }
993       };
994       DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc);
995       if (CallPcAttrVal)
996         patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");
997 
998       DIEValue CallRetPcAttrVal =
999           Die->findAttribute(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(dwarf::DW_AT_location);
1008       DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
1009       if (LocAttrInfo) {
1010         if (doesFormBelongToClass(LocAttrInfo.getForm(),
1011                                   DWARFFormValue::FC_Constant,
1012                                   Unit.getVersion()) ||
1013             doesFormBelongToClass(LocAttrInfo.getForm(),
1014                                   DWARFFormValue::FC_SectionOffset,
1015                                   Unit.getVersion())) {
1016           uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx
1017                                 ? LocAttrInfo.getDIELocList().getValue()
1018                                 : LocAttrInfo.getDIEInteger().getValue();
1019           DebugLocationsVector InputLL;
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(Offset);
1030             assert(LocOffset && "Location Offset is invalid.");
1031             Offset = *LocOffset;
1032           }
1033 
1034           Error E = Unit.getLocationTable().visitLocationList(
1035               &Offset, [&](const DWARFLocationEntry &Entry) {
1036                 switch (Entry.Kind) {
1037                 default:
1038                   llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
1039                 case dwarf::DW_LLE_end_of_list:
1040                   return false;
1041                 case dwarf::DW_LLE_base_address: {
1042                   assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
1043                          "absolute address expected");
1044                   BaseAddress = Entry.Value0;
1045                   break;
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(DebugLocationEntry{
1053                       BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,
1054                       Entry.Loc});
1055                   break;
1056                 case dwarf::DW_LLE_start_length:
1057                   InputLL.emplace_back(DebugLocationEntry{
1058                       Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});
1059                   break;
1060                 case dwarf::DW_LLE_base_addressx: {
1061                   std::optional<object::SectionedAddress> EntryAddress =
1062                       Unit.getAddrOffsetSectionItem(Entry.Value0);
1063                   assert(EntryAddress && "base Address not found.");
1064                   BaseAddress = EntryAddress->Address;
1065                   break;
1066                 }
1067                 case dwarf::DW_LLE_startx_length: {
1068                   std::optional<object::SectionedAddress> EntryAddress =
1069                       Unit.getAddrOffsetSectionItem(Entry.Value0);
1070                   assert(EntryAddress && "Address does not exist.");
1071                   InputLL.emplace_back(DebugLocationEntry{
1072                       EntryAddress->Address,
1073                       EntryAddress->Address + Entry.Value1, Entry.Loc});
1074                   break;
1075                 }
1076                 case dwarf::DW_LLE_startx_endx: {
1077                   std::optional<object::SectionedAddress> StartAddress =
1078                       Unit.getAddrOffsetSectionItem(Entry.Value0);
1079                   assert(StartAddress && "Start Address does not exist.");
1080                   std::optional<object::SectionedAddress> EndAddress =
1081                       Unit.getAddrOffsetSectionItem(Entry.Value1);
1082                   assert(EndAddress && "Start Address does not exist.");
1083                   InputLL.emplace_back(DebugLocationEntry{
1084                       StartAddress->Address, EndAddress->Address, Entry.Loc});
1085                   break;
1086                 }
1087                 }
1088                 return true;
1089               });
1090 
1091           if (E || InputLL.empty()) {
1092             consumeError(std::move(E));
1093             errs() << "BOLT-WARNING: empty location list detected at 0x"
1094                    << Twine::utohexstr(Offset) << " for DIE at 0x" << Die
1095                    << " in CU at 0x" << Twine::utohexstr(Unit.getOffset())
1096                    << '\n';
1097           } else {
1098             const uint64_t Address = InputLL.front().LowPC;
1099             DebugLocationsVector OutputLL;
1100             if (const BinaryFunction *Function =
1101                     BC.getBinaryFunctionContainingAddress(Address)) {
1102               OutputLL = translateInputToOutputLocationList(*Function, InputLL);
1103               LLVM_DEBUG(if (OutputLL.empty()) {
1104                 dbgs() << "BOLT-DEBUG: location list translated to an empty "
1105                           "one at 0x"
1106                        << Die << " in CU at 0x"
1107                        << Twine::utohexstr(Unit.getOffset()) << '\n';
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, LocAttrInfo, 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(LocAttrInfo.getForm(),
1129                                       DWARFFormValue::FC_Exprloc,
1130                                       Unit.getVersion())) {
1131               for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {
1132                 Sblock.push_back(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(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(LocAttrInfo.getForm(),
1162                                              DWARFFormValue::FC_Block,
1163                                              Unit.getVersion())) {
1164               Block = DIEBldr.allocateDIEValue<DIEBlock>();
1165               NewAttr = Block;
1166               Value = DIEValue(LocAttrInfo.getAttribute(),
1167                                LocAttrInfo.getForm(), Block);
1168             } else {
1169               errs() << "BOLT-WARNING: Unexpected Form value in Updating "
1170                         "DW_AT_Location\n";
1171               continue;
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(0);
1178               if (Expr.getDescription().Op.size() == 2)
1179                 CurEndOffset = Expr.getOperandEndOffset(1);
1180               if (Expr.getDescription().Op.size() > 2)
1181                 errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "
1182                           "number of operands.\n";
1183               // not addr index, just copy.
1184               if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
1185                     Expr.getCode() == dwarf::DW_OP_addrx)) {
1186                 auto Itr = AttrLocValList->values().begin();
1187                 std::advance(Itr, PrevOffset);
1188                 uint32_t CopyNum = CurEndOffset - PrevOffset;
1189                 NewExprSize += CopyNum;
1190                 while (CopyNum--) {
1191                   DIEBldr.addValue(NewAttr, *Itr);
1192                   std::advance(Itr, 1);
1193                 }
1194               } else {
1195                 const uint64_t Index = Expr.getRawOperand(0);
1196                 std::optional<object::SectionedAddress> EntryAddress =
1197                     Unit.getAddrOffsetSectionItem(Index);
1198                 assert(EntryAddress && "Address is not found.");
1199                 assert(Index <= std::numeric_limits<uint32_t>::max() &&
1200                        "Invalid Operand Index.");
1201                 const uint32_t AddrIndex = AddressWriter.getIndexFromAddress(
1202                     EntryAddress->Address, Unit);
1203                 // update Index into .debug_address section for DW_AT_location.
1204                 // The Size field is not stored in IR, we need to minus 1 in
1205                 // offset for each expr.
1206                 SmallString<8> Tmp;
1207                 raw_svector_ostream OSE(Tmp);
1208                 encodeULEB128(AddrIndex, OSE);
1209 
1210                 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1211                                  dwarf::DW_FORM_data1,
1212                                  DIEInteger(Expr.getCode()));
1213                 NewExprSize += 1;
1214                 for (uint8_t Byte : Tmp) {
1215                   DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
1216                                    dwarf::DW_FORM_data1, DIEInteger(Byte));
1217                   NewExprSize += 1;
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, LocAttrInfo.getAttribute(),
1229                                  LocAttrInfo.getForm(), Value);
1230           }
1231         }
1232       } else if (LowPCAttrInfo) {
1233         uint64_t Address = 0;
1234         uint64_t SectionIndex = 0;
1235         if (getLowPC(*Die, Unit, Address, SectionIndex)) {
1236           uint64_t NewAddress = 0;
1237           if (const BinaryFunction *Function =
1238                   BC.getBinaryFunctionContainingAddress(Address)) {
1239             NewAddress = Function->translateInputToOutputAddress(Address);
1240             LLVM_DEBUG(dbgs()
1241                        << "BOLT-DEBUG: Fixing low_pc 0x"
1242                        << Twine::utohexstr(Address) << " for DIE with tag "
1243                        << Die->getTag() << " to 0x"
1244                        << Twine::utohexstr(NewAddress) << '\n');
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                 NewAddress ? NewAddress : Address, Unit);
1255             DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1256                                  LowPCAttrInfo.getForm(), DIEInteger(Index));
1257           } else {
1258             DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
1259                                  LowPCAttrInfo.getForm(),
1260                                  DIEInteger(NewAddress));
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(Unit.getOffset()) << '\n';
1273 }
1274 
1275 void 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(dwarf::DW_AT_GNU_ranges_base);
1284     if (!RangesBaseInfo) {
1285       RangesBaseInfo = Die.findAttribute(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(*Unit.getDWOId());
1292         assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1293                "RangesWriter does not exist for DWOId");
1294         RangesWriterIterator->second->setDie(&Die);
1295       } else {
1296         DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(),
1297                              RangesBaseInfo.getForm(),
1298                              DIEInteger(static_cast<uint32_t>(*RangesBase)));
1299       }
1300       RangesBase = std::nullopt;
1301     }
1302   }
1303 
1304   DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc);
1305   DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges);
1306   if (RangesAttrInfo) {
1307     // Case 1: The object was already non-contiguous and had DW_AT_ranges.
1308     // In this case we simply need to update the value of DW_AT_ranges
1309     // and introduce DW_AT_GNU_ranges_base if required.
1310     // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
1311     bool NeedConverted = false;
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, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx,
1319                            DIEInteger(DebugRangesOffset));
1320     else
1321       DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(),
1322                            DIEInteger(DebugRangesOffset));
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, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(),
1329                              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, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
1341                        DIEInteger(INT_MAX));
1342       auto RangesWriterIterator =
1343           LegacyRangesWritersByCU.find(*Unit.getDWOId());
1344       assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1345              "RangesWriter does not exist for DWOId");
1346       RangesWriterIterator->second->setDie(&Die);
1347     } else if (Unit.getVersion() >= 5) {
1348       DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
1349                        dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
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(dwarf::DW_AT_high_pc);
1357   if (LowPCAttrInfo && HighPCAttrInfo) {
1358 
1359     convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset,
1360                                   LowPCAttrInfo, HighPCAttrInfo, RangesBase);
1361   } else if (!(Unit.isDWOUnit() &&
1362                Die.getTag() == dwarf::DW_TAG_compile_unit)) {
1363     if (opts::Verbosity >= 1)
1364       errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
1365              << Twine::utohexstr(Unit.getOffset()) << '\n';
1366   }
1367 }
1368 
1369 void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) {
1370   ErrorOr<BinarySection &> DbgInfoSection =
1371       BC.getUniqueSectionByName(".debug_info");
1372   ErrorOr<BinarySection &> TypeInfoSection =
1373       BC.getUniqueSectionByName(".debug_types");
1374   assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||
1375           BC.DwCtx->getNumTypeUnits() == 0) &&
1376          "Was not able to retrieve Debug Types section.");
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(dwarf::DW_AT_stmt_list);
1387     if (!StmtList)
1388       return std::nullopt;
1389     std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);
1390     assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");
1391     return *Offset;
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(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.get()->getUnitDIE());
1407     if (!StmtOffset)
1408       continue;
1409 
1410     const uint64_t LineTableOffset =
1411         Asm.getSymbolOffset(*Label);
1412     DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
1413     assert(DbgInfoSection && ".debug_info section must exist");
1414     LineTablePatchMap[CU.get()] = LineTableOffset;
1415   }
1416 
1417   for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())
1418     TUs.push_back(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(*StmtOffset);
1426     if (Iter == DebugLineOffsetMap.end()) {
1427       // Implementation depends on TU sharing DW_AT_stmt_list with a CU.
1428       // Only case that it hasn't been true was for manually modified assembly
1429       // file. Adding this warning in case assumption is false.
1430       errs()
1431           << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"
1432           << Twine::utohexstr(TU->getOffset())
1433           << " is not sharing "
1434              ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "
1435              "updated.\n";
1436       continue;
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 
1451 CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
1452                                                 DIEStreamer &Streamer,
1453                                                 GDBIndex &GDBIndexSection) {
1454   // update TypeUnit DW_AT_stmt_list with new .debug_line information.
1455   auto updateLineTable = [&](const DWARFUnit &Unit) -> void {
1456     DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit);
1457     DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);
1458     if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit))
1459       return;
1460     DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,
1461                           StmtAttrInfo.getForm(),
1462                           DIEInteger(TypeUnitRelocMap[&Unit]));
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>(OutBuffer);
1472   const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
1473   auto TheTriple = std::make_unique<Triple>(File->makeTriple());
1474   std::unique_ptr<DIEStreamer> TypeStreamer = createDIEStreamer(
1475       *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection);
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.get());
1483     emitUnit(DIEBlder, Streamer, *CU.get());
1484     uint32_t StartOffset = CUOffset;
1485     DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get());
1486     CUOffset += CU.get()->getHeaderSize();
1487     CUOffset += UnitDIE->getSize();
1488     CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
1489   }
1490 
1491   // Emit Type Unit of DWARF 4 to .debug_type section
1492   for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {
1493     updateLineTable(*TU);
1494     emitUnit(DIEBlder, *TypeStreamer, *TU);
1495   }
1496 
1497   TypeStreamer->finish();
1498 
1499   std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1500       MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
1501   std::unique_ptr<object::ObjectFile> Obj = cantFail(
1502       object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1503       "error creating in-memory object");
1504 
1505   for (const SectionRef &Section : Obj->sections()) {
1506     StringRef Contents = cantFail(Section.getContents());
1507     StringRef Name = cantFail(Section.getName());
1508     if (Name == ".debug_types")
1509       BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents),
1510                                      Contents.size());
1511   }
1512   return CUMap;
1513 }
1514 
1515 void DWARFRewriter::finalizeDebugSections(
1516     DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
1517     DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap,
1518     DebugAddrWriter &FinalAddrWriter) {
1519   if (StrWriter->isInitialized()) {
1520     RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
1521     std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
1522         StrWriter->releaseBuffer();
1523     BC.registerOrUpdateNoteSection(".debug_str",
1524                                    copyByteArray(*DebugStrSectionContents),
1525                                    DebugStrSectionContents->size());
1526   }
1527 
1528   if (StrOffstsWriter->isFinalized()) {
1529     RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");
1530     std::unique_ptr<DebugStrOffsetsBufferVector>
1531         DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();
1532     BC.registerOrUpdateNoteSection(
1533         ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents),
1534         DebugStrOffsetsSectionContents->size());
1535   }
1536 
1537   if (BC.isDWARFLegacyUsed()) {
1538     std::unique_ptr<DebugBufferVector> RangesSectionContents =
1539         LegacyRangesSectionWriter->releaseBuffer();
1540     BC.registerOrUpdateNoteSection(".debug_ranges",
1541                                    copyByteArray(*RangesSectionContents),
1542                                    RangesSectionContents->size());
1543   }
1544 
1545   if (BC.isDWARF5Used()) {
1546     std::unique_ptr<DebugBufferVector> RangesSectionContents =
1547         RangeListsSectionWriter->releaseBuffer();
1548     BC.registerOrUpdateNoteSection(".debug_rnglists",
1549                                    copyByteArray(*RangesSectionContents),
1550                                    RangesSectionContents->size());
1551   }
1552 
1553   if (BC.isDWARF5Used()) {
1554     std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1555         makeFinalLocListsSection(DWARFVersion::DWARF5);
1556     if (!LocationListSectionContents->empty())
1557       BC.registerOrUpdateNoteSection(
1558           ".debug_loclists", copyByteArray(*LocationListSectionContents),
1559           LocationListSectionContents->size());
1560   }
1561 
1562   if (BC.isDWARFLegacyUsed()) {
1563     std::unique_ptr<DebugBufferVector> LocationListSectionContents =
1564         makeFinalLocListsSection(DWARFVersion::DWARFLegacy);
1565     if (!LocationListSectionContents->empty())
1566       BC.registerOrUpdateNoteSection(
1567           ".debug_loc", copyByteArray(*LocationListSectionContents),
1568           LocationListSectionContents->size());
1569   }
1570 
1571   if (FinalAddrWriter.isInitialized()) {
1572     std::unique_ptr<AddressSectionBuffer> AddressSectionContents =
1573         FinalAddrWriter.releaseBuffer();
1574     BC.registerOrUpdateNoteSection(".debug_addr",
1575                                    copyByteArray(*AddressSectionContents),
1576                                    AddressSectionContents->size());
1577   }
1578 
1579   Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion());
1580   Streamer.finish();
1581 
1582   std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
1583       MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false);
1584   std::unique_ptr<object::ObjectFile> Obj = cantFail(
1585       object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
1586       "error creating in-memory object");
1587 
1588   for (const SectionRef &Secs : Obj->sections()) {
1589     StringRef Contents = cantFail(Secs.getContents());
1590     StringRef Name = cantFail(Secs.getName());
1591     if (Name == ".debug_abbrev") {
1592       BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents),
1593                                      Contents.size());
1594     } else if (Name == ".debug_info") {
1595       BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents),
1596                                      Contents.size());
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(*BC.STI, *BC.MRI, MCTargetOptions()));
1607 
1608     ARangesSectionWriter->writeARangesSection(OS, CUMap);
1609     const StringRef &ARangesContents = OS.str();
1610 
1611     BC.registerOrUpdateNoteSection(".debug_aranges",
1612                                    copyByteArray(ARangesContents),
1613                                    ARangesContents.size());
1614   }
1615 
1616   if (DebugNamesTable.isCreated()) {
1617     RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");
1618     std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =
1619         DebugNamesTable.releaseBuffer();
1620     BC.registerOrUpdateNoteSection(".debug_names",
1621                                    copyByteArray(*DebugNamesSectionContents),
1622                                    DebugNamesSectionContents->size());
1623   }
1624 }
1625 
1626 void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
1627                                          DIEStreamer &Streamer,
1628                                          CUOffsetMap &CUMap,
1629                                          const std::list<DWARFUnit *> &CUs,
1630                                          DebugAddrWriter &FinalAddrWriter) {
1631   for (DWARFUnit *CU : CUs) {
1632     auto AddressWriterIterator = AddressWritersByCU.find(CU->getOffset());
1633     assert(AddressWriterIterator != AddressWritersByCU.end() &&
1634            "AddressWriter does not exist for CU");
1635     DebugAddrWriter *AddressWriter = AddressWriterIterator->second.get();
1636     const size_t BufferOffset = FinalAddrWriter.getBufferSize();
1637     std::optional<uint64_t> Offset = AddressWriter->finalize(BufferOffset);
1638     /// If Offset already exists in UnmodifiedAddressOffsets, then update with
1639     /// Offset, else update with BufferOffset.
1640     if (Offset)
1641       AddressWriter->updateAddrBase(DIEBlder, *CU, *Offset);
1642     else if (AddressWriter->isInitialized())
1643       AddressWriter->updateAddrBase(DIEBlder, *CU, BufferOffset);
1644     if (AddressWriter->isInitialized()) {
1645       std::unique_ptr<AddressSectionBuffer> AddressSectionContents =
1646           AddressWriter->releaseBuffer();
1647       FinalAddrWriter.appendToAddressBuffer(*AddressSectionContents);
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(*DWOId);
1655     assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1656            "RangesWriter does not exist for DWOId");
1657     std::unique_ptr<DebugRangesSectionWriter> &LegacyRangesWriter =
1658         RangesWriterIterator->second;
1659     DIE *Die = LegacyRangesWriter->getDie();
1660     if (!Die)
1661       continue;
1662     DIEValue DvalGNUBase = Die->findAttribute(dwarf::DW_AT_GNU_ranges_base);
1663     assert(DvalGNUBase && "GNU_ranges_base attribute does not exist for DWOId");
1664     DIEBlder.replaceValue(
1665         Die, dwarf::DW_AT_GNU_ranges_base, DvalGNUBase.getForm(),
1666         DIEInteger(LegacyRangesSectionWriter->getSectionOffset()));
1667     std::unique_ptr<DebugBufferVector> RangesWritersContents =
1668         LegacyRangesWriter->releaseBuffer();
1669     LegacyRangesSectionWriter->appendToRangeBuffer(*RangesWritersContents);
1670   }
1671   DIEBlder.generateAbbrevs();
1672   DIEBlder.finish();
1673   DIEBlder.updateDebugNamesTable();
1674   // generate debug_info and CUMap
1675   for (DWARFUnit *CU : CUs) {
1676     emitUnit(DIEBlder, Streamer, *CU);
1677     const uint32_t StartOffset = CUOffset;
1678     DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);
1679     CUOffset += CU->getHeaderSize();
1680     CUOffset += UnitDIE->getSize();
1681     CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
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.
1689 namespace {
1690 
1691 std::unique_ptr<BinaryContext>
1692 createDwarfOnlyBC(const object::ObjectFile &File) {
1693   return cantFail(BinaryContext::createBinaryContext(
1694       File.makeTriple(), std::make_shared<orc::SymbolStringPool>(),
1695       File.getFileName(), nullptr, false,
1696       DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,
1697                            nullptr, "", WithColor::defaultErrorHandler,
1698                            WithColor::defaultWarningHandler),
1699       {llvm::outs(), llvm::errs()}));
1700 }
1701 
1702 StringMap<DWARFRewriter::KnownSectionsEntry>
1703 createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {
1704   StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {
1705       {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
1706       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
1707       {"debug_str_offsets.dwo",
1708        {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},
1709       {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},
1710       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
1711       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
1712       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
1713       {"debug_loclists.dwo",
1714        {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
1715       {"debug_rnglists.dwo",
1716        {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};
1717   return KnownSectionsTemp;
1718 }
1719 
1720 StringRef getSectionName(const SectionRef &Section) {
1721   Expected<StringRef> SectionName = Section.getName();
1722   assert(SectionName && "Invalid section name.");
1723   StringRef Name = *SectionName;
1724   Name = Name.substr(Name.find_first_not_of("._"));
1725   return Name;
1726 }
1727 
1728 // Exctracts an appropriate slice if input is DWP.
1729 // Applies patches or overwrites the section.
1730 std::optional<StringRef> updateDebugData(
1731     DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
1732     const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
1733     MCStreamer &Streamer, DWARFRewriter &Writer,
1734     const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
1735     std::unique_ptr<DebugBufferVector> &OutputBuffer,
1736     DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
1737     DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
1738     const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {
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(DWPOffset, DWOContrubution->getLength());
1749     }
1750     return OutData;
1751   };
1752 
1753   auto SectionIter = KnownSections.find(SectionName);
1754   if (SectionIter == KnownSections.end())
1755     return std::nullopt;
1756   Streamer.switchSection(SectionIter->second.first);
1757   uint64_t DWPOffset = 0;
1758 
1759   auto getOverridenSection =
1760       [&](DWARFSectionKind Kind) -> std::optional<StringRef> {
1761     auto Iter = OverridenSections.find(Kind);
1762     if (Iter == OverridenSections.end()) {
1763       errs()
1764           << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
1765              "section for: "
1766           << Twine::utohexstr(DWOId) << ".\n";
1767       return std::nullopt;
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 
1825 void DWARFRewriter::writeDWOFiles(
1826     DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
1827     const std::string &DWOName, DebugLocWriter &LocWriter,
1828     DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
1829     DebugRangesSectionWriter &TempRangesSectionWriter) {
1830   // Setup DWP code once.
1831   DWARFContext *DWOCtx = BC.getDWOContext();
1832   const uint64_t DWOId = *CU.getDWOId();
1833   const DWARFUnitIndex *CUIndex = nullptr;
1834   bool IsDWP = false;
1835   if (DWOCtx) {
1836     CUIndex = &DWOCtx->getCUIndex();
1837     IsDWP = !CUIndex->getRows().empty();
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(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(AbsolutePath, CompDir);
1857   sys::path::append(AbsolutePath, DWOName);
1858 
1859   std::error_code EC;
1860   std::unique_ptr<ToolOutputFile> TempOut =
1861       std::make_unique<ToolOutputFile>(AbsolutePath, EC, sys::fs::OF_None);
1862 
1863   const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
1864   if (IsDWP)
1865     CUDWOEntry = CUIndex->getFromHash(DWOId);
1866 
1867   const object::ObjectFile *File =
1868       (*DWOCU)->getContext().getDWARFObj().getFile();
1869   std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
1870   std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
1871   const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
1872   StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
1873 
1874   DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
1875   if (CU.getVersion() == 5) {
1876     RangeListssWriter =
1877         llvm::dyn_cast<DebugRangeListsSectionWriter>(&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((*DWOCU)->getContext(), "debug_rnglists.dwo", "",
1885                               KnownSections, *Streamer, *this, CUDWOEntry,
1886                               DWOId, OutputData, RangeListssWriter, LocWriter,
1887                               StrOffstsWriter, StrWriter, OverridenSections))
1888         Streamer->emitBytes(*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             (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
1901             *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
1902             LocWriter, StrOffstsWriter, StrWriter, OverridenSections))
1903       Streamer->emitBytes(*OutData);
1904   }
1905   Streamer->finish();
1906   TempOut->keep();
1907 }
1908 
1909 std::unique_ptr<DebugBufferVector>
1910 DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
1911   auto LocBuffer = std::make_unique<DebugBufferVector>();
1912   auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
1913   auto Writer =
1914       std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));
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>(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 
1942 void DWARFRewriter::convertToRangesPatchDebugInfo(
1943     DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
1944     uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
1945     DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {
1946   dwarf::Form LowForm = LowPCAttrInfo.getForm();
1947   dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
1948   dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;
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, 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(Unit.getOffset());
1967       assert(AddrWriterIterator != AddressWritersByCU.end() &&
1968              "AddressWriter does not exist for CU");
1969       DebugAddrWriter *AddrWriter = AddrWriterIterator->second.get();
1970       const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit);
1971       DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
1972                            LowPCAttrInfo.getForm(), DIEInteger(Index));
1973     } else {
1974       DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
1975                            LowPCAttrInfo.getForm(), DIEInteger(0));
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, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
1982                          DIEInteger(*RangesBase));
1983       } else {
1984         DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
1985                          DIEInteger(INT_MAX));
1986         auto RangesWriterIterator =
1987             LegacyRangesWritersByCU.find(*Unit.getDWOId());
1988         assert(RangesWriterIterator != LegacyRangesWritersByCU.end() &&
1989                "RangesWriter does not exist for DWOId");
1990         RangesWriterIterator->second->setDie(&Die);
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, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges,
1999                        RangesForm, DIEInteger(RangesSectionOffset));
2000 }
2001