1 //===- bolt/Rewrite/DWARFRewriter.cpp -------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "bolt/Rewrite/DWARFRewriter.h"
10 #include "bolt/Core/BinaryContext.h"
11 #include "bolt/Core/BinaryFunction.h"
12 #include "bolt/Core/DIEBuilder.h"
13 #include "bolt/Core/DebugData.h"
14 #include "bolt/Core/DynoStats.h"
15 #include "bolt/Core/ParallelUtilities.h"
16 #include "bolt/Rewrite/RewriteInstance.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/BinaryFormat/Dwarf.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/DIE.h"
23 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
24 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
27 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
28 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
29 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
30 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
31 #include "llvm/MC/MCAsmBackend.h"
32 #include "llvm/MC/MCAssembler.h"
33 #include "llvm/MC/MCObjectWriter.h"
34 #include "llvm/MC/MCStreamer.h"
35 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
36 #include "llvm/Object/ObjectFile.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Debug.h"
40 #include "llvm/Support/Endian.h"
41 #include "llvm/Support/Error.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/LEB128.h"
44 #include "llvm/Support/ThreadPool.h"
45 #include "llvm/Support/raw_ostream.h"
53 #include <unordered_map>
58 #define DEBUG_TYPE "bolt"
60 static mc::RegisterMCTargetOptionsFlags MOF
;
62 static void printDie(const DWARFDie
&DIE
) {
63 DIDumpOptions DumpOpts
;
64 DumpOpts
.ShowForm
= true;
65 DumpOpts
.Verbose
= true;
66 DumpOpts
.ChildRecurseDepth
= 0;
67 DumpOpts
.ShowChildren
= false;
68 DIE
.dump(dbgs(), 0, DumpOpts
);
71 /// Lazily parse DWARF DIE and print it out.
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
);
83 dbgs() << "Failed to extract abbreviation for"
84 << Twine::utohexstr(OriginalOffsets
) << "\n";
87 dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets
)
94 /// Take a set of DWARF address ranges corresponding to the input binary and
95 /// translate them to a set of address ranges in the output binary.
96 static DebugAddressRangesVector
97 translateInputToOutputRanges(const BinaryFunction
&BF
,
98 const DWARFAddressRangesVector
&InputRanges
) {
99 DebugAddressRangesVector OutputRanges
;
101 // If the function hasn't changed return the same ranges.
102 if (!BF
.isEmitted()) {
103 OutputRanges
.resize(InputRanges
.size());
104 llvm::transform(InputRanges
, OutputRanges
.begin(),
105 [](const DWARFAddressRange
&Range
) {
106 return DebugAddressRange(Range
.LowPC
, Range
.HighPC
);
111 for (const DWARFAddressRange
&Range
: InputRanges
)
112 llvm::append_range(OutputRanges
, BF
.translateInputToOutputRange(
113 {Range
.LowPC
, Range
.HighPC
}));
115 // Post-processing pass to sort and merge ranges.
116 llvm::sort(OutputRanges
);
117 DebugAddressRangesVector MergedRanges
;
118 uint64_t PrevHighPC
= 0;
119 for (const DebugAddressRange
&Range
: OutputRanges
) {
120 if (Range
.LowPC
<= PrevHighPC
) {
121 MergedRanges
.back().HighPC
=
122 std::max(MergedRanges
.back().HighPC
, Range
.HighPC
);
124 MergedRanges
.emplace_back(Range
.LowPC
, Range
.HighPC
);
126 PrevHighPC
= MergedRanges
.back().HighPC
;
132 /// Similar to translateInputToOutputRanges() but operates on location lists.
133 static DebugLocationsVector
134 translateInputToOutputLocationList(const BinaryFunction
&BF
,
135 const DebugLocationsVector
&InputLL
) {
136 DebugLocationsVector OutputLL
;
138 // If the function hasn't changed - there's nothing to update.
142 for (const DebugLocationEntry
&Entry
: InputLL
) {
143 DebugAddressRangesVector OutRanges
=
144 BF
.translateInputToOutputRange({Entry
.LowPC
, Entry
.HighPC
});
145 if (!OutRanges
.empty() && !OutputLL
.empty()) {
146 if (OutRanges
.front().LowPC
== OutputLL
.back().HighPC
&&
147 Entry
.Expr
== OutputLL
.back().Expr
) {
148 OutputLL
.back().HighPC
=
149 std::max(OutputLL
.back().HighPC
, OutRanges
.front().HighPC
);
150 OutRanges
.erase(OutRanges
.begin());
153 llvm::transform(OutRanges
, std::back_inserter(OutputLL
),
154 [&Entry
](const DebugAddressRange
&R
) {
155 return DebugLocationEntry
{R
.LowPC
, R
.HighPC
, Entry
.Expr
};
159 // Sort and merge adjacent entries with identical locations.
161 OutputLL
, [](const DebugLocationEntry
&A
, const DebugLocationEntry
&B
) {
162 return A
.LowPC
< B
.LowPC
;
164 DebugLocationsVector MergedLL
;
165 uint64_t PrevHighPC
= 0;
166 const SmallVectorImpl
<uint8_t> *PrevExpr
= nullptr;
167 for (const DebugLocationEntry
&Entry
: OutputLL
) {
168 if (Entry
.LowPC
<= PrevHighPC
&& *PrevExpr
== Entry
.Expr
) {
169 MergedLL
.back().HighPC
= std::max(Entry
.HighPC
, MergedLL
.back().HighPC
);
171 const uint64_t Begin
= std::max(Entry
.LowPC
, PrevHighPC
);
172 const uint64_t End
= std::max(Begin
, Entry
.HighPC
);
173 MergedLL
.emplace_back(DebugLocationEntry
{Begin
, End
, Entry
.Expr
});
175 PrevHighPC
= MergedLL
.back().HighPC
;
176 PrevExpr
= &MergedLL
.back().Expr
;
182 using namespace dwarf_linker
;
183 using namespace dwarf_linker::classic
;
187 /// Emits debug information into .debug_info or .debug_types section.
188 class DIEStreamer
: public DwarfStreamer
{
190 GDBIndex
&GDBIndexSection
;
193 /// Emit the compilation unit header for \p Unit in the debug_info
196 /// A Dwarf 4 section header is encoded as:
197 /// uint32_t Unit length (omitting this field)
199 /// uint32_t Abbreviation table offset
200 /// uint8_t Address size
201 /// Leading to a total of 11 bytes.
203 /// A Dwarf 5 section header is encoded as:
204 /// uint32_t Unit length (omitting this field)
206 /// uint8_t Unit type
207 /// uint8_t Address size
208 /// uint32_t Abbreviation table offset
209 /// Leading to a total of 12 bytes.
210 void emitCompileUnitHeader(DWARFUnit
&Unit
, DIE
&UnitDIE
,
211 unsigned DwarfVersion
) {
213 AsmPrinter
&Asm
= getAsmPrinter();
214 switchToDebugInfoSection(DwarfVersion
);
216 emitCommonHeader(Unit
, UnitDIE
, DwarfVersion
);
218 if (DwarfVersion
>= 5 &&
219 Unit
.getUnitType() != dwarf::UnitType::DW_UT_compile
) {
220 std::optional
<uint64_t> DWOId
= Unit
.getDWOId();
222 "DWOId does not exist and this is not a DW_UT_compile Unit");
223 Asm
.emitInt64(*DWOId
);
227 void emitCommonHeader(DWARFUnit
&Unit
, DIE
&UnitDIE
, uint16_t Version
) {
228 dwarf::UnitType UT
= dwarf::UnitType(Unit
.getUnitType());
229 llvm::AsmPrinter
&Asm
= getAsmPrinter();
231 // Emit size of content not including length itself
232 Asm
.emitInt32(Unit
.getHeaderSize() + UnitDIE
.getSize() - 4);
233 Asm
.emitInt16(Version
);
235 // DWARF v5 reorders the address size and adds a unit type.
238 Asm
.emitInt8(Asm
.MAI
->getCodePointerSize());
243 Asm
.emitInt8(Asm
.MAI
->getCodePointerSize());
247 void emitTypeUnitHeader(DWARFUnit
&Unit
, DIE
&UnitDIE
,
248 unsigned DwarfVersion
) {
249 AsmPrinter
&Asm
= getAsmPrinter();
250 const uint64_t TypeSignature
= cast
<DWARFTypeUnit
>(Unit
).getTypeHash();
251 DIE
*TypeDIE
= DIEBldr
->getTypeDIE(Unit
);
252 const DIEBuilder::DWARFUnitInfo
&UI
= DIEBldr
->getUnitInfoByDwarfUnit(Unit
);
253 GDBIndexSection
.addGDBTypeUnitEntry(
254 {UI
.UnitOffset
, TypeSignature
, TypeDIE
->getOffset()});
255 if (Unit
.getVersion() < 5) {
256 // Switch the section to .debug_types section.
257 std::unique_ptr
<MCStreamer
> &MS
= Asm
.OutStreamer
;
258 llvm::MCContext
&MC
= Asm
.OutContext
;
259 const llvm::MCObjectFileInfo
*MOFI
= MC
.getObjectFileInfo();
261 MS
->switchSection(MOFI
->getDwarfTypesSection(0));
262 MC
.setDwarfVersion(DwarfVersion
);
264 switchToDebugInfoSection(DwarfVersion
);
266 emitCommonHeader(Unit
, UnitDIE
, DwarfVersion
);
267 Asm
.OutStreamer
->emitIntValue(TypeSignature
, sizeof(TypeSignature
));
268 Asm
.emitDwarfLengthOrOffset(TypeDIE
? TypeDIE
->getOffset() : 0);
271 void emitUnitHeader(DWARFUnit
&Unit
, DIE
&UnitDIE
) {
272 if (Unit
.isTypeUnit())
273 emitTypeUnitHeader(Unit
, UnitDIE
, Unit
.getVersion());
275 emitCompileUnitHeader(Unit
, UnitDIE
, Unit
.getVersion());
278 void emitDIE(DIE
&Die
) override
{
279 AsmPrinter
&Asm
= getAsmPrinter();
280 Asm
.emitDwarfDIE(Die
);
284 DIEStreamer(DIEBuilder
*DIEBldr
, GDBIndex
&GDBIndexSection
,
285 DWARFLinkerBase::OutputFileType OutFileType
,
286 raw_pwrite_stream
&OutFile
,
287 DWARFLinkerBase::MessageHandlerTy Warning
)
288 : DwarfStreamer(OutFileType
, OutFile
, Warning
), DIEBldr(DIEBldr
),
289 GDBIndexSection(GDBIndexSection
) {};
291 using DwarfStreamer::emitCompileUnitHeader
;
293 void emitUnit(DWARFUnit
&Unit
, DIE
&UnitDIE
) {
294 emitUnitHeader(Unit
, UnitDIE
);
299 /// Finds attributes FormValue and Offset.
301 /// \param DIE die to look up in.
302 /// \param Attrs finds the first attribute that matches and extracts it.
303 /// \return an optional AttrInfo with DWARFFormValue and Offset.
304 std::optional
<AttrInfo
> findAttributeInfo(const DWARFDie DIE
,
305 std::vector
<dwarf::Attribute
> Attrs
) {
306 for (dwarf::Attribute
&Attr
: Attrs
)
307 if (std::optional
<AttrInfo
> Info
= findAttributeInfo(DIE
, Attr
))
315 using namespace llvm
;
316 using namespace llvm::support::endian
;
317 using namespace object
;
318 using namespace bolt
;
322 extern cl::OptionCategory BoltCategory
;
323 extern cl::opt
<unsigned> Verbosity
;
324 extern cl::opt
<std::string
> OutputFilename
;
326 static cl::opt
<bool> KeepARanges(
329 "keep or generate .debug_aranges section if .gdb_index is written"),
330 cl::Hidden
, cl::cat(BoltCategory
));
332 static cl::opt
<unsigned>
333 DebugThreadCount("debug-thread-count",
334 cl::desc("specifies thread count for the multithreading "
335 "for updating DWO debug info"),
336 cl::init(1), cl::cat(BoltCategory
));
338 static cl::opt
<std::string
> DwarfOutputPath(
340 cl::desc("Path to where .dwo files will be written out to."), cl::init(""),
341 cl::cat(BoltCategory
));
343 static cl::opt
<bool> CreateDebugNames(
344 "create-debug-names-section",
345 cl::desc("Creates .debug_names section, if the input binary doesn't have "
346 "it already, for DWARF5 CU/TUs."),
347 cl::init(false), cl::cat(BoltCategory
));
350 DebugSkeletonCu("debug-skeleton-cu",
351 cl::desc("prints out offsets for abbrev and debug_info of "
352 "Skeleton CUs that get patched."),
353 cl::ZeroOrMore
, cl::Hidden
, cl::init(false),
354 cl::cat(BoltCategory
));
356 static cl::opt
<unsigned> BatchSize(
357 "cu-processing-batch-size",
359 "Specifies the size of batches for processing CUs. Higher number has "
360 "better performance, but more memory usage. Default value is 1."),
361 cl::Hidden
, cl::init(1), cl::cat(BoltCategory
));
363 static cl::opt
<bool> AlwaysConvertToRanges(
364 "always-convert-to-ranges",
365 cl::desc("This option is for testing purposes only. It forces BOLT to "
366 "convert low_pc/high_pc to ranges always."),
367 cl::ReallyHidden
, cl::init(false), cl::cat(BoltCategory
));
369 extern cl::opt
<std::string
> CompDirOverride
;
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
);
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
||
385 uint32_t Index
= AddrOffset
? (LowPcValue
>> 32) : LowPcValue
;
386 std::optional
<object::SectionedAddress
> SA
=
387 DU
.getAddrOffsetSectionItem(Index
);
391 SA
->Address
+= (LowPcValue
& 0xffffffff);
394 SectionIndex
= SA
->SectionIndex
;
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
);
407 if (DvalHighPc
.getForm() == dwarf::DW_FORM_addr
)
408 HighPC
= DvalHighPc
.getDIEInteger().getValue();
410 HighPC
= LowPC
+ DvalHighPc
.getDIEInteger().getValue();
414 /// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
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
)) {
426 SectionIndex
= TempSectionIndex
;
432 static Expected
<llvm::DWARFAddressRangesVector
>
433 getDIEAddressRanges(const DIE
&Die
, DWARFUnit
&DU
) {
434 uint64_t LowPC
, HighPC
, Index
;
435 if (getLowAndHighPC(Die
, DU
, LowPC
, HighPC
, Index
))
436 return DWARFAddressRangesVector
{{LowPC
, HighPC
, Index
}};
437 if (DIEValue Dval
= Die
.findAttribute(dwarf::DW_AT_ranges
)) {
438 if (Dval
.getForm() == dwarf::DW_FORM_rnglistx
)
439 return DU
.findRnglistFromIndex(Dval
.getDIEInteger().getValue());
441 return DU
.findRnglistFromOffset(Dval
.getDIEInteger().getValue());
444 return DWARFAddressRangesVector();
447 static std::optional
<uint64_t> getAsAddress(const DWARFUnit
&DU
,
448 const DIEValue
&AttrVal
) {
449 DWARFFormValue::ValueType
Value(AttrVal
.getDIEInteger().getValue());
450 if (std::optional
<object::SectionedAddress
> SA
=
451 DWARFFormValue::getAsSectionedAddress(Value
, AttrVal
.getForm(), &DU
))
456 static std::unique_ptr
<DIEStreamer
>
457 createDIEStreamer(const Triple
&TheTriple
, raw_pwrite_stream
&OutFile
,
458 StringRef Swift5ReflectionSegmentName
, DIEBuilder
&DIEBldr
,
459 GDBIndex
&GDBIndexSection
) {
461 std::unique_ptr
<DIEStreamer
> Streamer
= std::make_unique
<DIEStreamer
>(
462 &DIEBldr
, GDBIndexSection
, DWARFLinkerBase::OutputFileType::Object
,
464 [&](const Twine
&Warning
, StringRef Context
, const DWARFDie
*) {});
465 Error Err
= Streamer
->init(TheTriple
, Swift5ReflectionSegmentName
);
468 << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
469 << toString(std::move(Err
)) << "\n";
473 static void emitUnit(DIEBuilder
&DIEBldr
, DIEStreamer
&Streamer
,
475 DIE
*UnitDIE
= DIEBldr
.getUnitDIEbyUnit(Unit
);
476 Streamer
.emitUnit(Unit
, *UnitDIE
);
479 static void emitDWOBuilder(const std::string
&DWOName
,
480 DIEBuilder
&DWODIEBuilder
, DWARFRewriter
&Rewriter
,
481 DWARFUnit
&SplitCU
, DWARFUnit
&CU
,
482 DebugLocWriter
&LocWriter
,
483 DebugStrOffsetsWriter
&StrOffstsWriter
,
484 DebugStrWriter
&StrWriter
, GDBIndex
&GDBIndexSection
,
485 DebugRangesSectionWriter
&TempRangesSectionWriter
) {
486 // Populate debug_info and debug_abbrev for current dwo into StringRef.
487 DWODIEBuilder
.generateAbbrevs();
488 DWODIEBuilder
.finish();
490 SmallVector
<char, 20> OutBuffer
;
491 std::shared_ptr
<raw_svector_ostream
> ObjOS
=
492 std::make_shared
<raw_svector_ostream
>(OutBuffer
);
493 const object::ObjectFile
*File
= SplitCU
.getContext().getDWARFObj().getFile();
494 auto TheTriple
= std::make_unique
<Triple
>(File
->makeTriple());
495 std::unique_ptr
<DIEStreamer
> Streamer
=
496 createDIEStreamer(*TheTriple
, *ObjOS
, "DwoStreamerInitAug2",
497 DWODIEBuilder
, GDBIndexSection
);
498 if (SplitCU
.getContext().getMaxDWOVersion() >= 5) {
499 for (std::unique_ptr
<llvm::DWARFUnit
> &CU
:
500 SplitCU
.getContext().dwo_info_section_units()) {
501 if (!CU
->isTypeUnit())
503 emitUnit(DWODIEBuilder
, *Streamer
, *CU
.get());
505 emitUnit(DWODIEBuilder
, *Streamer
, SplitCU
);
507 for (std::unique_ptr
<llvm::DWARFUnit
> &CU
:
508 SplitCU
.getContext().dwo_compile_units())
509 emitUnit(DWODIEBuilder
, *Streamer
, *CU
.get());
511 // emit debug_types sections for dwarf4
512 for (DWARFUnit
*CU
: DWODIEBuilder
.getDWARF4TUVector())
513 emitUnit(DWODIEBuilder
, *Streamer
, *CU
);
516 Streamer
->emitAbbrevs(DWODIEBuilder
.getAbbrevs(),
517 SplitCU
.getContext().getMaxVersion());
520 std::unique_ptr
<MemoryBuffer
> ObjectMemBuffer
=
521 MemoryBuffer::getMemBuffer(ObjOS
->str(), "in-memory object file", false);
522 std::unique_ptr
<object::ObjectFile
> Obj
= cantFail(
523 object::ObjectFile::createObjectFile(ObjectMemBuffer
->getMemBufferRef()),
524 "error creating in-memory object");
526 DWARFRewriter::OverriddenSectionsMap OverriddenSections
;
527 for (const SectionRef
&Secs
: Obj
->sections()) {
528 StringRef Contents
= cantFail(Secs
.getContents());
529 StringRef Name
= cantFail(Secs
.getName());
530 DWARFSectionKind Kind
=
531 StringSwitch
<DWARFSectionKind
>(Name
)
532 .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV
)
533 .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO
)
534 .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES
)
535 .Default(DWARFSectionKind::DW_SECT_EXT_unknown
);
536 if (Kind
== DWARFSectionKind::DW_SECT_EXT_unknown
)
538 OverriddenSections
[Kind
] = Contents
;
540 Rewriter
.writeDWOFiles(CU
, OverriddenSections
, DWOName
, LocWriter
,
541 StrOffstsWriter
, StrWriter
, TempRangesSectionWriter
);
544 using DWARFUnitVec
= std::vector
<DWARFUnit
*>;
545 using CUPartitionVector
= std::vector
<DWARFUnitVec
>;
546 /// Partitions CUs in to buckets. Bucket size is controlled by
547 /// cu-processing-batch-size. All the CUs that have cross CU reference reference
548 /// as a source are put in to the same initial bucket.
549 static CUPartitionVector
partitionCUs(DWARFContext
&DwCtx
) {
550 CUPartitionVector
Vec(2);
551 unsigned Counter
= 0;
552 const DWARFDebugAbbrev
*Abbr
= DwCtx
.getDebugAbbrev();
553 for (std::unique_ptr
<DWARFUnit
> &CU
: DwCtx
.compile_units()) {
554 Expected
<const DWARFAbbreviationDeclarationSet
*> AbbrDeclSet
=
555 Abbr
->getAbbreviationDeclarationSet(CU
->getAbbreviationsOffset());
557 consumeError(AbbrDeclSet
.takeError());
560 bool CrossCURefFound
= false;
561 for (const DWARFAbbreviationDeclaration
&Decl
: *AbbrDeclSet
.get()) {
562 for (const DWARFAbbreviationDeclaration::AttributeSpec
&Attr
:
564 if (Attr
.Form
== dwarf::DW_FORM_ref_addr
) {
565 CrossCURefFound
= true;
572 if (CrossCURefFound
) {
573 Vec
[0].push_back(CU
.get());
576 Vec
.back().push_back(CU
.get());
578 if (Counter
% opts::BatchSize
== 0 && !Vec
.back().empty())
584 void DWARFRewriter::updateDebugInfo() {
585 ErrorOr
<BinarySection
&> DebugInfo
= BC
.getUniqueSectionByName(".debug_info");
589 ARangesSectionWriter
= std::make_unique
<DebugARangesSectionWriter
>();
590 StrWriter
= std::make_unique
<DebugStrWriter
>(*BC
.DwCtx
, false);
591 StrOffstsWriter
= std::make_unique
<DebugStrOffsetsWriter
>(BC
);
593 /// Stores and serializes information that will be put into the
594 /// .debug_addr DWARF section.
595 std::unique_ptr
<DebugAddrWriter
> FinalAddrWriter
;
597 if (BC
.isDWARF5Used()) {
598 FinalAddrWriter
= std::make_unique
<DebugAddrWriterDwarf5
>(&BC
);
599 RangeListsSectionWriter
= std::make_unique
<DebugRangeListsSectionWriter
>();
601 FinalAddrWriter
= std::make_unique
<DebugAddrWriter
>(&BC
);
604 if (BC
.isDWARFLegacyUsed()) {
605 LegacyRangesSectionWriter
= std::make_unique
<DebugRangesSectionWriter
>();
606 LegacyRangesSectionWriter
->initSection();
609 uint32_t CUIndex
= 0;
610 std::mutex AccessMutex
;
611 // Needs to be invoked in the same order as CUs are processed.
612 llvm::DenseMap
<uint64_t, uint64_t> LocListWritersIndexByCU
;
613 auto createRangeLocListAddressWriters
= [&](DWARFUnit
&CU
) {
614 std::lock_guard
<std::mutex
> Lock(AccessMutex
);
615 const uint16_t DwarfVersion
= CU
.getVersion();
616 if (DwarfVersion
>= 5) {
617 auto AddrW
= std::make_unique
<DebugAddrWriterDwarf5
>(
618 &BC
, CU
.getAddressByteSize(), CU
.getAddrOffsetSectionBase());
619 RangeListsSectionWriter
->setAddressWriter(AddrW
.get());
620 LocListWritersByCU
[CUIndex
] =
621 std::make_unique
<DebugLoclistWriter
>(CU
, DwarfVersion
, false, *AddrW
);
623 if (std::optional
<uint64_t> DWOId
= CU
.getDWOId()) {
624 assert(RangeListsWritersByCU
.count(*DWOId
) == 0 &&
625 "RangeLists writer for DWO unit already exists.");
626 auto DWORangeListsSectionWriter
=
627 std::make_unique
<DebugRangeListsSectionWriter
>();
628 DWORangeListsSectionWriter
->initSection(CU
);
629 DWORangeListsSectionWriter
->setAddressWriter(AddrW
.get());
630 RangeListsWritersByCU
[*DWOId
] = std::move(DWORangeListsSectionWriter
);
632 AddressWritersByCU
[CU
.getOffset()] = std::move(AddrW
);
635 std::make_unique
<DebugAddrWriter
>(&BC
, CU
.getAddressByteSize());
636 AddressWritersByCU
[CU
.getOffset()] = std::move(AddrW
);
637 LocListWritersByCU
[CUIndex
] = std::make_unique
<DebugLocWriter
>();
638 if (std::optional
<uint64_t> DWOId
= CU
.getDWOId()) {
639 assert(LegacyRangesWritersByCU
.count(*DWOId
) == 0 &&
640 "LegacyRangeLists writer for DWO unit already exists.");
641 auto LegacyRangesSectionWriterByCU
=
642 std::make_unique
<DebugRangesSectionWriter
>();
643 LegacyRangesSectionWriterByCU
->initSection(CU
);
644 LegacyRangesWritersByCU
[*DWOId
] =
645 std::move(LegacyRangesSectionWriterByCU
);
648 LocListWritersIndexByCU
[CU
.getOffset()] = CUIndex
++;
651 DWARF5AcceleratorTable
DebugNamesTable(opts::CreateDebugNames
, BC
,
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,
668 updateUnitDebugInfo(SplitCU
, DWODIEBuilder
, DebugLocDWoWriter
,
669 TempRangesSectionWriter
, AddressWriter
);
670 DebugLocDWoWriter
.finalize(DWODIEBuilder
,
671 *DWODIEBuilder
.getUnitDIEbyUnit(SplitCU
));
672 if (Unit
.getVersion() >= 5)
673 TempRangesSectionWriter
.finalizeSection();
675 emitDWOBuilder(DWOName
, DWODIEBuilder
, *this, SplitCU
, Unit
,
676 DebugLocDWoWriter
, DWOStrOffstsWriter
, DWOStrWriter
,
677 GDBIndexSection
, TempRangesSectionWriter
);
679 auto processMainBinaryCU
= [&](DWARFUnit
&Unit
, DIEBuilder
&DIEBlder
) {
680 std::optional
<DWARFUnit
*> SplitCU
;
681 std::optional
<uint64_t> RangesBase
;
682 std::optional
<uint64_t> DWOId
= Unit
.getDWOId();
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
);
699 StrOffstsWriter
->finalizeSection(Unit
, DIEBlder
);
700 } else if (SplitCU
) {
701 RangesBase
= LegacyRangesSectionWriter
.get()->getSectionOffset();
704 updateUnitDebugInfo(Unit
, DIEBlder
, DebugLocWriter
, RangesSectionWriter
,
705 AddressWriter
, RangesBase
);
706 DebugLocWriter
.finalize(DIEBlder
, *DIEBlder
.getUnitDIEbyUnit(Unit
));
707 if (Unit
.getVersion() >= 5)
708 RangesSectionWriter
.finalizeSection();
711 DIEBuilder
DIEBlder(BC
, BC
.DwCtx
.get(), DebugNamesTable
);
712 DIEBlder
.buildTypeUnits(StrOffstsWriter
.get());
713 SmallVector
<char, 20> OutBuffer
;
714 std::unique_ptr
<raw_svector_ostream
> ObjOS
=
715 std::make_unique
<raw_svector_ostream
>(OutBuffer
);
716 const object::ObjectFile
*File
= BC
.DwCtx
->getDWARFObj().getFile();
717 auto TheTriple
= std::make_unique
<Triple
>(File
->makeTriple());
718 std::unique_ptr
<DIEStreamer
> Streamer
= createDIEStreamer(
719 *TheTriple
, *ObjOS
, "TypeStreamer", DIEBlder
, GDBIndexSection
);
720 CUOffsetMap OffsetMap
=
721 finalizeTypeSections(DIEBlder
, *Streamer
, GDBIndexSection
);
723 CUPartitionVector PartVec
= partitionCUs(*BC
.DwCtx
);
724 const unsigned int ThreadCount
=
725 std::min(opts::DebugThreadCount
, opts::ThreadCount
);
726 for (std::vector
<DWARFUnit
*> &Vec
: PartVec
) {
727 DIEBlder
.buildCompileUnits(Vec
);
728 llvm::SmallVector
<std::unique_ptr
<DIEBuilder
>, 72> DWODIEBuildersByCU
;
729 ThreadPoolInterface
&ThreadPool
=
730 ParallelUtilities::getThreadPool(ThreadCount
);
731 for (DWARFUnit
*CU
: DIEBlder
.getProcessedCUs()) {
732 createRangeLocListAddressWriters(*CU
);
733 std::optional
<DWARFUnit
*> SplitCU
;
734 std::optional
<uint64_t> DWOId
= CU
->getDWOId();
736 SplitCU
= BC
.getDWOCU(*DWOId
);
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()
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
761 ThreadPool
.async([&, DwarfOutputPath
, DWOName
, CU
, SplitCU
] {
762 processSplitCU(*CU
, **SplitCU
, TempRangesSectionWriter
, AddressWriter
,
763 DWOName
, DwarfOutputPath
, DWODIEBuilder
);
767 for (std::unique_ptr
<DIEBuilder
> &DWODIEBuilderPtr
: DWODIEBuildersByCU
)
768 DWODIEBuilderPtr
->updateDebugNamesTable();
769 for (DWARFUnit
*CU
: DIEBlder
.getProcessedCUs())
770 processMainBinaryCU(*CU
, DIEBlder
);
771 finalizeCompileUnits(DIEBlder
, *Streamer
, OffsetMap
,
772 DIEBlder
.getProcessedCUs(), *FinalAddrWriter
);
775 DebugNamesTable
.emitAccelTable();
777 finalizeDebugSections(DIEBlder
, DebugNamesTable
, *Streamer
, *ObjOS
, OffsetMap
,
779 GDBIndexSection
.updateGdbIndexSection(OffsetMap
, CUIndex
,
780 *ARangesSectionWriter
);
783 void DWARFRewriter::updateUnitDebugInfo(
784 DWARFUnit
&Unit
, DIEBuilder
&DIEBldr
, DebugLocWriter
&DebugLocWriter
,
785 DebugRangesSectionWriter
&RangesSectionWriter
,
786 DebugAddrWriter
&AddressWriter
, std::optional
<uint64_t> RangesBase
) {
787 // Cache debug ranges so that the offset for identical ranges could be reused.
788 std::map
<DebugAddressRangesVector
, uint64_t> CachedRanges
;
790 uint64_t DIEOffset
= Unit
.getOffset() + Unit
.getHeaderSize();
791 uint64_t NextCUOffset
= Unit
.getNextUnitOffset();
792 const std::vector
<std::unique_ptr
<DIEBuilder::DIEInfo
>> &DIs
=
793 DIEBldr
.getDIEsByUnit(Unit
);
795 // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
796 auto updateLowPCHighPC
= [&](DIE
*Die
, const DIEValue
&LowPCVal
,
797 const DIEValue
&HighPCVal
, uint64_t LowPC
,
798 const uint64_t HighPC
) {
799 dwarf::Attribute AttrLowPC
= dwarf::DW_AT_low_pc
;
800 dwarf::Form FormLowPC
= dwarf::DW_FORM_addr
;
801 dwarf::Attribute AttrHighPC
= dwarf::DW_AT_high_pc
;
802 dwarf::Form FormHighPC
= dwarf::DW_FORM_data4
;
803 const uint32_t Size
= HighPC
- LowPC
;
804 // Whatever was generated is not low_pc/high_pc, so will reset to
805 // default for size 1.
806 if (!LowPCVal
|| !HighPCVal
) {
807 if (Unit
.getVersion() >= 5)
808 FormLowPC
= dwarf::DW_FORM_addrx
;
809 else if (Unit
.isDWOUnit())
810 FormLowPC
= dwarf::DW_FORM_GNU_addr_index
;
812 AttrLowPC
= LowPCVal
.getAttribute();
813 FormLowPC
= LowPCVal
.getForm();
814 AttrHighPC
= HighPCVal
.getAttribute();
815 FormHighPC
= HighPCVal
.getForm();
818 if (FormLowPC
== dwarf::DW_FORM_addrx
||
819 FormLowPC
== dwarf::DW_FORM_GNU_addr_index
)
820 LowPC
= AddressWriter
.getIndexFromAddress(LowPC
, Unit
);
823 DIEBldr
.replaceValue(Die
, AttrLowPC
, FormLowPC
, DIEInteger(LowPC
));
825 DIEBldr
.addValue(Die
, AttrLowPC
, FormLowPC
, DIEInteger(LowPC
));
827 DIEBldr
.replaceValue(Die
, AttrHighPC
, FormHighPC
, DIEInteger(Size
));
829 DIEBldr
.deleteValue(Die
, dwarf::DW_AT_ranges
);
830 DIEBldr
.addValue(Die
, AttrHighPC
, FormHighPC
, DIEInteger(Size
));
834 for (const std::unique_ptr
<DIEBuilder::DIEInfo
> &DI
: DIs
) {
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())
847 auto ModuleRangesOrError
= getDIEAddressRanges(*Die
, Unit
);
848 if (!ModuleRangesOrError
) {
849 consumeError(ModuleRangesOrError
.takeError());
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
,
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
]));
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());
890 DWARFAddressRangesVector Ranges
= *RangesOrError
;
891 // Not a function definition.
895 for (const DWARFAddressRange
&Range
: Ranges
) {
896 if (const BinaryFunction
*Function
=
897 BC
.getBinaryFunctionAtAddress(Range
.LowPC
))
898 FunctionRanges
.append(Function
->getOutputAddressRanges());
901 if (const BinaryFunction
*Function
=
902 BC
.getBinaryFunctionAtAddress(Address
))
903 FunctionRanges
= Function
->getOutputAddressRanges();
906 // Clear cached ranges as the new function will have its own set.
907 CachedRanges
.clear();
908 DIEValue LowPCVal
= Die
->findAttribute(dwarf::DW_AT_low_pc
);
909 DIEValue HighPCVal
= Die
->findAttribute(dwarf::DW_AT_high_pc
);
910 if (FunctionRanges
.empty()) {
911 if (LowPCVal
&& HighPCVal
)
912 FunctionRanges
.push_back({0, HighPCVal
.getDIEInteger().getValue()});
914 FunctionRanges
.push_back({0, 1});
917 if (FunctionRanges
.size() == 1 && !opts::AlwaysConvertToRanges
) {
918 updateLowPCHighPC(Die
, LowPCVal
, HighPCVal
, FunctionRanges
.back().LowPC
,
919 FunctionRanges
.back().HighPC
);
923 updateDWARFObjectAddressRanges(
924 Unit
, DIEBldr
, *Die
, RangesSectionWriter
.addRanges(FunctionRanges
));
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
)
940 DebugAddressRangesVector OutputRanges
;
942 OutputRanges
= translateInputToOutputRanges(*Function
, *RangesOrError
);
943 LLVM_DEBUG(if (OutputRanges
.empty() != RangesOrError
->empty()) {
944 dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
945 << Twine::utohexstr(Die
->getOffset()) << " in CU at 0x"
946 << Twine::utohexstr(Unit
.getOffset()) << '\n';
948 if (opts::AlwaysConvertToRanges
|| OutputRanges
.size() > 1) {
949 RangesSectionOffset
= RangesSectionWriter
.addRanges(
950 std::move(OutputRanges
), CachedRanges
);
951 OutputRanges
.clear();
952 } else if (OutputRanges
.empty()) {
953 OutputRanges
.push_back({0, RangesOrError
.get().front().HighPC
});
955 } else if (!RangesOrError
) {
956 consumeError(RangesOrError
.takeError());
958 OutputRanges
.push_back({0, !RangesOrError
->empty()
959 ? RangesOrError
.get().front().HighPC
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
);
969 updateDWARFObjectAddressRanges(Unit
, DIEBldr
, *Die
, RangesSectionOffset
);
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
;
980 Function
->translateInputToOutputAddress(UpdatedAddress
);
982 if (AttrVal
.getForm() == dwarf::DW_FORM_addrx
) {
983 const uint32_t Index
=
984 AddressWriter
.getIndexFromAddress(UpdatedAddress
, Unit
);
985 DIEBldr
.replaceValue(Die
, AttrVal
.getAttribute(), AttrVal
.getForm(),
987 } else if (AttrVal
.getForm() == dwarf::DW_FORM_addr
) {
988 DIEBldr
.replaceValue(Die
, AttrVal
.getAttribute(), AttrVal
.getForm(),
989 DIEInteger(UpdatedAddress
));
991 errs() << "BOLT-ERROR: unsupported form for " << Entry
<< "\n";
994 DIEValue CallPcAttrVal
= Die
->findAttribute(dwarf::DW_AT_call_pc
);
996 patchPC(Die
, CallPcAttrVal
, "DW_AT_call_pc");
998 DIEValue CallRetPcAttrVal
=
999 Die
->findAttribute(dwarf::DW_AT_call_return_pc
);
1000 if (CallRetPcAttrVal
)
1001 patchPC(Die
, CallRetPcAttrVal
, "DW_AT_call_return_pc");
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
);
1010 if (doesFormBelongToClass(LocAttrInfo
.getForm(),
1011 DWARFFormValue::FC_Constant
,
1012 Unit
.getVersion()) ||
1013 doesFormBelongToClass(LocAttrInfo
.getForm(),
1014 DWARFFormValue::FC_SectionOffset
,
1015 Unit
.getVersion())) {
1016 uint64_t Offset
= LocAttrInfo
.getForm() == dwarf::DW_FORM_loclistx
1017 ? LocAttrInfo
.getDIELocList().getValue()
1018 : LocAttrInfo
.getDIEInteger().getValue();
1019 DebugLocationsVector InputLL
;
1021 std::optional
<object::SectionedAddress
> SectionAddress
=
1022 Unit
.getBaseAddress();
1023 uint64_t BaseAddress
= 0;
1025 BaseAddress
= SectionAddress
->Address
;
1027 if (Unit
.getVersion() >= 5 &&
1028 LocAttrInfo
.getForm() == dwarf::DW_FORM_loclistx
) {
1029 std::optional
<uint64_t> LocOffset
= Unit
.getLoclistOffset(Offset
);
1030 assert(LocOffset
&& "Location Offset is invalid.");
1031 Offset
= *LocOffset
;
1034 Error E
= Unit
.getLocationTable().visitLocationList(
1035 &Offset
, [&](const DWARFLocationEntry
&Entry
) {
1036 switch (Entry
.Kind
) {
1038 llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
1039 case dwarf::DW_LLE_end_of_list
:
1041 case dwarf::DW_LLE_base_address
: {
1042 assert(Entry
.SectionIndex
== SectionedAddress::UndefSection
&&
1043 "absolute address expected");
1044 BaseAddress
= Entry
.Value0
;
1047 case dwarf::DW_LLE_offset_pair
:
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
,
1056 case dwarf::DW_LLE_start_length
:
1057 InputLL
.emplace_back(DebugLocationEntry
{
1058 Entry
.Value0
, Entry
.Value0
+ Entry
.Value1
, Entry
.Loc
});
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
;
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
});
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
});
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())
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 "
1106 << Die
<< " in CU at 0x"
1107 << Twine::utohexstr(Unit
.getOffset()) << '\n';
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
1115 DebugLocWriter
.addList(DIEBldr
, *Die
, LocAttrInfo
, OutputLL
);
1118 assert((doesFormBelongToClass(LocAttrInfo
.getForm(),
1119 DWARFFormValue::FC_Exprloc
,
1120 Unit
.getVersion()) ||
1121 doesFormBelongToClass(LocAttrInfo
.getForm(),
1122 DWARFFormValue::FC_Block
,
1123 Unit
.getVersion())) &&
1124 "unexpected DW_AT_location form");
1125 if (Unit
.isDWOUnit() || Unit
.getVersion() >= 5) {
1126 std::vector
<uint8_t> Sblock
;
1127 DIEValueList
*AttrLocValList
;
1128 if (doesFormBelongToClass(LocAttrInfo
.getForm(),
1129 DWARFFormValue::FC_Exprloc
,
1130 Unit
.getVersion())) {
1131 for (const DIEValue
&Val
: LocAttrInfo
.getDIELoc().values()) {
1132 Sblock
.push_back(Val
.getDIEInteger().getValue());
1134 DIELoc
*LocAttr
= const_cast<DIELoc
*>(&LocAttrInfo
.getDIELoc());
1135 AttrLocValList
= static_cast<DIEValueList
*>(LocAttr
);
1137 for (const DIEValue
&Val
: LocAttrInfo
.getDIEBlock().values()) {
1138 Sblock
.push_back(Val
.getDIEInteger().getValue());
1140 DIEBlock
*BlockAttr
=
1141 const_cast<DIEBlock
*>(&LocAttrInfo
.getDIEBlock());
1142 AttrLocValList
= static_cast<DIEValueList
*>(BlockAttr
);
1144 ArrayRef
<uint8_t> Expr
= ArrayRef
<uint8_t>(Sblock
);
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
;
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
>();
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
>();
1166 Value
= DIEValue(LocAttrInfo
.getAttribute(),
1167 LocAttrInfo
.getForm(), Block
);
1169 errs() << "BOLT-WARNING: Unexpected Form value in Updating "
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
;
1191 DIEBldr
.addValue(NewAttr
, *Itr
);
1192 std::advance(Itr
, 1);
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.
1207 raw_svector_ostream
OSE(Tmp
);
1208 encodeULEB128(AddrIndex
, OSE
);
1210 DIEBldr
.addValue(NewAttr
, static_cast<dwarf::Attribute
>(0),
1211 dwarf::DW_FORM_data1
,
1212 DIEInteger(Expr
.getCode()));
1214 for (uint8_t Byte
: Tmp
) {
1215 DIEBldr
.addValue(NewAttr
, static_cast<dwarf::Attribute
>(0),
1216 dwarf::DW_FORM_data1
, DIEInteger(Byte
));
1220 PrevOffset
= CurEndOffset
;
1223 // update the size since the index might be changed
1225 Loc
->setSize(NewExprSize
);
1227 Block
->setSize(NewExprSize
);
1228 DIEBldr
.replaceValue(Die
, LocAttrInfo
.getAttribute(),
1229 LocAttrInfo
.getForm(), Value
);
1232 } else if (LowPCAttrInfo
) {
1233 uint64_t Address
= 0;
1234 uint64_t SectionIndex
= 0;
1235 if (getLowPC(*Die
, Unit
, Address
, SectionIndex
)) {
1236 uint64_t NewAddress
= 0;
1237 if (const BinaryFunction
*Function
=
1238 BC
.getBinaryFunctionContainingAddress(Address
)) {
1239 NewAddress
= Function
->translateInputToOutputAddress(Address
);
1241 << "BOLT-DEBUG: Fixing low_pc 0x"
1242 << Twine::utohexstr(Address
) << " for DIE with tag "
1243 << Die
->getTag() << " to 0x"
1244 << Twine::utohexstr(NewAddress
) << '\n');
1247 dwarf::Form Form
= LowPCAttrInfo
.getForm();
1248 assert(Form
!= dwarf::DW_FORM_LLVM_addrx_offset
&&
1249 "DW_FORM_LLVM_addrx_offset is not supported");
1250 std::lock_guard
<std::mutex
> Lock(DWARFRewriterMutex
);
1251 if (Form
== dwarf::DW_FORM_addrx
||
1252 Form
== dwarf::DW_FORM_GNU_addr_index
) {
1253 const uint32_t Index
= AddressWriter
.getIndexFromAddress(
1254 NewAddress
? NewAddress
: Address
, Unit
);
1255 DIEBldr
.replaceValue(Die
, LowPCAttrInfo
.getAttribute(),
1256 LowPCAttrInfo
.getForm(), DIEInteger(Index
));
1258 DIEBldr
.replaceValue(Die
, LowPCAttrInfo
.getAttribute(),
1259 LowPCAttrInfo
.getForm(),
1260 DIEInteger(NewAddress
));
1262 } else if (opts::Verbosity
>= 1) {
1263 errs() << "BOLT-WARNING: unexpected form value for attribute "
1270 if (DIEOffset
> NextCUOffset
)
1271 errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"
1272 << Twine::utohexstr(Unit
.getOffset()) << '\n';
1275 void DWARFRewriter::updateDWARFObjectAddressRanges(
1276 DWARFUnit
&Unit
, DIEBuilder
&DIEBldr
, DIE
&Die
, uint64_t DebugRangesOffset
,
1277 std::optional
<uint64_t> RangesBase
) {
1280 // If DW_AT_GNU_ranges_base is present, update it. No further modifications
1281 // are needed for ranges base.
1283 DIEValue RangesBaseInfo
= Die
.findAttribute(dwarf::DW_AT_GNU_ranges_base
);
1284 if (!RangesBaseInfo
) {
1285 RangesBaseInfo
= Die
.findAttribute(dwarf::DW_AT_rnglists_base
);
1288 if (RangesBaseInfo
) {
1289 if (RangesBaseInfo
.getAttribute() == dwarf::DW_AT_GNU_ranges_base
) {
1290 auto RangesWriterIterator
=
1291 LegacyRangesWritersByCU
.find(*Unit
.getDWOId());
1292 assert(RangesWriterIterator
!= LegacyRangesWritersByCU
.end() &&
1293 "RangesWriter does not exist for DWOId");
1294 RangesWriterIterator
->second
->setDie(&Die
);
1296 DIEBldr
.replaceValue(&Die
, RangesBaseInfo
.getAttribute(),
1297 RangesBaseInfo
.getForm(),
1298 DIEInteger(static_cast<uint32_t>(*RangesBase
)));
1300 RangesBase
= std::nullopt
;
1304 DIEValue LowPCAttrInfo
= Die
.findAttribute(dwarf::DW_AT_low_pc
);
1305 DIEValue RangesAttrInfo
= Die
.findAttribute(dwarf::DW_AT_ranges
);
1306 if (RangesAttrInfo
) {
1307 // Case 1: The object was already non-contiguous and had DW_AT_ranges.
1308 // In this case we simply need to update the value of DW_AT_ranges
1309 // and introduce DW_AT_GNU_ranges_base if required.
1310 // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
1311 bool NeedConverted
= false;
1313 if (Unit
.getVersion() >= 5 &&
1314 RangesAttrInfo
.getForm() == dwarf::DW_FORM_sec_offset
)
1315 NeedConverted
= true;
1317 if (NeedConverted
|| RangesAttrInfo
.getForm() == dwarf::DW_FORM_rnglistx
)
1318 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_ranges
, dwarf::DW_FORM_rnglistx
,
1319 DIEInteger(DebugRangesOffset
));
1321 DIEBldr
.replaceValue(&Die
, dwarf::DW_AT_ranges
, RangesAttrInfo
.getForm(),
1322 DIEInteger(DebugRangesOffset
));
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(),
1333 if (!(Die
.getTag() == dwarf::DW_TAG_compile_unit
||
1334 Die
.getTag() == dwarf::DW_TAG_skeleton_unit
))
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
));
1354 // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
1355 // to back. Replace with new attributes and patch the DIE.
1356 DIEValue HighPCAttrInfo
= Die
.findAttribute(dwarf::DW_AT_high_pc
);
1357 if (LowPCAttrInfo
&& HighPCAttrInfo
) {
1359 convertToRangesPatchDebugInfo(Unit
, DIEBldr
, Die
, DebugRangesOffset
,
1360 LowPCAttrInfo
, HighPCAttrInfo
, RangesBase
);
1361 } else if (!(Unit
.isDWOUnit() &&
1362 Die
.getTag() == dwarf::DW_TAG_compile_unit
)) {
1363 if (opts::Verbosity
>= 1)
1364 errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
1365 << Twine::utohexstr(Unit
.getOffset()) << '\n';
1369 void DWARFRewriter::updateLineTableOffsets(const MCAssembler
&Asm
) {
1370 ErrorOr
<BinarySection
&> DbgInfoSection
=
1371 BC
.getUniqueSectionByName(".debug_info");
1372 ErrorOr
<BinarySection
&> TypeInfoSection
=
1373 BC
.getUniqueSectionByName(".debug_types");
1374 assert(((BC
.DwCtx
->getNumTypeUnits() > 0 && TypeInfoSection
) ||
1375 BC
.DwCtx
->getNumTypeUnits() == 0) &&
1376 "Was not able to retrieve Debug Types section.");
1378 // There is no direct connection between CU and TU, but same offsets,
1379 // encoded in DW_AT_stmt_list, into .debug_line get modified.
1380 // We take advantage of that to map original CU line table offsets to new
1382 std::unordered_map
<uint64_t, uint64_t> DebugLineOffsetMap
;
1384 auto GetStatementListValue
=
1385 [](const DWARFDie
&DIE
) -> std::optional
<uint64_t> {
1386 std::optional
<DWARFFormValue
> StmtList
= DIE
.find(dwarf::DW_AT_stmt_list
);
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.");
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());
1400 const unsigned CUID
= CU
->getOffset();
1401 MCSymbol
*Label
= BC
.getDwarfLineTable(CUID
).getLabel();
1405 std::optional
<uint64_t> StmtOffset
=
1406 GetStatementListValue(CU
.get()->getUnitDIE());
1410 const uint64_t LineTableOffset
=
1411 Asm
.getSymbolOffset(*Label
);
1412 DebugLineOffsetMap
[*StmtOffset
] = LineTableOffset
;
1413 assert(DbgInfoSection
&& ".debug_info section must exist");
1414 LineTablePatchMap
[CU
.get()] = LineTableOffset
;
1417 for (const std::unique_ptr
<DWARFUnit
> &TU
: BC
.DwCtx
->types_section_units())
1418 TUs
.push_back(TU
.get());
1420 for (DWARFUnit
*TU
: TUs
) {
1421 std::optional
<uint64_t> StmtOffset
=
1422 GetStatementListValue(TU
->getUnitDIE());
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.
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 "
1438 TypeUnitRelocMap
[TU
] = Iter
->second
;
1441 // Set .debug_info as finalized so it won't be skipped over when
1442 // we process sections while writing out the new binary. This ensures
1443 // that the pending relocations will be processed and not ignored.
1445 DbgInfoSection
->setIsFinalized();
1447 if (TypeInfoSection
)
1448 TypeInfoSection
->setIsFinalized();
1451 CUOffsetMap
DWARFRewriter::finalizeTypeSections(DIEBuilder
&DIEBlder
,
1452 DIEStreamer
&Streamer
,
1453 GDBIndex
&GDBIndexSection
) {
1454 // update TypeUnit DW_AT_stmt_list with new .debug_line information.
1455 auto updateLineTable
= [&](const DWARFUnit
&Unit
) -> void {
1456 DIE
*UnitDIE
= DIEBlder
.getUnitDIEbyUnit(Unit
);
1457 DIEValue StmtAttrInfo
= UnitDIE
->findAttribute(dwarf::DW_AT_stmt_list
);
1458 if (!StmtAttrInfo
|| !TypeUnitRelocMap
.count(&Unit
))
1460 DIEBlder
.replaceValue(UnitDIE
, dwarf::DW_AT_stmt_list
,
1461 StmtAttrInfo
.getForm(),
1462 DIEInteger(TypeUnitRelocMap
[&Unit
]));
1465 // generate and populate abbrevs here
1466 DIEBlder
.generateAbbrevs();
1468 DIEBlder
.updateDebugNamesTable();
1469 SmallVector
<char, 20> OutBuffer
;
1470 std::shared_ptr
<raw_svector_ostream
> ObjOS
=
1471 std::make_shared
<raw_svector_ostream
>(OutBuffer
);
1472 const object::ObjectFile
*File
= BC
.DwCtx
->getDWARFObj().getFile();
1473 auto TheTriple
= std::make_unique
<Triple
>(File
->makeTriple());
1474 std::unique_ptr
<DIEStreamer
> TypeStreamer
= createDIEStreamer(
1475 *TheTriple
, *ObjOS
, "TypeStreamer", DIEBlder
, GDBIndexSection
);
1477 // generate debug_info and CUMap
1479 for (std::unique_ptr
<llvm::DWARFUnit
> &CU
: BC
.DwCtx
->info_section_units()) {
1480 if (!CU
->isTypeUnit())
1482 updateLineTable(*CU
.get());
1483 emitUnit(DIEBlder
, Streamer
, *CU
.get());
1484 uint32_t StartOffset
= CUOffset
;
1485 DIE
*UnitDIE
= DIEBlder
.getUnitDIEbyUnit(*CU
.get());
1486 CUOffset
+= CU
.get()->getHeaderSize();
1487 CUOffset
+= UnitDIE
->getSize();
1488 CUMap
[CU
.get()->getOffset()] = {StartOffset
, CUOffset
- StartOffset
- 4};
1491 // Emit Type Unit of DWARF 4 to .debug_type section
1492 for (DWARFUnit
*TU
: DIEBlder
.getDWARF4TUVector()) {
1493 updateLineTable(*TU
);
1494 emitUnit(DIEBlder
, *TypeStreamer
, *TU
);
1497 TypeStreamer
->finish();
1499 std::unique_ptr
<MemoryBuffer
> ObjectMemBuffer
=
1500 MemoryBuffer::getMemBuffer(ObjOS
->str(), "in-memory object file", false);
1501 std::unique_ptr
<object::ObjectFile
> Obj
= cantFail(
1502 object::ObjectFile::createObjectFile(ObjectMemBuffer
->getMemBufferRef()),
1503 "error creating in-memory object");
1505 for (const SectionRef
&Section
: Obj
->sections()) {
1506 StringRef Contents
= cantFail(Section
.getContents());
1507 StringRef Name
= cantFail(Section
.getName());
1508 if (Name
== ".debug_types")
1509 BC
.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents
),
1515 void DWARFRewriter::finalizeDebugSections(
1516 DIEBuilder
&DIEBlder
, DWARF5AcceleratorTable
&DebugNamesTable
,
1517 DIEStreamer
&Streamer
, raw_svector_ostream
&ObjOS
, CUOffsetMap
&CUMap
,
1518 DebugAddrWriter
&FinalAddrWriter
) {
1519 if (StrWriter
->isInitialized()) {
1520 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
1521 std::unique_ptr
<DebugStrBufferVector
> DebugStrSectionContents
=
1522 StrWriter
->releaseBuffer();
1523 BC
.registerOrUpdateNoteSection(".debug_str",
1524 copyByteArray(*DebugStrSectionContents
),
1525 DebugStrSectionContents
->size());
1528 if (StrOffstsWriter
->isFinalized()) {
1529 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");
1530 std::unique_ptr
<DebugStrOffsetsBufferVector
>
1531 DebugStrOffsetsSectionContents
= StrOffstsWriter
->releaseBuffer();
1532 BC
.registerOrUpdateNoteSection(
1533 ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents
),
1534 DebugStrOffsetsSectionContents
->size());
1537 if (BC
.isDWARFLegacyUsed()) {
1538 std::unique_ptr
<DebugBufferVector
> RangesSectionContents
=
1539 LegacyRangesSectionWriter
->releaseBuffer();
1540 BC
.registerOrUpdateNoteSection(".debug_ranges",
1541 copyByteArray(*RangesSectionContents
),
1542 RangesSectionContents
->size());
1545 if (BC
.isDWARF5Used()) {
1546 std::unique_ptr
<DebugBufferVector
> RangesSectionContents
=
1547 RangeListsSectionWriter
->releaseBuffer();
1548 BC
.registerOrUpdateNoteSection(".debug_rnglists",
1549 copyByteArray(*RangesSectionContents
),
1550 RangesSectionContents
->size());
1553 if (BC
.isDWARF5Used()) {
1554 std::unique_ptr
<DebugBufferVector
> LocationListSectionContents
=
1555 makeFinalLocListsSection(DWARFVersion::DWARF5
);
1556 if (!LocationListSectionContents
->empty())
1557 BC
.registerOrUpdateNoteSection(
1558 ".debug_loclists", copyByteArray(*LocationListSectionContents
),
1559 LocationListSectionContents
->size());
1562 if (BC
.isDWARFLegacyUsed()) {
1563 std::unique_ptr
<DebugBufferVector
> LocationListSectionContents
=
1564 makeFinalLocListsSection(DWARFVersion::DWARFLegacy
);
1565 if (!LocationListSectionContents
->empty())
1566 BC
.registerOrUpdateNoteSection(
1567 ".debug_loc", copyByteArray(*LocationListSectionContents
),
1568 LocationListSectionContents
->size());
1571 if (FinalAddrWriter
.isInitialized()) {
1572 std::unique_ptr
<AddressSectionBuffer
> AddressSectionContents
=
1573 FinalAddrWriter
.releaseBuffer();
1574 BC
.registerOrUpdateNoteSection(".debug_addr",
1575 copyByteArray(*AddressSectionContents
),
1576 AddressSectionContents
->size());
1579 Streamer
.emitAbbrevs(DIEBlder
.getAbbrevs(), BC
.DwCtx
->getMaxVersion());
1582 std::unique_ptr
<MemoryBuffer
> ObjectMemBuffer
=
1583 MemoryBuffer::getMemBuffer(ObjOS
.str(), "in-memory object file", false);
1584 std::unique_ptr
<object::ObjectFile
> Obj
= cantFail(
1585 object::ObjectFile::createObjectFile(ObjectMemBuffer
->getMemBufferRef()),
1586 "error creating in-memory object");
1588 for (const SectionRef
&Secs
: Obj
->sections()) {
1589 StringRef Contents
= cantFail(Secs
.getContents());
1590 StringRef Name
= cantFail(Secs
.getName());
1591 if (Name
== ".debug_abbrev") {
1592 BC
.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents
),
1594 } else if (Name
== ".debug_info") {
1595 BC
.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents
),
1600 // Skip .debug_aranges if we are re-generating .gdb_index.
1601 if (opts::KeepARanges
|| !BC
.getGdbIndexSection()) {
1602 SmallVector
<char, 16> ARangesBuffer
;
1603 raw_svector_ostream
OS(ARangesBuffer
);
1605 auto MAB
= std::unique_ptr
<MCAsmBackend
>(
1606 BC
.TheTarget
->createMCAsmBackend(*BC
.STI
, *BC
.MRI
, MCTargetOptions()));
1608 ARangesSectionWriter
->writeARangesSection(OS
, CUMap
);
1609 const StringRef
&ARangesContents
= OS
.str();
1611 BC
.registerOrUpdateNoteSection(".debug_aranges",
1612 copyByteArray(ARangesContents
),
1613 ARangesContents
.size());
1616 if (DebugNamesTable
.isCreated()) {
1617 RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");
1618 std::unique_ptr
<DebugBufferVector
> DebugNamesSectionContents
=
1619 DebugNamesTable
.releaseBuffer();
1620 BC
.registerOrUpdateNoteSection(".debug_names",
1621 copyByteArray(*DebugNamesSectionContents
),
1622 DebugNamesSectionContents
->size());
1626 void DWARFRewriter::finalizeCompileUnits(DIEBuilder
&DIEBlder
,
1627 DIEStreamer
&Streamer
,
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.
1641 AddressWriter
->updateAddrBase(DIEBlder
, *CU
, *Offset
);
1642 else if (AddressWriter
->isInitialized())
1643 AddressWriter
->updateAddrBase(DIEBlder
, *CU
, BufferOffset
);
1644 if (AddressWriter
->isInitialized()) {
1645 std::unique_ptr
<AddressSectionBuffer
> AddressSectionContents
=
1646 AddressWriter
->releaseBuffer();
1647 FinalAddrWriter
.appendToAddressBuffer(*AddressSectionContents
);
1649 if (CU
->getVersion() != 4)
1651 std::optional
<uint64_t> DWOId
= CU
->getDWOId();
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();
1662 DIEValue DvalGNUBase
= Die
->findAttribute(dwarf::DW_AT_GNU_ranges_base
);
1663 assert(DvalGNUBase
&& "GNU_ranges_base attribute does not exist for DWOId");
1664 DIEBlder
.replaceValue(
1665 Die
, dwarf::DW_AT_GNU_ranges_base
, DvalGNUBase
.getForm(),
1666 DIEInteger(LegacyRangesSectionWriter
->getSectionOffset()));
1667 std::unique_ptr
<DebugBufferVector
> RangesWritersContents
=
1668 LegacyRangesWriter
->releaseBuffer();
1669 LegacyRangesSectionWriter
->appendToRangeBuffer(*RangesWritersContents
);
1671 DIEBlder
.generateAbbrevs();
1673 DIEBlder
.updateDebugNamesTable();
1674 // generate debug_info and CUMap
1675 for (DWARFUnit
*CU
: CUs
) {
1676 emitUnit(DIEBlder
, Streamer
, *CU
);
1677 const uint32_t StartOffset
= CUOffset
;
1678 DIE
*UnitDIE
= DIEBlder
.getUnitDIEbyUnit(*CU
);
1679 CUOffset
+= CU
->getHeaderSize();
1680 CUOffset
+= UnitDIE
->getSize();
1681 CUMap
[CU
->getOffset()] = {StartOffset
, CUOffset
- StartOffset
- 4};
1685 // Creates all the data structures necessary for creating MCStreamer.
1686 // They are passed by reference because they need to be kept around.
1687 // Also creates known debug sections. These are sections handled by
1688 // handleDebugDataPatching.
1691 std::unique_ptr
<BinaryContext
>
1692 createDwarfOnlyBC(const object::ObjectFile
&File
) {
1693 return cantFail(BinaryContext::createBinaryContext(
1694 File
.makeTriple(), std::make_shared
<orc::SymbolStringPool
>(),
1695 File
.getFileName(), nullptr, false,
1696 DWARFContext::create(File
, DWARFContext::ProcessDebugRelocations::Ignore
,
1697 nullptr, "", WithColor::defaultErrorHandler
,
1698 WithColor::defaultWarningHandler
),
1699 {llvm::outs(), llvm::errs()}));
1702 StringMap
<DWARFRewriter::KnownSectionsEntry
>
1703 createKnownSectionsMap(const MCObjectFileInfo
&MCOFI
) {
1704 StringMap
<DWARFRewriter::KnownSectionsEntry
> KnownSectionsTemp
= {
1705 {"debug_info.dwo", {MCOFI
.getDwarfInfoDWOSection(), DW_SECT_INFO
}},
1706 {"debug_types.dwo", {MCOFI
.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES
}},
1707 {"debug_str_offsets.dwo",
1708 {MCOFI
.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS
}},
1709 {"debug_str.dwo", {MCOFI
.getDwarfStrDWOSection(), DW_SECT_EXT_unknown
}},
1710 {"debug_loc.dwo", {MCOFI
.getDwarfLocDWOSection(), DW_SECT_EXT_LOC
}},
1711 {"debug_abbrev.dwo", {MCOFI
.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV
}},
1712 {"debug_line.dwo", {MCOFI
.getDwarfLineDWOSection(), DW_SECT_LINE
}},
1713 {"debug_loclists.dwo",
1714 {MCOFI
.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS
}},
1715 {"debug_rnglists.dwo",
1716 {MCOFI
.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS
}}};
1717 return KnownSectionsTemp
;
1720 StringRef
getSectionName(const SectionRef
&Section
) {
1721 Expected
<StringRef
> SectionName
= Section
.getName();
1722 assert(SectionName
&& "Invalid section name.");
1723 StringRef Name
= *SectionName
;
1724 Name
= Name
.substr(Name
.find_first_not_of("._"));
1728 // Exctracts an appropriate slice if input is DWP.
1729 // Applies patches or overwrites the section.
1730 std::optional
<StringRef
> updateDebugData(
1731 DWARFContext
&DWCtx
, StringRef SectionName
, StringRef SectionContents
,
1732 const StringMap
<DWARFRewriter::KnownSectionsEntry
> &KnownSections
,
1733 MCStreamer
&Streamer
, DWARFRewriter
&Writer
,
1734 const DWARFUnitIndex::Entry
*CUDWOEntry
, uint64_t DWOId
,
1735 std::unique_ptr
<DebugBufferVector
> &OutputBuffer
,
1736 DebugRangeListsSectionWriter
*RangeListsWriter
, DebugLocWriter
&LocWriter
,
1737 DebugStrOffsetsWriter
&StrOffstsWriter
, DebugStrWriter
&StrWriter
,
1738 const llvm::bolt::DWARFRewriter::OverriddenSectionsMap
&OverridenSections
) {
1740 using DWOSectionContribution
=
1741 const DWARFUnitIndex::Entry::SectionContribution
;
1742 auto getSliceData
= [&](const DWARFUnitIndex::Entry
*DWOEntry
,
1743 StringRef OutData
, DWARFSectionKind Sec
,
1744 uint64_t &DWPOffset
) -> StringRef
{
1746 DWOSectionContribution
*DWOContrubution
= DWOEntry
->getContribution(Sec
);
1747 DWPOffset
= DWOContrubution
->getOffset();
1748 OutData
= OutData
.substr(DWPOffset
, DWOContrubution
->getLength());
1753 auto SectionIter
= KnownSections
.find(SectionName
);
1754 if (SectionIter
== KnownSections
.end())
1755 return std::nullopt
;
1756 Streamer
.switchSection(SectionIter
->second
.first
);
1757 uint64_t DWPOffset
= 0;
1759 auto getOverridenSection
=
1760 [&](DWARFSectionKind Kind
) -> std::optional
<StringRef
> {
1761 auto Iter
= OverridenSections
.find(Kind
);
1762 if (Iter
== OverridenSections
.end()) {
1764 << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
1766 << Twine::utohexstr(DWOId
) << ".\n";
1767 return std::nullopt
;
1769 return Iter
->second
;
1771 switch (SectionIter
->second
.second
) {
1773 if (SectionName
!= "debug_str.dwo")
1774 errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
1776 if (StrWriter
.isInitialized()) {
1777 OutputBuffer
= StrWriter
.releaseBuffer();
1778 return StringRef(reinterpret_cast<const char *>(OutputBuffer
->data()),
1779 OutputBuffer
->size());
1781 return SectionContents
;
1783 case DWARFSectionKind::DW_SECT_INFO
: {
1784 return getOverridenSection(DWARFSectionKind::DW_SECT_INFO
);
1786 case DWARFSectionKind::DW_SECT_EXT_TYPES
: {
1787 return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES
);
1789 case DWARFSectionKind::DW_SECT_STR_OFFSETS
: {
1790 if (StrOffstsWriter
.isFinalized()) {
1791 OutputBuffer
= StrOffstsWriter
.releaseBuffer();
1792 return StringRef(reinterpret_cast<const char *>(OutputBuffer
->data()),
1793 OutputBuffer
->size());
1795 return getSliceData(CUDWOEntry
, SectionContents
,
1796 DWARFSectionKind::DW_SECT_STR_OFFSETS
, DWPOffset
);
1798 case DWARFSectionKind::DW_SECT_ABBREV
: {
1799 return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV
);
1801 case DWARFSectionKind::DW_SECT_EXT_LOC
:
1802 case DWARFSectionKind::DW_SECT_LOCLISTS
: {
1803 OutputBuffer
= LocWriter
.getBuffer();
1804 // Creating explicit StringRef here, otherwise
1805 // with implicit conversion it will take null byte as end of
1807 return StringRef(reinterpret_cast<const char *>(OutputBuffer
->data()),
1808 OutputBuffer
->size());
1810 case DWARFSectionKind::DW_SECT_LINE
: {
1811 return getSliceData(CUDWOEntry
, SectionContents
,
1812 DWARFSectionKind::DW_SECT_LINE
, DWPOffset
);
1814 case DWARFSectionKind::DW_SECT_RNGLISTS
: {
1815 assert(RangeListsWriter
&& "RangeListsWriter was not created.");
1816 OutputBuffer
= RangeListsWriter
->releaseBuffer();
1817 return StringRef(reinterpret_cast<const char *>(OutputBuffer
->data()),
1818 OutputBuffer
->size());
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;
1836 CUIndex
= &DWOCtx
->getCUIndex();
1837 IsDWP
= !CUIndex
->getRows().empty();
1840 // Skipping CUs that we failed to load.
1841 std::optional
<DWARFUnit
*> DWOCU
= BC
.getDWOCU(DWOId
);
1843 errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "
1844 << Twine::utohexstr(DWOId
) << " is not found.\n";
1848 std::string CompDir
= CU
.getCompilationDir();
1850 if (!opts::DwarfOutputPath
.empty())
1851 CompDir
= opts::DwarfOutputPath
.c_str();
1852 else if (!opts::CompDirOverride
.empty())
1853 CompDir
= opts::CompDirOverride
;
1855 SmallString
<16> AbsolutePath
;
1856 sys::path::append(AbsolutePath
, CompDir
);
1857 sys::path::append(AbsolutePath
, DWOName
);
1860 std::unique_ptr
<ToolOutputFile
> TempOut
=
1861 std::make_unique
<ToolOutputFile
>(AbsolutePath
, EC
, sys::fs::OF_None
);
1863 const DWARFUnitIndex::Entry
*CUDWOEntry
= nullptr;
1865 CUDWOEntry
= CUIndex
->getFromHash(DWOId
);
1867 const object::ObjectFile
*File
=
1868 (*DWOCU
)->getContext().getDWARFObj().getFile();
1869 std::unique_ptr
<BinaryContext
> TmpBC
= createDwarfOnlyBC(*File
);
1870 std::unique_ptr
<MCStreamer
> Streamer
= TmpBC
->createStreamer(TempOut
->os());
1871 const MCObjectFileInfo
&MCOFI
= *Streamer
->getContext().getObjectFileInfo();
1872 StringMap
<KnownSectionsEntry
> KnownSections
= createKnownSectionsMap(MCOFI
);
1874 DebugRangeListsSectionWriter
*RangeListssWriter
= nullptr;
1875 if (CU
.getVersion() == 5) {
1877 llvm::dyn_cast
<DebugRangeListsSectionWriter
>(&TempRangesSectionWriter
);
1879 // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not
1880 // have .debug_rnglists so won't be part of the loop below.
1881 if (!RangeListssWriter
->empty()) {
1882 std::unique_ptr
<DebugBufferVector
> OutputData
;
1883 if (std::optional
<StringRef
> OutData
=
1884 updateDebugData((*DWOCU
)->getContext(), "debug_rnglists.dwo", "",
1885 KnownSections
, *Streamer
, *this, CUDWOEntry
,
1886 DWOId
, OutputData
, RangeListssWriter
, LocWriter
,
1887 StrOffstsWriter
, StrWriter
, OverridenSections
))
1888 Streamer
->emitBytes(*OutData
);
1892 for (const SectionRef
&Section
: File
->sections()) {
1893 std::unique_ptr
<DebugBufferVector
> OutputData
;
1894 StringRef SectionName
= getSectionName(Section
);
1895 if (SectionName
== "debug_rnglists.dwo")
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
);
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
);
1914 std::unique_ptr
<MCObjectWriter
>(BC
.createObjectWriter(*LocStream
));
1916 for (std::pair
<const uint64_t, std::unique_ptr
<DebugLocWriter
>> &Loc
:
1917 LocListWritersByCU
) {
1918 DebugLocWriter
*LocWriter
= Loc
.second
.get();
1919 auto *LocListWriter
= llvm::dyn_cast
<DebugLoclistWriter
>(LocWriter
);
1921 // Filter out DWARF4, writing out DWARF5
1922 if (Version
== DWARFVersion::DWARF5
&&
1923 (!LocListWriter
|| LocListWriter
->getDwarfVersion() <= 4))
1926 // Filter out DWARF5, writing out DWARF4
1927 if (Version
== DWARFVersion::DWARFLegacy
&&
1928 (LocListWriter
&& LocListWriter
->getDwarfVersion() >= 5))
1931 // Skipping DWARF4/5 split dwarf.
1932 if (LocListWriter
&& LocListWriter
->getDwarfVersion() <= 4)
1934 std::unique_ptr
<DebugBufferVector
> CurrCULocationLists
=
1935 LocWriter
->getBuffer();
1936 *LocStream
<< *CurrCULocationLists
;
1942 void DWARFRewriter::convertToRangesPatchDebugInfo(
1943 DWARFUnit
&Unit
, DIEBuilder
&DIEBldr
, DIE
&Die
,
1944 uint64_t RangesSectionOffset
, DIEValue
&LowPCAttrInfo
,
1945 DIEValue
&HighPCAttrInfo
, std::optional
<uint64_t> RangesBase
) {
1946 dwarf::Form LowForm
= LowPCAttrInfo
.getForm();
1947 dwarf::Attribute RangeBaseAttribute
= dwarf::DW_AT_GNU_ranges_base
;
1948 dwarf::Form RangesForm
= dwarf::DW_FORM_sec_offset
;
1950 if (Unit
.getVersion() >= 5) {
1951 RangeBaseAttribute
= dwarf::DW_AT_rnglists_base
;
1952 RangesForm
= dwarf::DW_FORM_rnglistx
;
1953 } else if (Unit
.getVersion() < 4) {
1954 RangesForm
= dwarf::DW_FORM_data4
;
1956 bool IsUnitDie
= Die
.getTag() == dwarf::DW_TAG_compile_unit
||
1957 Die
.getTag() == dwarf::DW_TAG_skeleton_unit
;
1959 DIEBldr
.deleteValue(&Die
, LowPCAttrInfo
.getAttribute());
1961 // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
1962 // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
1963 // when it's absent.
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
));
1974 DIEBldr
.replaceValue(&Die
, LowPCAttrInfo
.getAttribute(),
1975 LowPCAttrInfo
.getForm(), DIEInteger(0));
1977 // Original CU didn't have DW_AT_*_base. We converted it's children (or
1978 // dwo), so need to insert it into CU.
1980 if (Unit
.getVersion() >= 5) {
1981 DIEBldr
.addValue(&Die
, RangeBaseAttribute
, dwarf::DW_FORM_sec_offset
,
1982 DIEInteger(*RangesBase
));
1984 DIEBldr
.addValue(&Die
, RangeBaseAttribute
, dwarf::DW_FORM_sec_offset
,
1985 DIEInteger(INT_MAX
));
1986 auto RangesWriterIterator
=
1987 LegacyRangesWritersByCU
.find(*Unit
.getDWOId());
1988 assert(RangesWriterIterator
!= LegacyRangesWritersByCU
.end() &&
1989 "RangesWriter does not exist for DWOId");
1990 RangesWriterIterator
->second
->setDie(&Die
);
1995 // HighPC was conveted into DW_AT_ranges.
1996 // For DWARF5 we only access ranges through index.
1998 DIEBldr
.replaceValue(&Die
, HighPCAttrInfo
.getAttribute(), dwarf::DW_AT_ranges
,
1999 RangesForm
, DIEInteger(RangesSectionOffset
));