1 //===- bolt/Core/DIEBuilder.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/Core/DIEBuilder.h"
10 #include "bolt/Core/BinaryContext.h"
11 #include "bolt/Core/ParallelUtilities.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/CodeGen/DIE.h"
15 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
17 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
18 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
19 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
20 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
21 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/LEB128.h"
33 #include <unordered_map>
38 #define DEBUG_TYPE "bolt"
40 extern cl::opt
<unsigned> Verbosity
;
45 /// Returns DWO Name to be used to update DW_AT_dwo_name/DW_AT_GNU_dwo_name
46 /// either in CU or TU unit die. Handles case where user specifies output DWO
47 /// directory, and there are duplicate names. Assumes DWO ID is unique.
49 getDWOName(llvm::DWARFUnit
&CU
,
50 std::unordered_map
<std::string
, uint32_t> &NameToIndexMap
,
51 std::optional
<StringRef
> &DwarfOutputPath
) {
52 assert(CU
.getDWOId() && "DWO ID not found.");
53 std::string DWOName
= dwarf::toString(
54 CU
.getUnitDIE().find({dwarf::DW_AT_dwo_name
, dwarf::DW_AT_GNU_dwo_name
}),
56 assert(!DWOName
.empty() &&
57 "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exist.");
58 if (DwarfOutputPath
) {
59 DWOName
= std::string(sys::path::filename(DWOName
));
60 uint32_t &Index
= NameToIndexMap
[DWOName
];
61 DWOName
.append(std::to_string(Index
));
64 DWOName
.append(".dwo");
68 /// Adds a \p Str to .debug_str section.
69 /// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using
70 /// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets
71 /// for this contribution of \p Unit.
72 static void addStringHelper(DebugStrOffsetsWriter
&StrOffstsWriter
,
73 DebugStrWriter
&StrWriter
, DIEBuilder
&DIEBldr
,
74 DIE
&Die
, const DWARFUnit
&Unit
,
75 DIEValue
&DIEAttrInfo
, StringRef Str
) {
76 uint32_t NewOffset
= StrWriter
.addString(Str
);
77 if (Unit
.getVersion() >= 5) {
78 StrOffstsWriter
.updateAddressMap(DIEAttrInfo
.getDIEInteger().getValue(),
82 DIEBldr
.replaceValue(&Die
, DIEAttrInfo
.getAttribute(), DIEAttrInfo
.getForm(),
83 DIEInteger(NewOffset
));
86 std::string
DIEBuilder::updateDWONameCompDir(
87 DebugStrOffsetsWriter
&StrOffstsWriter
, DebugStrWriter
&StrWriter
,
88 DWARFUnit
&SkeletonCU
, std::optional
<StringRef
> DwarfOutputPath
,
89 std::optional
<StringRef
> DWONameToUse
) {
90 DIE
&UnitDIE
= *getUnitDIEbyUnit(SkeletonCU
);
91 DIEValue DWONameAttrInfo
= UnitDIE
.findAttribute(dwarf::DW_AT_dwo_name
);
93 DWONameAttrInfo
= UnitDIE
.findAttribute(dwarf::DW_AT_GNU_dwo_name
);
96 std::string ObjectName
;
98 ObjectName
= *DWONameToUse
;
100 ObjectName
= getDWOName(SkeletonCU
, NameToIndexMap
, DwarfOutputPath
);
101 addStringHelper(StrOffstsWriter
, StrWriter
, *this, UnitDIE
, SkeletonCU
,
102 DWONameAttrInfo
, ObjectName
);
104 DIEValue CompDirAttrInfo
= UnitDIE
.findAttribute(dwarf::DW_AT_comp_dir
);
105 assert(CompDirAttrInfo
&& "DW_AT_comp_dir is not in Skeleton CU.");
107 if (DwarfOutputPath
) {
108 if (!sys::fs::exists(*DwarfOutputPath
))
109 sys::fs::create_directory(*DwarfOutputPath
);
110 addStringHelper(StrOffstsWriter
, StrWriter
, *this, UnitDIE
, SkeletonCU
,
111 CompDirAttrInfo
, *DwarfOutputPath
);
116 void DIEBuilder::updateDWONameCompDirForTypes(
117 DebugStrOffsetsWriter
&StrOffstsWriter
, DebugStrWriter
&StrWriter
,
118 DWARFUnit
&Unit
, std::optional
<StringRef
> DwarfOutputPath
,
119 const StringRef DWOName
) {
120 for (DWARFUnit
*DU
: getState().DWARF5TUVector
)
121 updateDWONameCompDir(StrOffstsWriter
, StrWriter
, *DU
, DwarfOutputPath
,
123 if (StrOffstsWriter
.isStrOffsetsSectionModified())
124 StrOffstsWriter
.finalizeSection(Unit
, *this);
127 void DIEBuilder::updateReferences() {
128 for (auto &[SrcDIEInfo
, ReferenceInfo
] : getState().AddrReferences
) {
129 DIEInfo
*DstDIEInfo
= ReferenceInfo
.Dst
;
130 DWARFUnitInfo
&DstUnitInfo
= getUnitInfo(DstDIEInfo
->UnitId
);
131 dwarf::Attribute Attr
= ReferenceInfo
.AttrSpec
.Attr
;
132 dwarf::Form Form
= ReferenceInfo
.AttrSpec
.Form
;
134 const uint64_t NewAddr
=
135 DstDIEInfo
->Die
->getOffset() + DstUnitInfo
.UnitOffset
;
136 SrcDIEInfo
->Die
->replaceValue(getState().DIEAlloc
, Attr
, Form
,
137 DIEInteger(NewAddr
));
140 // Handling referenes in location expressions.
141 for (LocWithReference
&LocExpr
: getState().LocWithReferencesToProcess
) {
142 SmallVector
<uint8_t, 32> Buffer
;
143 DataExtractor
Data(StringRef((const char *)LocExpr
.BlockData
.data(),
144 LocExpr
.BlockData
.size()),
145 LocExpr
.U
.isLittleEndian(),
146 LocExpr
.U
.getAddressByteSize());
147 DWARFExpression
Expr(Data
, LocExpr
.U
.getAddressByteSize(),
148 LocExpr
.U
.getFormParams().Format
);
149 cloneExpression(Data
, Expr
, LocExpr
.U
, Buffer
, CloneExpressionStage::PATCH
);
151 DIEValueList
*AttrVal
;
152 if (LocExpr
.Form
== dwarf::DW_FORM_exprloc
) {
153 DIELoc
*DL
= new (getState().DIEAlloc
) DIELoc
;
154 DL
->setSize(Buffer
.size());
155 AttrVal
= static_cast<DIEValueList
*>(DL
);
157 DIEBlock
*DBL
= new (getState().DIEAlloc
) DIEBlock
;
158 DBL
->setSize(Buffer
.size());
159 AttrVal
= static_cast<DIEValueList
*>(DBL
);
161 for (auto Byte
: Buffer
)
162 AttrVal
->addValue(getState().DIEAlloc
, static_cast<dwarf::Attribute
>(0),
163 dwarf::DW_FORM_data1
, DIEInteger(Byte
));
166 if (LocExpr
.Form
== dwarf::DW_FORM_exprloc
)
168 DIEValue(dwarf::Attribute(LocExpr
.Attr
), dwarf::Form(LocExpr
.Form
),
169 static_cast<DIELoc
*>(AttrVal
));
172 DIEValue(dwarf::Attribute(LocExpr
.Attr
), dwarf::Form(LocExpr
.Form
),
173 static_cast<DIEBlock
*>(AttrVal
));
175 LocExpr
.Die
.replaceValue(getState().DIEAlloc
, LocExpr
.Attr
, LocExpr
.Form
,
182 uint32_t DIEBuilder::allocDIE(const DWARFUnit
&DU
, const DWARFDie
&DDie
,
183 BumpPtrAllocator
&Alloc
, const uint32_t UId
) {
184 DWARFUnitInfo
&DWARFUnitInfo
= getUnitInfo(UId
);
185 const uint64_t DDieOffset
= DDie
.getOffset();
186 if (DWARFUnitInfo
.DIEIDMap
.count(DDieOffset
))
187 return DWARFUnitInfo
.DIEIDMap
[DDieOffset
];
189 DIE
*Die
= DIE::get(Alloc
, dwarf::Tag(DDie
.getTag()));
190 // This handles the case where there is a DIE ref which points to
191 // invalid DIE. This prevents assert when IR is written out.
192 // Also it makes debugging easier.
193 // DIE dump is not very useful.
194 // It's nice to know original offset from which this DIE was constructed.
195 Die
->setOffset(DDie
.getOffset());
196 if (opts::Verbosity
>= 1)
197 getState().DWARFDieAddressesParsed
.insert(DDie
.getOffset());
198 const uint32_t DId
= DWARFUnitInfo
.DieInfoVector
.size();
199 DWARFUnitInfo
.DIEIDMap
[DDieOffset
] = DId
;
200 DWARFUnitInfo
.DieInfoVector
.emplace_back(
201 std::make_unique
<DIEInfo
>(DIEInfo
{Die
, DId
, UId
}));
205 void DIEBuilder::constructFromUnit(DWARFUnit
&DU
) {
206 std::optional
<uint32_t> UnitId
= getUnitId(DU
);
208 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
209 << "Skip Unit at " << Twine::utohexstr(DU
.getOffset()) << "\n";
213 const uint32_t UnitHeaderSize
= DU
.getHeaderSize();
214 uint64_t DIEOffset
= DU
.getOffset() + UnitHeaderSize
;
215 uint64_t NextCUOffset
= DU
.getNextUnitOffset();
216 DWARFDataExtractor DebugInfoData
= DU
.getDebugInfoExtractor();
217 DWARFDebugInfoEntry DIEEntry
;
218 std::vector
<DIE
*> CurParentDIEStack
;
219 std::vector
<uint32_t> Parents
;
220 uint32_t TUTypeOffset
= 0;
222 if (DWARFTypeUnit
*TU
= dyn_cast_or_null
<DWARFTypeUnit
>(&DU
))
223 TUTypeOffset
= TU
->getTypeOffset();
225 assert(DebugInfoData
.isValidOffset(NextCUOffset
- 1));
226 Parents
.push_back(UINT32_MAX
);
228 const bool IsTypeDIE
= (TUTypeOffset
== DIEOffset
- DU
.getOffset());
229 if (!DIEEntry
.extractFast(DU
, &DIEOffset
, DebugInfoData
, NextCUOffset
,
233 if (const DWARFAbbreviationDeclaration
*AbbrDecl
=
234 DIEEntry
.getAbbreviationDeclarationPtr()) {
235 DWARFDie
DDie(&DU
, &DIEEntry
);
237 DIE
*CurDIE
= constructDIEFast(DDie
, DU
, *UnitId
);
238 DWARFUnitInfo
&UI
= getUnitInfo(*UnitId
);
239 // Can't rely on first element in DieVector due to cross CU forward
244 getState().TypeDIEMap
[&DU
] = CurDIE
;
246 if (!CurParentDIEStack
.empty())
247 CurParentDIEStack
.back()->addChild(CurDIE
);
249 if (AbbrDecl
->hasChildren())
250 CurParentDIEStack
.push_back(CurDIE
);
252 // NULL DIE: finishes current children scope.
253 CurParentDIEStack
.pop_back();
255 } while (CurParentDIEStack
.size() > 0);
257 getState().CloneUnitCtxMap
[*UnitId
].IsConstructed
= true;
260 DIEBuilder::DIEBuilder(BinaryContext
&BC
, DWARFContext
*DwarfContext
,
261 DWARF5AcceleratorTable
&DebugNamesTable
,
262 DWARFUnit
*SkeletonCU
)
263 : BC(BC
), DwarfContext(DwarfContext
), SkeletonCU(SkeletonCU
),
264 DebugNamesTable(DebugNamesTable
) {}
266 static unsigned int getCUNum(DWARFContext
*DwarfContext
, bool IsDWO
) {
267 unsigned int CUNum
= IsDWO
? DwarfContext
->getNumDWOCompileUnits()
268 : DwarfContext
->getNumCompileUnits();
269 CUNum
+= IsDWO
? DwarfContext
->getNumDWOTypeUnits()
270 : DwarfContext
->getNumTypeUnits();
274 void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter
*StrOffsetWriter
,
277 BuilderState
.reset(new State());
279 const DWARFUnitIndex
&TUIndex
= DwarfContext
->getTUIndex();
280 if (!TUIndex
.getRows().empty()) {
281 for (auto &Row
: TUIndex
.getRows()) {
282 uint64_t Signature
= Row
.getSignature();
283 // manually populate TypeUnit to UnitVector
284 DwarfContext
->getTypeUnitForHash(Signature
, true);
287 const unsigned int CUNum
= getCUNum(DwarfContext
, isDWO());
288 getState().CloneUnitCtxMap
.resize(CUNum
);
289 DWARFContext::unit_iterator_range CU4TURanges
=
290 isDWO() ? DwarfContext
->dwo_types_section_units()
291 : DwarfContext
->types_section_units();
293 getState().Type
= ProcessingType::DWARF4TUs
;
294 for (std::unique_ptr
<DWARFUnit
> &DU
: CU4TURanges
)
295 registerUnit(*DU
.get(), false);
297 for (std::unique_ptr
<DWARFUnit
> &DU
: CU4TURanges
)
298 constructFromUnit(*DU
.get());
300 DWARFContext::unit_iterator_range CURanges
=
301 isDWO() ? DwarfContext
->dwo_info_section_units()
302 : DwarfContext
->info_section_units();
304 // This handles DWARF4 CUs and DWARF5 CU/TUs.
305 // Creating a vector so that for reference handling only DWARF5 CU/TUs are
306 // used, and not DWARF4 TUs.
307 getState().Type
= ProcessingType::DWARF5TUs
;
308 for (std::unique_ptr
<DWARFUnit
> &DU
: CURanges
) {
309 if (!DU
->isTypeUnit())
311 registerUnit(*DU
.get(), false);
314 for (DWARFUnit
*DU
: getState().DWARF5TUVector
) {
315 constructFromUnit(*DU
);
317 StrOffsetWriter
->finalizeSection(*DU
, *this);
321 void DIEBuilder::buildCompileUnits(const bool Init
) {
323 BuilderState
.reset(new State());
325 unsigned int CUNum
= getCUNum(DwarfContext
, isDWO());
326 getState().CloneUnitCtxMap
.resize(CUNum
);
327 DWARFContext::unit_iterator_range CURanges
=
328 isDWO() ? DwarfContext
->dwo_info_section_units()
329 : DwarfContext
->info_section_units();
331 // This handles DWARF4 CUs and DWARF5 CU/TUs.
332 // Creating a vector so that for reference handling only DWARF5 CU/TUs are
333 // used, and not DWARF4 TUs.getState().DUList
334 getState().Type
= ProcessingType::CUs
;
335 for (std::unique_ptr
<DWARFUnit
> &DU
: CURanges
) {
336 if (DU
->isTypeUnit())
338 registerUnit(*DU
.get(), false);
341 // Using DULIst since it can be modified by cross CU refrence resolution.
342 for (DWARFUnit
*DU
: getState().DUList
) {
343 if (DU
->isTypeUnit())
345 constructFromUnit(*DU
);
348 void DIEBuilder::buildCompileUnits(const std::vector
<DWARFUnit
*> &CUs
) {
349 BuilderState
.reset(new State());
350 // Allocating enough for current batch being processed.
351 // In real use cases we either processing a batch of CUs with no cross
352 // references, or if they do have them it is due to LTO. With clang they will
353 // share the same abbrev table. In either case this vector will not grow.
354 getState().CloneUnitCtxMap
.resize(CUs
.size());
355 getState().Type
= ProcessingType::CUs
;
356 for (DWARFUnit
*CU
: CUs
)
357 registerUnit(*CU
, false);
359 for (DWARFUnit
*DU
: getState().DUList
)
360 constructFromUnit(*DU
);
363 void DIEBuilder::buildDWOUnit(DWARFUnit
&U
) {
364 BuilderState
.release();
365 BuilderState
= std::make_unique
<State
>();
366 buildTypeUnits(nullptr, false);
367 getState().Type
= ProcessingType::CUs
;
368 registerUnit(U
, false);
369 constructFromUnit(U
);
372 DIE
*DIEBuilder::constructDIEFast(DWARFDie
&DDie
, DWARFUnit
&U
,
375 std::optional
<uint32_t> Idx
= getAllocDIEId(U
, DDie
);
377 DWARFUnitInfo
&DWARFUnitInfo
= getUnitInfo(UnitId
);
378 DIEInfo
&DieInfo
= getDIEInfo(UnitId
, *Idx
);
379 if (DWARFUnitInfo
.IsConstructed
&& DieInfo
.Die
)
382 Idx
= allocDIE(U
, DDie
, getState().DIEAlloc
, UnitId
);
385 DIEInfo
&DieInfo
= getDIEInfo(UnitId
, *Idx
);
387 uint64_t Offset
= DDie
.getOffset();
388 uint64_t NextOffset
= Offset
;
389 DWARFDataExtractor Data
= U
.getDebugInfoExtractor();
390 DWARFDebugInfoEntry DDIEntry
;
392 if (DDIEntry
.extractFast(U
, &NextOffset
, Data
, U
.getNextUnitOffset(), 0))
393 assert(NextOffset
- U
.getOffset() <= Data
.getData().size() &&
396 SmallString
<40> DIECopy(Data
.getData().substr(Offset
, NextOffset
- Offset
));
398 DWARFDataExtractor(DIECopy
, Data
.isLittleEndian(), Data
.getAddressSize());
400 const DWARFAbbreviationDeclaration
*Abbrev
=
401 DDie
.getAbbreviationDeclarationPtr();
402 uint64_t AttrOffset
= getULEB128Size(Abbrev
->getCode());
404 using AttrSpec
= DWARFAbbreviationDeclaration::AttributeSpec
;
405 for (const AttrSpec
&AttrSpec
: Abbrev
->attributes()) {
406 DWARFFormValue
Val(AttrSpec
.Form
);
407 Val
.extractValue(Data
, &AttrOffset
, U
.getFormParams(), &U
);
408 cloneAttribute(*DieInfo
.Die
, DDie
, U
, Val
, AttrSpec
);
414 getUnitForOffset(DIEBuilder
&Builder
, DWARFContext
&DWCtx
,
415 const uint64_t Offset
,
416 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
) {
417 auto findUnit
= [&](std::vector
<DWARFUnit
*> &Units
) -> DWARFUnit
* {
418 auto CUIter
= llvm::upper_bound(Units
, Offset
,
419 [](uint64_t LHS
, const DWARFUnit
*RHS
) {
420 return LHS
< RHS
->getNextUnitOffset();
422 static std::vector
<DWARFUnit
*> CUOffsets
;
423 static std::once_flag InitVectorFlag
;
424 auto initCUVector
= [&]() {
425 CUOffsets
.reserve(DWCtx
.getNumCompileUnits());
426 for (const std::unique_ptr
<DWARFUnit
> &CU
: DWCtx
.compile_units())
427 CUOffsets
.emplace_back(CU
.get());
429 DWARFUnit
*CU
= CUIter
!= Units
.end() ? *CUIter
: nullptr;
430 // Above algorithm breaks when there is only one CU, and reference is
431 // outside of it. Fall through slower path, that searches all the CUs.
432 // For example when src and destination of cross CU references have
433 // different abbrev section.
435 (CU
&& AttrSpec
.Form
== dwarf::DW_FORM_ref_addr
&&
436 !(CU
->getOffset() < Offset
&& CU
->getNextUnitOffset() > Offset
))) {
437 // This is a work around for XCode clang. There is a build error when we
438 // pass DWCtx.compile_units() to llvm::upper_bound
439 std::call_once(InitVectorFlag
, initCUVector
);
440 auto CUIter
= std::upper_bound(CUOffsets
.begin(), CUOffsets
.end(), Offset
,
441 [](uint64_t LHS
, const DWARFUnit
*RHS
) {
442 return LHS
< RHS
->getNextUnitOffset();
444 CU
= CUIter
!= CUOffsets
.end() ? (*CUIter
) : nullptr;
449 switch (Builder
.getCurrentProcessingState()) {
450 case DIEBuilder::ProcessingType::DWARF4TUs
:
451 return findUnit(Builder
.getDWARF4TUVector());
452 case DIEBuilder::ProcessingType::DWARF5TUs
:
453 return findUnit(Builder
.getDWARF5TUVector());
454 case DIEBuilder::ProcessingType::CUs
:
455 return findUnit(Builder
.getDWARFCUVector());
461 uint32_t DIEBuilder::finalizeDIEs(DWARFUnit
&CU
, DIE
&Die
,
462 uint32_t &CurOffset
) {
463 getState().DWARFDieAddressesParsed
.erase(Die
.getOffset());
464 uint32_t CurSize
= 0;
465 Die
.setOffset(CurOffset
);
466 // It is possible that an indexed debugging information entry has a parent
467 // that is not indexed (for example, if its parent does not have a name
468 // attribute). In such a case, a parent attribute may point to a nameless
469 // index entry (that is, one that cannot be reached from any entry in the name
470 // table), or it may point to the nearest ancestor that does have an index
472 // Skipping entry is not very useful for LLDB. This follows clang where
473 // children of forward declaration won't have DW_IDX_parent.
474 // https://github.com/llvm/llvm-project/pull/91808
476 // If Parent is nullopt and NumberParentsInChain is not zero, then forward
477 // declaration was encountered in this DF traversal. Propagating nullopt for
478 // Parent to children.
479 for (DIEValue
&Val
: Die
.values())
480 CurSize
+= Val
.sizeOf(CU
.getFormParams());
481 CurSize
+= getULEB128Size(Die
.getAbbrevNumber());
482 CurOffset
+= CurSize
;
484 for (DIE
&Child
: Die
.children()) {
485 uint32_t ChildSize
= finalizeDIEs(CU
, Child
, CurOffset
);
486 CurSize
+= ChildSize
;
488 // for children end mark.
489 if (Die
.hasChildren()) {
490 CurSize
+= sizeof(uint8_t);
491 CurOffset
+= sizeof(uint8_t);
494 Die
.setSize(CurSize
);
498 void DIEBuilder::finish() {
499 auto finalizeCU
= [&](DWARFUnit
&CU
, uint64_t &UnitStartOffset
) -> void {
500 DIE
*UnitDIE
= getUnitDIEbyUnit(CU
);
501 uint32_t HeaderSize
= CU
.getHeaderSize();
502 uint32_t CurOffset
= HeaderSize
;
503 std::vector
<std::optional
<BOLTDWARF5AccelTableData
*>> Parents
;
504 Parents
.push_back(std::nullopt
);
505 finalizeDIEs(CU
, *UnitDIE
, CurOffset
);
507 DWARFUnitInfo
&CurUnitInfo
= getUnitInfoByDwarfUnit(CU
);
508 CurUnitInfo
.UnitOffset
= UnitStartOffset
;
509 CurUnitInfo
.UnitLength
= HeaderSize
+ UnitDIE
->getSize();
510 UnitStartOffset
+= CurUnitInfo
.UnitLength
;
512 // Computing offsets for .debug_types section.
513 // It's processed first when CU is registered so will be at the begginnig of
515 uint64_t TypeUnitStartOffset
= 0;
516 for (DWARFUnit
*CU
: getState().DUList
) {
517 // We process DWARF$ types first.
518 if (!(CU
->getVersion() < 5 && CU
->isTypeUnit()))
520 finalizeCU(*CU
, TypeUnitStartOffset
);
523 for (DWARFUnit
*CU
: getState().DUList
) {
524 // Skipping DWARF4 types.
525 if (CU
->getVersion() < 5 && CU
->isTypeUnit())
527 finalizeCU(*CU
, UnitSize
);
529 if (opts::Verbosity
>= 1) {
530 if (!getState().DWARFDieAddressesParsed
.empty())
531 dbgs() << "Referenced DIE offsets not in .debug_info\n";
532 for (const uint64_t Address
: getState().DWARFDieAddressesParsed
) {
533 dbgs() << Twine::utohexstr(Address
) << "\n";
538 void DIEBuilder::populateDebugNamesTable(
539 DWARFUnit
&CU
, const DIE
&Die
,
540 std::optional
<BOLTDWARF5AccelTableData
*> Parent
,
541 uint32_t NumberParentsInChain
) {
542 std::optional
<BOLTDWARF5AccelTableData
*> NameEntry
=
543 DebugNamesTable
.addAccelTableEntry(
544 CU
, Die
, SkeletonCU
? SkeletonCU
->getDWOId() : std::nullopt
,
545 NumberParentsInChain
, Parent
);
546 if (!Parent
&& NumberParentsInChain
)
547 NameEntry
= std::nullopt
;
549 ++NumberParentsInChain
;
551 for (const DIE
&Child
: Die
.children())
552 populateDebugNamesTable(CU
, Child
, NameEntry
, NumberParentsInChain
);
555 void DIEBuilder::updateDebugNamesTable() {
556 auto finalizeDebugNamesTableForCU
= [&](DWARFUnit
&CU
,
557 uint64_t &UnitStartOffset
) -> void {
558 DIE
*UnitDIE
= getUnitDIEbyUnit(CU
);
559 DebugNamesTable
.setCurrentUnit(CU
, UnitStartOffset
);
560 populateDebugNamesTable(CU
, *UnitDIE
, std::nullopt
, 0);
562 DWARFUnitInfo
&CurUnitInfo
= getUnitInfoByDwarfUnit(CU
);
563 UnitStartOffset
+= CurUnitInfo
.UnitLength
;
566 uint64_t TypeUnitStartOffset
= 0;
567 for (DWARFUnit
*CU
: getState().DUList
) {
568 if (!(CU
->getVersion() < 5 && CU
->isTypeUnit()))
570 finalizeDebugNamesTableForCU(*CU
, TypeUnitStartOffset
);
573 for (DWARFUnit
*CU
: getState().DUList
) {
574 if (CU
->getVersion() < 5 && CU
->isTypeUnit())
576 finalizeDebugNamesTableForCU(*CU
, DebugNamesUnitSize
);
581 DWARFDie
DIEBuilder::resolveDIEReference(
582 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
583 const uint64_t RefOffset
, DWARFUnit
*&RefCU
,
584 DWARFDebugInfoEntry
&DwarfDebugInfoEntry
) {
585 uint64_t TmpRefOffset
= RefOffset
;
587 getUnitForOffset(*this, *DwarfContext
, TmpRefOffset
, AttrSpec
))) {
588 /// Trying to add to current working set in case it's cross CU reference.
589 registerUnit(*RefCU
, true);
590 DWARFDataExtractor DebugInfoData
= RefCU
->getDebugInfoExtractor();
591 if (DwarfDebugInfoEntry
.extractFast(*RefCU
, &TmpRefOffset
, DebugInfoData
,
592 RefCU
->getNextUnitOffset(), 0)) {
593 // In a file with broken references, an attribute might point to a NULL
595 DWARFDie RefDie
= DWARFDie(RefCU
, &DwarfDebugInfoEntry
);
596 if (!RefDie
.isNULL()) {
597 std::optional
<uint32_t> UnitId
= getUnitId(*RefCU
);
600 if (UnitId
&& !getState().CloneUnitCtxMap
[*UnitId
].IsConstructed
&&
601 !getAllocDIEId(*RefCU
, RefDie
))
602 allocDIE(*RefCU
, RefDie
, getState().DIEAlloc
, *UnitId
);
606 << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE "
608 << Twine::utohexstr(RefOffset
) << ".\n";
611 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse "
612 "referenced DIE at offset: "
613 << Twine::utohexstr(RefOffset
) << ".\n";
617 << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced "
618 "CU. Referenced DIE offset: "
619 << Twine::utohexstr(RefOffset
) << ".\n";
624 void DIEBuilder::cloneDieOffsetReferenceAttribute(
625 DIE
&Die
, DWARFUnit
&U
, const DWARFDie
&InputDIE
,
626 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
, uint64_t Ref
) {
627 DIE
*NewRefDie
= nullptr;
628 DWARFUnit
*RefUnit
= nullptr;
630 DWARFDebugInfoEntry DDIEntry
;
631 const DWARFDie RefDie
= resolveDIEReference(AttrSpec
, Ref
, RefUnit
, DDIEntry
);
636 const std::optional
<uint32_t> UnitId
= getUnitId(*RefUnit
);
637 const std::optional
<uint32_t> IsAllocId
= getAllocDIEId(*RefUnit
, RefDie
);
638 assert(IsAllocId
.has_value() && "Encountered unexpected unallocated DIE.");
639 const uint32_t DIEId
= *IsAllocId
;
640 DIEInfo
&DieInfo
= getDIEInfo(*UnitId
, DIEId
);
643 assert(Ref
> InputDIE
.getOffset());
645 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected "
646 "unallocated DIE. Should be alloc!\n";
647 // We haven't cloned this DIE yet. Just create an empty one and
648 // store it. It'll get really cloned when we process it.
649 DieInfo
.Die
= DIE::get(getState().DIEAlloc
, dwarf::Tag(RefDie
.getTag()));
651 NewRefDie
= DieInfo
.Die
;
653 if (AttrSpec
.Form
== dwarf::DW_FORM_ref_addr
) {
654 // Adding referenced DIE to DebugNames to be used when entries are created
655 // that contain cross cu references.
656 if (DebugNamesTable
.canGenerateEntryWithCrossCUReference(U
, Die
, AttrSpec
))
657 DebugNamesTable
.addCrossCUDie(&U
, DieInfo
.Die
);
658 // no matter forward reference or backward reference, we are supposed
659 // to calculate them in `finish` due to the possible modification of
661 DWARFDie CurDie
= const_cast<DWARFDie
&>(InputDIE
);
662 DIEInfo
*CurDieInfo
= &getDIEInfoByDwarfDie(CurDie
);
663 getState().AddrReferences
.push_back(
664 std::make_pair(CurDieInfo
, AddrReferenceInfo(&DieInfo
, AttrSpec
)));
666 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, dwarf::DW_FORM_ref_addr
,
667 DIEInteger(DieInfo
.Die
->getOffset()));
671 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, AttrSpec
.Form
,
672 DIEEntry(*NewRefDie
));
675 void DIEBuilder::cloneStringAttribute(
676 DIE
&Die
, const DWARFUnit
&U
,
677 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
678 const DWARFFormValue
&Val
) {
679 if (AttrSpec
.Form
== dwarf::DW_FORM_string
) {
680 Expected
<const char *> StrAddr
= Val
.getAsCString();
682 consumeError(StrAddr
.takeError());
685 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, dwarf::DW_FORM_string
,
686 new (getState().DIEAlloc
)
687 DIEInlineString(StrAddr
.get(), getState().DIEAlloc
));
689 std::optional
<uint64_t> OffsetIndex
= Val
.getRawUValue();
690 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, AttrSpec
.Form
,
691 DIEInteger(*OffsetIndex
));
695 bool DIEBuilder::cloneExpression(const DataExtractor
&Data
,
696 const DWARFExpression
&Expression
,
698 SmallVectorImpl
<uint8_t> &OutputBuffer
,
699 const CloneExpressionStage
&Stage
) {
700 using Encoding
= DWARFExpression::Operation::Encoding
;
701 using Descr
= DWARFExpression::Operation::Description
;
702 uint64_t OpOffset
= 0;
703 bool DoesContainReference
= false;
704 for (const DWARFExpression::Operation
&Op
: Expression
) {
705 const Descr
&Description
= Op
.getDescription();
706 // DW_OP_const_type is variable-length and has 3
707 // operands. Thus far we only support 2.
708 if ((Description
.Op
.size() == 2 &&
709 Description
.Op
[0] == Encoding::BaseTypeRef
) ||
710 (Description
.Op
.size() == 2 &&
711 Description
.Op
[1] == Encoding::BaseTypeRef
&&
712 Description
.Op
[0] != Encoding::Size1
))
713 BC
.outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP "
716 if ((Description
.Op
.size() == 1 &&
717 Description
.Op
[0] == Encoding::BaseTypeRef
) ||
718 (Description
.Op
.size() == 2 &&
719 Description
.Op
[1] == Encoding::BaseTypeRef
&&
720 Description
.Op
[0] == Encoding::Size1
)) {
721 // This code assumes that the other non-typeref operand fits into 1
723 assert(OpOffset
< Op
.getEndOffset());
724 const uint32_t ULEBsize
= Op
.getEndOffset() - OpOffset
- 1;
726 assert(ULEBsize
<= 16);
728 // Copy over the operation.
729 OutputBuffer
.push_back(Op
.getCode());
731 if (Description
.Op
.size() == 1) {
732 RefOffset
= Op
.getRawOperand(0);
734 OutputBuffer
.push_back(Op
.getRawOperand(0));
735 RefOffset
= Op
.getRawOperand(1);
738 if (RefOffset
> 0 || Op
.getCode() != dwarf::DW_OP_convert
) {
739 DoesContainReference
= true;
740 std::optional
<uint32_t> RefDieID
=
741 getAllocDIEId(U
, U
.getOffset() + RefOffset
);
742 std::optional
<uint32_t> RefUnitID
= getUnitId(U
);
743 if (RefDieID
.has_value() && RefUnitID
.has_value()) {
744 DIEInfo
&RefDieInfo
= getDIEInfo(*RefUnitID
, *RefDieID
);
745 if (DIE
*Clone
= RefDieInfo
.Die
)
746 Offset
= Stage
== CloneExpressionStage::INIT
? RefOffset
747 : Clone
->getOffset();
749 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref "
751 "DW_TAG_base_type.\n";
755 // Hard coding to max size so size doesn't change when we update the
757 encodeULEB128(Offset
, ULEB
, 4);
758 ArrayRef
<uint8_t> ULEBbytes(ULEB
, 4);
759 OutputBuffer
.append(ULEBbytes
.begin(), ULEBbytes
.end());
761 // Copy over everything else unmodified.
762 const StringRef Bytes
= Data
.getData().slice(OpOffset
, Op
.getEndOffset());
763 OutputBuffer
.append(Bytes
.begin(), Bytes
.end());
765 OpOffset
= Op
.getEndOffset();
767 return DoesContainReference
;
770 void DIEBuilder::cloneBlockAttribute(
771 DIE
&Die
, DWARFUnit
&U
,
772 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
773 const DWARFFormValue
&Val
) {
776 DIELoc
*Loc
= nullptr;
777 DIEBlock
*Block
= nullptr;
779 if (AttrSpec
.Form
== dwarf::DW_FORM_exprloc
) {
780 Loc
= new (getState().DIEAlloc
) DIELoc
;
781 } else if (doesFormBelongToClass(AttrSpec
.Form
, DWARFFormValue::FC_Block
,
783 Block
= new (getState().DIEAlloc
) DIEBlock
;
786 << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in "
787 "cloneBlockAttribute\n";
790 Attr
= Loc
? static_cast<DIEValueList
*>(Loc
)
791 : static_cast<DIEValueList
*>(Block
);
793 SmallVector
<uint8_t, 32> Buffer
;
794 ArrayRef
<uint8_t> Bytes
= *Val
.getAsBlock();
795 if (DWARFAttribute::mayHaveLocationExpr(AttrSpec
.Attr
) &&
796 (Val
.isFormClass(DWARFFormValue::FC_Block
) ||
797 Val
.isFormClass(DWARFFormValue::FC_Exprloc
))) {
798 DataExtractor
Data(StringRef((const char *)Bytes
.data(), Bytes
.size()),
799 U
.isLittleEndian(), U
.getAddressByteSize());
800 DWARFExpression
Expr(Data
, U
.getAddressByteSize(),
801 U
.getFormParams().Format
);
802 if (cloneExpression(Data
, Expr
, U
, Buffer
, CloneExpressionStage::INIT
))
803 getState().LocWithReferencesToProcess
.emplace_back(
804 Bytes
.vec(), U
, Die
, AttrSpec
.Form
, AttrSpec
.Attr
);
807 for (auto Byte
: Bytes
)
808 Attr
->addValue(getState().DIEAlloc
, static_cast<dwarf::Attribute
>(0),
809 dwarf::DW_FORM_data1
, DIEInteger(Byte
));
812 Loc
->setSize(Bytes
.size());
814 Block
->setSize(Bytes
.size());
817 Value
= DIEValue(dwarf::Attribute(AttrSpec
.Attr
),
818 dwarf::Form(AttrSpec
.Form
), Loc
);
820 Value
= DIEValue(dwarf::Attribute(AttrSpec
.Attr
),
821 dwarf::Form(AttrSpec
.Form
), Block
);
822 Die
.addValue(getState().DIEAlloc
, Value
);
825 void DIEBuilder::cloneAddressAttribute(
826 DIE
&Die
, const DWARFUnit
&U
,
827 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
828 const DWARFFormValue
&Val
) {
829 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, AttrSpec
.Form
,
830 DIEInteger(Val
.getRawUValue()));
833 void DIEBuilder::cloneRefsigAttribute(
834 DIE
&Die
, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
835 const DWARFFormValue
&Val
) {
836 const std::optional
<uint64_t> SigVal
= Val
.getAsSignatureReference();
837 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, dwarf::DW_FORM_ref_sig8
,
838 DIEInteger(*SigVal
));
841 void DIEBuilder::cloneScalarAttribute(
842 DIE
&Die
, const DWARFDie
&InputDIE
,
843 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
844 const DWARFFormValue
&Val
) {
847 if (auto OptionalValue
= Val
.getAsUnsignedConstant())
848 Value
= *OptionalValue
;
849 else if (auto OptionalValue
= Val
.getAsSignedConstant())
850 Value
= *OptionalValue
;
851 else if (auto OptionalValue
= Val
.getAsSectionOffset())
852 Value
= *OptionalValue
;
854 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
855 "attribute form. Dropping "
860 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, AttrSpec
.Form
,
864 void DIEBuilder::cloneLoclistAttrubute(
865 DIE
&Die
, const DWARFDie
&InputDIE
,
866 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
,
867 const DWARFFormValue
&Val
) {
868 std::optional
<uint64_t> Value
= std::nullopt
;
870 if (auto OptionalValue
= Val
.getAsUnsignedConstant())
871 Value
= OptionalValue
;
872 else if (auto OptionalValue
= Val
.getAsSignedConstant())
873 Value
= OptionalValue
;
874 else if (auto OptionalValue
= Val
.getAsSectionOffset())
875 Value
= OptionalValue
;
877 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
878 "attribute form. Dropping "
881 if (!Value
.has_value())
884 Die
.addValue(getState().DIEAlloc
, AttrSpec
.Attr
, AttrSpec
.Form
,
888 void DIEBuilder::cloneAttribute(
889 DIE
&Die
, const DWARFDie
&InputDIE
, DWARFUnit
&U
, const DWARFFormValue
&Val
,
890 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec
) {
891 switch (AttrSpec
.Form
) {
892 case dwarf::DW_FORM_strp
:
893 case dwarf::DW_FORM_string
:
894 case dwarf::DW_FORM_strx
:
895 case dwarf::DW_FORM_strx1
:
896 case dwarf::DW_FORM_strx2
:
897 case dwarf::DW_FORM_strx3
:
898 case dwarf::DW_FORM_strx4
:
899 case dwarf::DW_FORM_GNU_str_index
:
900 case dwarf::DW_FORM_line_strp
:
901 cloneStringAttribute(Die
, U
, AttrSpec
, Val
);
903 case dwarf::DW_FORM_ref_addr
:
904 cloneDieOffsetReferenceAttribute(Die
, U
, InputDIE
, AttrSpec
,
905 *Val
.getAsDebugInfoReference());
907 case dwarf::DW_FORM_ref1
:
908 case dwarf::DW_FORM_ref2
:
909 case dwarf::DW_FORM_ref4
:
910 case dwarf::DW_FORM_ref8
:
911 cloneDieOffsetReferenceAttribute(Die
, U
, InputDIE
, AttrSpec
,
912 Val
.getUnit()->getOffset() +
913 *Val
.getAsRelativeReference());
915 case dwarf::DW_FORM_block
:
916 case dwarf::DW_FORM_block1
:
917 case dwarf::DW_FORM_block2
:
918 case dwarf::DW_FORM_block4
:
919 case dwarf::DW_FORM_exprloc
:
920 cloneBlockAttribute(Die
, U
, AttrSpec
, Val
);
922 case dwarf::DW_FORM_addr
:
923 case dwarf::DW_FORM_addrx
:
924 case dwarf::DW_FORM_GNU_addr_index
:
925 cloneAddressAttribute(Die
, U
, AttrSpec
, Val
);
927 case dwarf::DW_FORM_data1
:
928 case dwarf::DW_FORM_data2
:
929 case dwarf::DW_FORM_data4
:
930 case dwarf::DW_FORM_data8
:
931 case dwarf::DW_FORM_udata
:
932 case dwarf::DW_FORM_sdata
:
933 case dwarf::DW_FORM_sec_offset
:
934 case dwarf::DW_FORM_rnglistx
:
935 case dwarf::DW_FORM_flag
:
936 case dwarf::DW_FORM_flag_present
:
937 case dwarf::DW_FORM_implicit_const
:
938 cloneScalarAttribute(Die
, InputDIE
, AttrSpec
, Val
);
940 case dwarf::DW_FORM_loclistx
:
941 cloneLoclistAttrubute(Die
, InputDIE
, AttrSpec
, Val
);
943 case dwarf::DW_FORM_ref_sig8
:
944 cloneRefsigAttribute(Die
, AttrSpec
, Val
);
947 BC
.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute "
949 dwarf::FormEncodingString(AttrSpec
.Form
).str() +
950 " in cloneAttribute. Dropping.";
953 void DIEBuilder::assignAbbrev(DIEAbbrev
&Abbrev
) {
954 // Check the set for priors.
958 DIEAbbrev
*InSet
= AbbreviationsSet
.FindNodeOrInsertPos(ID
, InsertToken
);
960 // If it's newly added.
962 // Assign existing abbreviation number.
963 Abbrev
.setNumber(InSet
->getNumber());
965 // Add to abbreviation list.
966 Abbreviations
.push_back(
967 std::make_unique
<DIEAbbrev
>(Abbrev
.getTag(), Abbrev
.hasChildren()));
968 for (const auto &Attr
: Abbrev
.getData())
969 Abbreviations
.back()->AddAttribute(Attr
.getAttribute(), Attr
.getForm());
970 AbbreviationsSet
.InsertNode(Abbreviations
.back().get(), InsertToken
);
971 // Assign the unique abbreviation number.
972 Abbrev
.setNumber(Abbreviations
.size());
973 Abbreviations
.back()->setNumber(Abbreviations
.size());
977 void DIEBuilder::generateAbbrevs() {
981 for (DWARFUnit
*DU
: getState().DUList
) {
982 DIE
*UnitDIE
= getUnitDIEbyUnit(*DU
);
983 generateUnitAbbrevs(UnitDIE
);
987 void DIEBuilder::generateUnitAbbrevs(DIE
*Die
) {
988 DIEAbbrev NewAbbrev
= Die
->generateAbbrev();
990 if (Die
->hasChildren())
991 NewAbbrev
.setChildrenFlag(dwarf::DW_CHILDREN_yes
);
992 assignAbbrev(NewAbbrev
);
993 Die
->setAbbrevNumber(NewAbbrev
.getNumber());
995 for (auto &Child
: Die
->children()) {
996 generateUnitAbbrevs(&Child
);
1000 static uint64_t getHash(const DWARFUnit
&DU
) {
1001 // Before DWARF5 TU units are in their own section, so at least one offset,
1002 // first one, will be the same as CUs in .debug_info.dwo section
1003 if (DU
.getVersion() < 5 && DU
.isTypeUnit()) {
1004 const uint64_t TypeUnitHash
=
1005 cast_or_null
<DWARFTypeUnit
>(&DU
)->getTypeHash();
1006 const uint64_t Offset
= DU
.getOffset();
1007 return llvm::hash_combine(llvm::hash_value(TypeUnitHash
),
1008 llvm::hash_value(Offset
));
1010 return DU
.getOffset();
1013 void DIEBuilder::registerUnit(DWARFUnit
&DU
, bool NeedSort
) {
1014 auto IterGlobal
= AllProcessed
.insert(getHash(DU
));
1015 // If DU is already in a current working set or was already processed we can
1017 if (!IterGlobal
.second
)
1019 if (getState().Type
== ProcessingType::DWARF4TUs
) {
1020 getState().DWARF4TUVector
.push_back(&DU
);
1021 } else if (getState().Type
== ProcessingType::DWARF5TUs
) {
1022 getState().DWARF5TUVector
.push_back(&DU
);
1024 getState().DWARFCUVector
.push_back(&DU
);
1025 /// Sorting for cross CU reference resolution.
1027 std::sort(getState().DWARFCUVector
.begin(),
1028 getState().DWARFCUVector
.end(),
1029 [](const DWARFUnit
*A
, const DWARFUnit
*B
) {
1030 return A
->getOffset() < B
->getOffset();
1033 getState().UnitIDMap
[getHash(DU
)] = getState().DUList
.size();
1034 // This handles the case where we do have cross cu references, but CUs do not
1035 // share the same abbrev table.
1036 if (getState().DUList
.size() == getState().CloneUnitCtxMap
.size())
1037 getState().CloneUnitCtxMap
.emplace_back();
1038 getState().DUList
.push_back(&DU
);
1041 std::optional
<uint32_t> DIEBuilder::getUnitId(const DWARFUnit
&DU
) {
1042 auto Iter
= getState().UnitIDMap
.find(getHash(DU
));
1043 if (Iter
!= getState().UnitIDMap
.end())
1044 return Iter
->second
;
1045 return std::nullopt
;