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 //===----------------------------------------------------------------------===// 8 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" 27 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> 36 37 #undef DEBUG_TYPE 38 #define DEBUG_TYPE "bolt" 39 namespace opts { 40 extern cl::opt<unsigned> Verbosity; 41 } 42 namespace llvm { 43 namespace bolt { 44 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; 63 } 64 DWOName.append(".dwo"); 65 return DWOName; 66 } 67 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; 81 } 82 DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(), 83 DIEInteger(NewOffset)); 84 } 85 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); 103 104 DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir); 105 assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU."); 106 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); 112 } 113 return ObjectName; 114 } 115 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); 125 } 126 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; 133 134 const uint64_t NewAddr = 135 DstDIEInfo->Die->getOffset() + DstUnitInfo.UnitOffset; 136 SrcDIEInfo->Die->replaceValue(getState().DIEAlloc, Attr, Form, 137 DIEInteger(NewAddr)); 138 } 139 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); 150 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); 160 } 161 for (auto Byte : Buffer) 162 AttrVal->addValue(getState().DIEAlloc, static_cast<dwarf::Attribute>(0), 163 dwarf::DW_FORM_data1, DIEInteger(Byte)); 164 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)); 174 175 LocExpr.Die.replaceValue(getState().DIEAlloc, LocExpr.Attr, LocExpr.Form, 176 Value); 177 } 178 179 return; 180 } 181 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]; 188 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; 203 } 204 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; 211 } 212 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; 221 222 if (DWARFTypeUnit *TU = dyn_cast_or_null<DWARFTypeUnit>(&DU)) 223 TUTypeOffset = TU->getTypeOffset(); 224 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; 232 233 if (const DWARFAbbreviationDeclaration *AbbrDecl = 234 DIEEntry.getAbbreviationDeclarationPtr()) { 235 DWARFDie DDie(&DU, &DIEEntry); 236 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; 245 246 if (!CurParentDIEStack.empty()) 247 CurParentDIEStack.back()->addChild(CurDIE); 248 249 if (AbbrDecl->hasChildren()) 250 CurParentDIEStack.push_back(CurDIE); 251 } else { 252 // NULL DIE: finishes current children scope. 253 CurParentDIEStack.pop_back(); 254 } 255 } while (CurParentDIEStack.size() > 0); 256 257 getState().CloneUnitCtxMap[*UnitId].IsConstructed = true; 258 } 259 260 DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, 261 DWARF5AcceleratorTable &DebugNamesTable, 262 DWARFUnit *SkeletonCU) 263 : BC(BC), DwarfContext(DwarfContext), SkeletonCU(SkeletonCU), 264 DebugNamesTable(DebugNamesTable) {} 265 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; 272 } 273 274 void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter *StrOffsetWriter, 275 const bool Init) { 276 if (Init) 277 BuilderState.reset(new State()); 278 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); 285 } 286 } 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(); 292 293 getState().Type = ProcessingType::DWARF4TUs; 294 for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) 295 registerUnit(*DU.get(), false); 296 297 for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) 298 constructFromUnit(*DU.get()); 299 300 DWARFContext::unit_iterator_range CURanges = 301 isDWO() ? DwarfContext->dwo_info_section_units() 302 : DwarfContext->info_section_units(); 303 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); 312 } 313 314 for (DWARFUnit *DU : getState().DWARF5TUVector) { 315 constructFromUnit(*DU); 316 if (StrOffsetWriter) 317 StrOffsetWriter->finalizeSection(*DU, *this); 318 } 319 } 320 321 void DIEBuilder::buildCompileUnits(const bool Init) { 322 if (Init) 323 BuilderState.reset(new State()); 324 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(); 330 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); 339 } 340 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); 346 } 347 } 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); 358 359 for (DWARFUnit *DU : getState().DUList) 360 constructFromUnit(*DU); 361 } 362 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); 370 } 371 372 DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U, 373 uint32_t UnitId) { 374 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); 383 } 384 385 DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); 386 387 uint64_t Offset = DDie.getOffset(); 388 uint64_t NextOffset = Offset; 389 DWARFDataExtractor Data = U.getDebugInfoExtractor(); 390 DWARFDebugInfoEntry DDIEntry; 391 392 if (DDIEntry.extractFast(U, &NextOffset, Data, U.getNextUnitOffset(), 0)) 393 assert(NextOffset - U.getOffset() <= Data.getData().size() && 394 "NextOffset OOB"); 395 396 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); 397 Data = 398 DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); 399 400 const DWARFAbbreviationDeclaration *Abbrev = 401 DDie.getAbbreviationDeclarationPtr(); 402 uint64_t AttrOffset = getULEB128Size(Abbrev->getCode()); 403 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); 409 } 410 return DieInfo.Die; 411 } 412 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(); 421 }); 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()); 428 }; 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(); 443 }); 444 CU = CUIter != CUOffsets.end() ? (*CUIter) : nullptr; 445 } 446 return CU; 447 }; 448 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()); 456 }; 457 458 return nullptr; 459 } 460 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 475 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; 483 484 for (DIE &Child : Die.children()) { 485 uint32_t ChildSize = finalizeDIEs(CU, Child, CurOffset); 486 CurSize += ChildSize; 487 } 488 // for children end mark. 489 if (Die.hasChildren()) { 490 CurSize += sizeof(uint8_t); 491 CurOffset += sizeof(uint8_t); 492 } 493 494 Die.setSize(CurSize); 495 return CurSize; 496 } 497 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); 506 507 DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); 508 CurUnitInfo.UnitOffset = UnitStartOffset; 509 CurUnitInfo.UnitLength = HeaderSize + UnitDIE->getSize(); 510 UnitStartOffset += CurUnitInfo.UnitLength; 511 }; 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); 521 } 522 523 for (DWARFUnit *CU : getState().DUList) { 524 // Skipping DWARF4 types. 525 if (CU->getVersion() < 5 && CU->isTypeUnit()) 526 continue; 527 finalizeCU(*CU, UnitSize); 528 } 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"; 534 } 535 } 536 } 537 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; 550 551 for (const DIE &Child : Die.children()) 552 populateDebugNamesTable(CU, Child, NameEntry, NumberParentsInChain); 553 } 554 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); 561 562 DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); 563 UnitStartOffset += CurUnitInfo.UnitLength; 564 }; 565 566 uint64_t TypeUnitStartOffset = 0; 567 for (DWARFUnit *CU : getState().DUList) { 568 if (!(CU->getVersion() < 5 && CU->isTypeUnit())) 569 break; 570 finalizeDebugNamesTableForCU(*CU, TypeUnitStartOffset); 571 } 572 573 for (DWARFUnit *CU : getState().DUList) { 574 if (CU->getVersion() < 5 && CU->isTypeUnit()) 575 continue; 576 finalizeDebugNamesTableForCU(*CU, DebugNamesUnitSize); 577 } 578 updateReferences(); 579 } 580 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); 598 599 // forward reference 600 if (UnitId && !getState().CloneUnitCtxMap[*UnitId].IsConstructed && 601 !getAllocDIEId(*RefCU, RefDie)) 602 allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId); 603 return RefDie; 604 } 605 BC.errs() 606 << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE " 607 "at offset: " 608 << Twine::utohexstr(RefOffset) << ".\n"; 609 610 } else { 611 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse " 612 "referenced DIE at offset: " 613 << Twine::utohexstr(RefOffset) << ".\n"; 614 } 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"; 620 } 621 return DWARFDie(); 622 } 623 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; 629 630 DWARFDebugInfoEntry DDIEntry; 631 const DWARFDie RefDie = resolveDIEReference(AttrSpec, Ref, RefUnit, DDIEntry); 632 633 if (!RefDie) 634 return; 635 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); 641 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())); 650 } 651 NewRefDie = DieInfo.Die; 652 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))); 665 666 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 667 DIEInteger(DieInfo.Die->getOffset())); 668 return; 669 } 670 671 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 672 DIEEntry(*NewRefDie)); 673 } 674 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; 684 } 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)); 692 } 693 } 694 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"; 715 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); 727 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); 736 } 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"; 752 } 753 } 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()); 764 } 765 OpOffset = Op.getEndOffset(); 766 } 767 return DoesContainReference; 768 } 769 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; 778 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; 789 } 790 Attr = Loc ? static_cast<DIEValueList *>(Loc) 791 : static_cast<DIEValueList *>(Block); 792 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; 806 } 807 for (auto Byte : Bytes) 808 Attr->addValue(getState().DIEAlloc, static_cast<dwarf::Attribute>(0), 809 dwarf::DW_FORM_data1, DIEInteger(Byte)); 810 811 if (Loc) 812 Loc->setSize(Bytes.size()); 813 else 814 Block->setSize(Bytes.size()); 815 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); 823 } 824 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())); 831 } 832 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)); 839 } 840 841 void DIEBuilder::cloneScalarAttribute( 842 DIE &Die, const DWARFDie &InputDIE, 843 const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 844 const DWARFFormValue &Val) { 845 uint64_t Value; 846 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; 858 } 859 860 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 861 DIEInteger(Value)); 862 } 863 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; 869 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"; 880 881 if (!Value.has_value()) 882 return; 883 884 Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 885 DIELocList(*Value)); 886 } 887 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."; 951 } 952 } 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); 959 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()); 974 } 975 } 976 977 void DIEBuilder::generateAbbrevs() { 978 if (isEmpty()) 979 return; 980 981 for (DWARFUnit *DU : getState().DUList) { 982 DIE *UnitDIE = getUnitDIEbyUnit(*DU); 983 generateUnitAbbrevs(UnitDIE); 984 } 985 } 986 987 void DIEBuilder::generateUnitAbbrevs(DIE *Die) { 988 DIEAbbrev NewAbbrev = Die->generateAbbrev(); 989 990 if (Die->hasChildren()) 991 NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); 992 assignAbbrev(NewAbbrev); 993 Die->setAbbrevNumber(NewAbbrev.getNumber()); 994 995 for (auto &Child : Die->children()) { 996 generateUnitAbbrevs(&Child); 997 } 998 } 999 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)); 1009 } 1010 return DU.getOffset(); 1011 } 1012 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(); 1031 }); 1032 } 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); 1039 } 1040 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; 1046 } 1047 1048 } // namespace bolt 1049 } // namespace llvm 1050