[nfc][Driver] Remove {{(.exe)?}} from sanitizer test (#121160)
[llvm-project.git] / bolt / lib / Core / DIEBuilder.cpp
blob80ad583e079d49aa2fdbe0e5bde51d9a47248541
1 //===- bolt/Core/DIEBuilder.cpp -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
28 #include <algorithm>
29 #include <cstdint>
30 #include <memory>
31 #include <mutex>
32 #include <optional>
33 #include <unordered_map>
34 #include <utility>
35 #include <vector>
37 #undef DEBUG_TYPE
38 #define DEBUG_TYPE "bolt"
39 namespace opts {
40 extern cl::opt<unsigned> Verbosity;
42 namespace llvm {
43 namespace bolt {
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.
48 static std::string
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}),
55 "");
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));
62 ++Index;
64 DWOName.append(".dwo");
65 return DWOName;
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(),
79 NewOffset, Unit);
80 return;
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);
92 if (!DWONameAttrInfo)
93 DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name);
94 if (!DWONameAttrInfo)
95 return "";
96 std::string ObjectName;
97 if (DWONameToUse)
98 ObjectName = *DWONameToUse;
99 else
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);
113 return ObjectName;
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,
122 DWOName);
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);
156 } else {
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));
165 DIEValue Value;
166 if (LocExpr.Form == dwarf::DW_FORM_exprloc)
167 Value =
168 DIEValue(dwarf::Attribute(LocExpr.Attr), dwarf::Form(LocExpr.Form),
169 static_cast<DIELoc *>(AttrVal));
170 else
171 Value =
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,
176 Value);
179 return;
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}));
202 return DId;
205 void DIEBuilder::constructFromUnit(DWARFUnit &DU) {
206 std::optional<uint32_t> UnitId = getUnitId(DU);
207 if (!UnitId) {
208 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
209 << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n";
210 return;
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);
227 do {
228 const bool IsTypeDIE = (TUTypeOffset == DIEOffset - DU.getOffset());
229 if (!DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset,
230 Parents.back()))
231 break;
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
240 // references.
241 if (!UI.UnitDie)
242 UI.UnitDie = CurDIE;
243 if (IsTypeDIE)
244 getState().TypeDIEMap[&DU] = CurDIE;
246 if (!CurParentDIEStack.empty())
247 CurParentDIEStack.back()->addChild(CurDIE);
249 if (AbbrDecl->hasChildren())
250 CurParentDIEStack.push_back(CurDIE);
251 } else {
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();
271 return CUNum;
274 void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter *StrOffsetWriter,
275 const bool Init) {
276 if (Init)
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())
310 continue;
311 registerUnit(*DU.get(), false);
314 for (DWARFUnit *DU : getState().DWARF5TUVector) {
315 constructFromUnit(*DU);
316 if (StrOffsetWriter)
317 StrOffsetWriter->finalizeSection(*DU, *this);
321 void DIEBuilder::buildCompileUnits(const bool Init) {
322 if (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())
337 continue;
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())
344 continue;
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,
373 uint32_t UnitId) {
375 std::optional<uint32_t> Idx = getAllocDIEId(U, DDie);
376 if (Idx) {
377 DWARFUnitInfo &DWARFUnitInfo = getUnitInfo(UnitId);
378 DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx);
379 if (DWARFUnitInfo.IsConstructed && DieInfo.Die)
380 return DieInfo.Die;
381 } else {
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() &&
394 "NextOffset OOB");
396 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
397 Data =
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);
410 return DieInfo.Die;
413 static DWARFUnit *
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.
434 if (!CU ||
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;
446 return CU;
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());
458 return nullptr;
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
471 // entry.
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);
495 return 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
514 // the vector.
515 uint64_t TypeUnitStartOffset = 0;
516 for (DWARFUnit *CU : getState().DUList) {
517 // We process DWARF$ types first.
518 if (!(CU->getVersion() < 5 && CU->isTypeUnit()))
519 break;
520 finalizeCU(*CU, TypeUnitStartOffset);
523 for (DWARFUnit *CU : getState().DUList) {
524 // Skipping DWARF4 types.
525 if (CU->getVersion() < 5 && CU->isTypeUnit())
526 continue;
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;
548 if (NameEntry)
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()))
569 break;
570 finalizeDebugNamesTableForCU(*CU, TypeUnitStartOffset);
573 for (DWARFUnit *CU : getState().DUList) {
574 if (CU->getVersion() < 5 && CU->isTypeUnit())
575 continue;
576 finalizeDebugNamesTableForCU(*CU, DebugNamesUnitSize);
578 updateReferences();
581 DWARFDie DIEBuilder::resolveDIEReference(
582 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
583 const uint64_t RefOffset, DWARFUnit *&RefCU,
584 DWARFDebugInfoEntry &DwarfDebugInfoEntry) {
585 uint64_t TmpRefOffset = RefOffset;
586 if ((RefCU =
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
594 // DIE.
595 DWARFDie RefDie = DWARFDie(RefCU, &DwarfDebugInfoEntry);
596 if (!RefDie.isNULL()) {
597 std::optional<uint32_t> UnitId = getUnitId(*RefCU);
599 // forward reference
600 if (UnitId && !getState().CloneUnitCtxMap[*UnitId].IsConstructed &&
601 !getAllocDIEId(*RefCU, RefDie))
602 allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId);
603 return RefDie;
605 BC.errs()
606 << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE "
607 "at offset: "
608 << Twine::utohexstr(RefOffset) << ".\n";
610 } else {
611 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse "
612 "referenced DIE at offset: "
613 << Twine::utohexstr(RefOffset) << ".\n";
615 } else {
616 BC.errs()
617 << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced "
618 "CU. Referenced DIE offset: "
619 << Twine::utohexstr(RefOffset) << ".\n";
621 return DWARFDie();
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);
633 if (!RefDie)
634 return;
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);
642 if (!DieInfo.Die) {
643 assert(Ref > InputDIE.getOffset());
644 (void)Ref;
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
660 // the DIE.
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()));
668 return;
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();
681 if (!StrAddr) {
682 consumeError(StrAddr.takeError());
683 return;
685 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_string,
686 new (getState().DIEAlloc)
687 DIEInlineString(StrAddr.get(), getState().DIEAlloc));
688 } else {
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,
697 DWARFUnit &U,
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 "
714 "encoding.\n";
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
722 // byte.
723 assert(OpOffset < Op.getEndOffset());
724 const uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
725 (void)ULEBsize;
726 assert(ULEBsize <= 16);
728 // Copy over the operation.
729 OutputBuffer.push_back(Op.getCode());
730 uint64_t RefOffset;
731 if (Description.Op.size() == 1) {
732 RefOffset = Op.getRawOperand(0);
733 } else {
734 OutputBuffer.push_back(Op.getRawOperand(0));
735 RefOffset = Op.getRawOperand(1);
737 uint32_t Offset = 0;
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();
748 else
749 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref "
750 "doesn't point to "
751 "DW_TAG_base_type.\n";
754 uint8_t ULEB[16];
755 // Hard coding to max size so size doesn't change when we update the
756 // offset.
757 encodeULEB128(Offset, ULEB, 4);
758 ArrayRef<uint8_t> ULEBbytes(ULEB, 4);
759 OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
760 } else {
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) {
774 DIEValueList *Attr;
775 DIEValue Value;
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,
782 U.getVersion())) {
783 Block = new (getState().DIEAlloc) DIEBlock;
784 } else {
785 BC.errs()
786 << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in "
787 "cloneBlockAttribute\n";
788 return;
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);
805 Bytes = Buffer;
807 for (auto Byte : Bytes)
808 Attr->addValue(getState().DIEAlloc, static_cast<dwarf::Attribute>(0),
809 dwarf::DW_FORM_data1, DIEInteger(Byte));
811 if (Loc)
812 Loc->setSize(Bytes.size());
813 else
814 Block->setSize(Bytes.size());
816 if (Loc)
817 Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
818 dwarf::Form(AttrSpec.Form), Loc);
819 else
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) {
845 uint64_t Value;
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;
853 else {
854 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
855 "attribute form. Dropping "
856 "attribute.\n";
857 return;
860 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form,
861 DIEInteger(Value));
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;
876 else
877 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar "
878 "attribute form. Dropping "
879 "attribute.\n";
881 if (!Value.has_value())
882 return;
884 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form,
885 DIELocList(*Value));
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);
902 break;
903 case dwarf::DW_FORM_ref_addr:
904 cloneDieOffsetReferenceAttribute(Die, U, InputDIE, AttrSpec,
905 *Val.getAsDebugInfoReference());
906 break;
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());
914 break;
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);
921 break;
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);
926 break;
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);
939 break;
940 case dwarf::DW_FORM_loclistx:
941 cloneLoclistAttrubute(Die, InputDIE, AttrSpec, Val);
942 break;
943 case dwarf::DW_FORM_ref_sig8:
944 cloneRefsigAttribute(Die, AttrSpec, Val);
945 break;
946 default:
947 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute "
948 "form " +
949 dwarf::FormEncodingString(AttrSpec.Form).str() +
950 " in cloneAttribute. Dropping.";
953 void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) {
954 // Check the set for priors.
955 FoldingSetNodeID ID;
956 Abbrev.Profile(ID);
957 void *InsertToken;
958 DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
960 // If it's newly added.
961 if (InSet) {
962 // Assign existing abbreviation number.
963 Abbrev.setNumber(InSet->getNumber());
964 } else {
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() {
978 if (isEmpty())
979 return;
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
1016 // skip it.
1017 if (!IterGlobal.second)
1018 return;
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);
1023 } else {
1024 getState().DWARFCUVector.push_back(&DU);
1025 /// Sorting for cross CU reference resolution.
1026 if (NeedSort)
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;
1048 } // namespace bolt
1049 } // namespace llvm