1 //===- DWARFLinkerCompileUnit.h ---------------------------------*- C++ -*-===// 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 #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H 10 #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H 11 12 #include "DWARFLinkerUnit.h" 13 #include "llvm/DWARFLinker/DWARFFile.h" 14 #include <optional> 15 16 namespace llvm { 17 namespace dwarf_linker { 18 namespace parallel { 19 20 using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>; 21 22 struct AttributesInfo; 23 class SyntheticTypeNameBuilder; 24 class DIEGenerator; 25 class TypeUnit; 26 class DependencyTracker; 27 28 class CompileUnit; 29 30 /// This is a helper structure which keeps a debug info entry 31 /// with it's containing compilation unit. 32 struct UnitEntryPairTy { 33 UnitEntryPairTy() = default; 34 UnitEntryPairTy(CompileUnit *CU, const DWARFDebugInfoEntry *DieEntry) 35 : CU(CU), DieEntry(DieEntry) {} 36 37 CompileUnit *CU = nullptr; 38 const DWARFDebugInfoEntry *DieEntry = nullptr; 39 40 UnitEntryPairTy getNamespaceOrigin(); 41 std::optional<UnitEntryPairTy> getParent(); 42 }; 43 44 enum ResolveInterCUReferencesMode : bool { 45 Resolve = true, 46 AvoidResolving = false, 47 }; 48 49 /// Stores all information related to a compile unit, be it in its original 50 /// instance of the object file or its brand new cloned and generated DIE tree. 51 /// NOTE: we need alignment of at least 8 bytes as we use 52 /// PointerIntPair<CompileUnit *, 3> in the DependencyTracker.h 53 class alignas(8) CompileUnit : public DwarfUnit { 54 public: 55 /// The stages of new compile unit processing. 56 enum class Stage : uint8_t { 57 /// Created, linked with input DWARF file. 58 CreatedNotLoaded = 0, 59 60 /// Input DWARF is loaded. 61 Loaded, 62 63 /// Input DWARF is analysed(DIEs pointing to the real code section are 64 /// discovered, type names are assigned if ODR is requested). 65 LivenessAnalysisDone, 66 67 /// Check if dependencies have incompatible placement. 68 /// If that is the case modify placement to be compatible. 69 UpdateDependenciesCompleteness, 70 71 /// Type names assigned to DIEs. 72 TypeNamesAssigned, 73 74 /// Output DWARF is generated. 75 Cloned, 76 77 /// Offsets inside patch records are updated. 78 PatchesUpdated, 79 80 /// Resources(Input DWARF, Output DWARF tree) are released. 81 Cleaned, 82 83 /// Compile Unit should be skipped 84 Skipped 85 }; 86 87 CompileUnit(LinkingGlobalData &GlobalData, unsigned ID, 88 StringRef ClangModuleName, DWARFFile &File, 89 OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format, 90 llvm::endianness Endianess); 91 92 CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, unsigned ID, 93 StringRef ClangModuleName, DWARFFile &File, 94 OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format, 95 llvm::endianness Endianess); 96 97 /// Returns stage of overall processing. 98 Stage getStage() const { return Stage; } 99 100 /// Set stage of overall processing. 101 void setStage(Stage Stage) { this->Stage = Stage; } 102 103 /// Loads unit line table. 104 void loadLineTable(); 105 106 /// Returns name of the file for the \p FileIdx 107 /// from the unit`s line table. 108 StringEntry *getFileName(unsigned FileIdx, StringPool &GlobalStrings); 109 110 /// Returns DWARFFile containing this compile unit. 111 const DWARFFile &getContaingFile() const { return File; } 112 113 /// Load DIEs of input compilation unit. \returns true if input DIEs 114 /// successfully loaded. 115 bool loadInputDIEs(); 116 117 /// Reset compile units data(results of liveness analysis, clonning) 118 /// if current stage greater than Stage::Loaded. We need to reset data 119 /// as we are going to repeat stages. 120 void maybeResetToLoadedStage(); 121 122 /// Collect references to parseable Swift interfaces in imported 123 /// DW_TAG_module blocks. 124 void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry); 125 126 /// Navigate DWARF tree and set die properties. 127 void analyzeDWARFStructure() { 128 analyzeDWARFStructureRec(getUnitDIE().getDebugInfoEntry(), false); 129 } 130 131 /// Cleanup unneeded resources after compile unit is cloned. 132 void cleanupDataAfterClonning(); 133 134 /// After cloning stage the output DIEs offsets are deallocated. 135 /// This method copies output offsets for referenced DIEs into DIEs patches. 136 void updateDieRefPatchesWithClonedOffsets(); 137 138 /// Search for subprograms and variables referencing live code and discover 139 /// dependend DIEs. Mark live DIEs, set placement for DIEs. 140 bool resolveDependenciesAndMarkLiveness( 141 bool InterCUProcessingStarted, 142 std::atomic<bool> &HasNewInterconnectedCUs); 143 144 /// Check dependend DIEs for incompatible placement. 145 /// Make placement to be consistent. 146 bool updateDependenciesCompleteness(); 147 148 /// Check DIEs to have a consistent marking(keep marking, placement marking). 149 void verifyDependencies(); 150 151 /// Search for type entries and assign names. 152 Error assignTypeNames(TypePool &TypePoolRef); 153 154 /// Kinds of placement for the output die. 155 enum DieOutputPlacement : uint8_t { 156 NotSet = 0, 157 158 /// Corresponding DIE goes to the type table only. 159 TypeTable = 1, 160 161 /// Corresponding DIE goes to the plain dwarf only. 162 PlainDwarf = 2, 163 164 /// Corresponding DIE goes to type table and to plain dwarf. 165 Both = 3, 166 }; 167 168 /// Information gathered about source DIEs. 169 struct DIEInfo { 170 DIEInfo() = default; 171 DIEInfo(const DIEInfo &Other) { Flags = Other.Flags.load(); } 172 DIEInfo &operator=(const DIEInfo &Other) { 173 Flags = Other.Flags.load(); 174 return *this; 175 } 176 177 /// Data member keeping various flags. 178 std::atomic<uint16_t> Flags = {0}; 179 180 /// \returns Placement kind for the corresponding die. 181 DieOutputPlacement getPlacement() const { 182 return DieOutputPlacement(Flags & 0x7); 183 } 184 185 /// Sets Placement kind for the corresponding die. 186 void setPlacement(DieOutputPlacement Placement) { 187 auto InputData = Flags.load(); 188 while (!Flags.compare_exchange_weak(InputData, 189 ((InputData & ~0x7) | Placement))) { 190 } 191 } 192 193 /// Unsets Placement kind for the corresponding die. 194 void unsetPlacement() { 195 auto InputData = Flags.load(); 196 while (!Flags.compare_exchange_weak(InputData, (InputData & ~0x7))) { 197 } 198 } 199 200 /// Sets Placement kind for the corresponding die. 201 bool setPlacementIfUnset(DieOutputPlacement Placement) { 202 auto InputData = Flags.load(); 203 if ((InputData & 0x7) == NotSet) 204 if (Flags.compare_exchange_weak(InputData, (InputData | Placement))) 205 return true; 206 207 return false; 208 } 209 210 #define SINGLE_FLAG_METHODS_SET(Name, Value) \ 211 bool get##Name() const { return Flags & Value; } \ 212 void set##Name() { \ 213 auto InputData = Flags.load(); \ 214 while (!Flags.compare_exchange_weak(InputData, InputData | Value)) { \ 215 } \ 216 } \ 217 void unset##Name() { \ 218 auto InputData = Flags.load(); \ 219 while (!Flags.compare_exchange_weak(InputData, InputData & ~Value)) { \ 220 } \ 221 } 222 223 /// DIE is a part of the linked output. 224 SINGLE_FLAG_METHODS_SET(Keep, 0x08) 225 226 /// DIE has children which are part of the linked output. 227 SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10) 228 229 /// DIE has children which are part of the type table. 230 SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20) 231 232 /// DIE is in module scope. 233 SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40) 234 235 /// DIE is in function scope. 236 SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80) 237 238 /// DIE is in anonymous namespace scope. 239 SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100) 240 241 /// DIE is available for ODR type deduplication. 242 SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200) 243 244 /// Track liveness for the DIE. 245 SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400) 246 247 /// Track liveness for the DIE. 248 SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800) 249 250 void unsetFlagsWhichSetDuringLiveAnalysis() { 251 auto InputData = Flags.load(); 252 while (!Flags.compare_exchange_weak( 253 InputData, InputData & ~(0x7 | 0x8 | 0x10 | 0x20))) { 254 } 255 } 256 257 /// Erase all flags. 258 void eraseData() { Flags = 0; } 259 260 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 261 LLVM_DUMP_METHOD void dump(); 262 #endif 263 264 bool needToPlaceInTypeTable() const { 265 return (getKeep() && (getPlacement() == CompileUnit::TypeTable || 266 getPlacement() == CompileUnit::Both)) || 267 getKeepTypeChildren(); 268 } 269 270 bool needToKeepInPlainDwarf() const { 271 return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf || 272 getPlacement() == CompileUnit::Both)) || 273 getKeepPlainChildren(); 274 } 275 }; 276 277 /// \defgroup Group of functions returning DIE info. 278 /// 279 /// @{ 280 281 /// \p Idx index of the DIE. 282 /// \returns DieInfo descriptor. 283 DIEInfo &getDIEInfo(unsigned Idx) { return DieInfoArray[Idx]; } 284 285 /// \p Idx index of the DIE. 286 /// \returns DieInfo descriptor. 287 const DIEInfo &getDIEInfo(unsigned Idx) const { return DieInfoArray[Idx]; } 288 289 /// \p Idx index of the DIE. 290 /// \returns DieInfo descriptor. 291 DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) { 292 return DieInfoArray[getOrigUnit().getDIEIndex(Entry)]; 293 } 294 295 /// \p Idx index of the DIE. 296 /// \returns DieInfo descriptor. 297 const DIEInfo &getDIEInfo(const DWARFDebugInfoEntry *Entry) const { 298 return DieInfoArray[getOrigUnit().getDIEIndex(Entry)]; 299 } 300 301 /// \p Die 302 /// \returns PlainDieInfo descriptor. 303 DIEInfo &getDIEInfo(const DWARFDie &Die) { 304 return DieInfoArray[getOrigUnit().getDIEIndex(Die)]; 305 } 306 307 /// \p Die 308 /// \returns PlainDieInfo descriptor. 309 const DIEInfo &getDIEInfo(const DWARFDie &Die) const { 310 return DieInfoArray[getOrigUnit().getDIEIndex(Die)]; 311 } 312 313 /// \p Idx index of the DIE. 314 /// \returns DieInfo descriptor. 315 uint64_t getDieOutOffset(uint32_t Idx) { 316 return reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx]) 317 ->load(); 318 } 319 320 /// \p Idx index of the DIE. 321 /// \returns type entry. 322 TypeEntry *getDieTypeEntry(uint32_t Idx) { 323 return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx]) 324 ->load(); 325 } 326 327 /// \p InputDieEntry debug info entry. 328 /// \returns DieInfo descriptor. 329 uint64_t getDieOutOffset(const DWARFDebugInfoEntry *InputDieEntry) { 330 return reinterpret_cast<std::atomic<uint64_t> *>( 331 &OutDieOffsetArray[getOrigUnit().getDIEIndex(InputDieEntry)]) 332 ->load(); 333 } 334 335 /// \p InputDieEntry debug info entry. 336 /// \returns type entry. 337 TypeEntry *getDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry) { 338 return reinterpret_cast<std::atomic<TypeEntry *> *>( 339 &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)]) 340 ->load(); 341 } 342 343 /// \p Idx index of the DIE. 344 /// \returns DieInfo descriptor. 345 void rememberDieOutOffset(uint32_t Idx, uint64_t Offset) { 346 reinterpret_cast<std::atomic<uint64_t> *>(&OutDieOffsetArray[Idx]) 347 ->store(Offset); 348 } 349 350 /// \p Idx index of the DIE. 351 /// \p Type entry. 352 void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry) { 353 reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx]) 354 ->store(Entry); 355 } 356 357 /// \p InputDieEntry debug info entry. 358 /// \p Type entry. 359 void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry, 360 TypeEntry *Entry) { 361 reinterpret_cast<std::atomic<TypeEntry *> *>( 362 &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)]) 363 ->store(Entry); 364 } 365 366 /// @} 367 368 /// Returns value of DW_AT_low_pc attribute. 369 std::optional<uint64_t> getLowPc() const { return LowPc; } 370 371 /// Returns value of DW_AT_high_pc attribute. 372 uint64_t getHighPc() const { return HighPc; } 373 374 /// Returns true if there is a label corresponding to the specified \p Addr. 375 bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); } 376 377 /// Add the low_pc of a label that is relocated by applying 378 /// offset \p PCOffset. 379 void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset); 380 381 /// Resolve the DIE attribute reference that has been extracted in \p 382 /// RefValue. The resulting DIE might be in another CompileUnit. 383 /// \returns referenced die and corresponding compilation unit. 384 /// compilation unit is null if reference could not be resolved. 385 std::optional<UnitEntryPairTy> 386 resolveDIEReference(const DWARFFormValue &RefValue, 387 ResolveInterCUReferencesMode CanResolveInterCUReferences); 388 389 std::optional<UnitEntryPairTy> 390 resolveDIEReference(const DWARFDebugInfoEntry *DieEntry, 391 dwarf::Attribute Attr, 392 ResolveInterCUReferencesMode CanResolveInterCUReferences); 393 394 /// @} 395 396 /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying 397 /// offset \p PCOffset. 398 void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset); 399 400 /// Returns function ranges of this unit. 401 const RangesTy &getFunctionRanges() const { return Ranges; } 402 403 /// Clone and emit this compilation unit. 404 Error cloneAndEmit(std::optional<Triple> TargetTriple, 405 TypeUnit *ArtificialTypeUnit); 406 407 /// Clone and emit debug locations(.debug_loc/.debug_loclists). 408 Error cloneAndEmitDebugLocations(); 409 410 /// Clone and emit ranges. 411 Error cloneAndEmitRanges(); 412 413 /// Clone and emit debug macros(.debug_macinfo/.debug_macro). 414 Error cloneAndEmitDebugMacro(); 415 416 // Clone input DIE entry. 417 std::pair<DIE *, TypeEntry *> 418 cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, 419 TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset, 420 std::optional<int64_t> FuncAddressAdjustment, 421 std::optional<int64_t> VarAddressAdjustment, 422 BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit); 423 424 // Clone and emit line table. 425 Error cloneAndEmitLineTable(Triple &TargetTriple); 426 427 /// Clone attribute location axpression. 428 void cloneDieAttrExpression(const DWARFExpression &InputExpression, 429 SmallVectorImpl<uint8_t> &OutputExpression, 430 SectionDescriptor &Section, 431 std::optional<int64_t> VarAddressAdjustment, 432 OffsetsPtrVector &PatchesOffsets); 433 434 /// Returns index(inside .debug_addr) of an address. 435 uint64_t getDebugAddrIndex(uint64_t Addr) { 436 return DebugAddrIndexMap.getValueIndex(Addr); 437 } 438 439 /// Returns directory and file from the line table by index. 440 std::optional<std::pair<StringRef, StringRef>> 441 getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue); 442 443 /// Returns directory and file from the line table by index. 444 std::optional<std::pair<StringRef, StringRef>> 445 getDirAndFilenameFromLineTable(uint64_t FileIdx); 446 447 /// \defgroup Helper methods to access OrigUnit. 448 /// 449 /// @{ 450 451 /// Returns paired compile unit from input DWARF. 452 DWARFUnit &getOrigUnit() const { 453 assert(OrigUnit != nullptr); 454 return *OrigUnit; 455 } 456 457 const DWARFDebugInfoEntry * 458 getFirstChildEntry(const DWARFDebugInfoEntry *Die) const { 459 assert(OrigUnit != nullptr); 460 return OrigUnit->getFirstChildEntry(Die); 461 } 462 463 const DWARFDebugInfoEntry * 464 getSiblingEntry(const DWARFDebugInfoEntry *Die) const { 465 assert(OrigUnit != nullptr); 466 return OrigUnit->getSiblingEntry(Die); 467 } 468 469 DWARFDie getParent(const DWARFDebugInfoEntry *Die) { 470 assert(OrigUnit != nullptr); 471 return OrigUnit->getParent(Die); 472 } 473 474 DWARFDie getDIEAtIndex(unsigned Index) { 475 assert(OrigUnit != nullptr); 476 return OrigUnit->getDIEAtIndex(Index); 477 } 478 479 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const { 480 assert(OrigUnit != nullptr); 481 return OrigUnit->getDebugInfoEntry(Index); 482 } 483 484 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { 485 assert(OrigUnit != nullptr); 486 return OrigUnit->getUnitDIE(ExtractUnitDIEOnly); 487 } 488 489 DWARFDie getDIE(const DWARFDebugInfoEntry *Die) { 490 assert(OrigUnit != nullptr); 491 return DWARFDie(OrigUnit, Die); 492 } 493 494 uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const { 495 assert(OrigUnit != nullptr); 496 return OrigUnit->getDIEIndex(Die); 497 } 498 499 uint32_t getDIEIndex(const DWARFDie &Die) const { 500 assert(OrigUnit != nullptr); 501 return OrigUnit->getDIEIndex(Die); 502 } 503 504 std::optional<DWARFFormValue> find(uint32_t DieIdx, 505 ArrayRef<dwarf::Attribute> Attrs) const { 506 assert(OrigUnit != nullptr); 507 return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs); 508 } 509 510 std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die, 511 ArrayRef<dwarf::Attribute> Attrs) const { 512 if (!Die) 513 return std::nullopt; 514 auto AbbrevDecl = Die->getAbbreviationDeclarationPtr(); 515 if (AbbrevDecl) { 516 for (auto Attr : Attrs) { 517 if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr, 518 *OrigUnit)) 519 return Value; 520 } 521 } 522 return std::nullopt; 523 } 524 525 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) { 526 return OrigUnit->getDIEIndexForOffset(Offset); 527 } 528 529 /// @} 530 531 /// \defgroup Methods used for reporting warnings and errors: 532 /// 533 /// @{ 534 535 void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) { 536 GlobalData.warn(Warning, getUnitName(), DIE); 537 } 538 539 void warn(Error Warning, const DWARFDie *DIE = nullptr) { 540 handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) { 541 GlobalData.warn(Info.message(), getUnitName(), DIE); 542 }); 543 } 544 545 void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) { 546 if (DieEntry != nullptr) { 547 DWARFDie DIE(&getOrigUnit(), DieEntry); 548 GlobalData.warn(Warning, getUnitName(), &DIE); 549 return; 550 } 551 552 GlobalData.warn(Warning, getUnitName()); 553 } 554 555 void error(const Twine &Err, const DWARFDie *DIE = nullptr) { 556 GlobalData.warn(Err, getUnitName(), DIE); 557 } 558 559 void error(Error Err, const DWARFDie *DIE = nullptr) { 560 handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) { 561 GlobalData.error(Info.message(), getUnitName(), DIE); 562 }); 563 } 564 565 /// @} 566 567 /// Save specified accelerator info \p Info. 568 void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) { 569 AcceleratorRecords.add(Info); 570 } 571 572 /// Enumerates all units accelerator records. 573 void 574 forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override { 575 AcceleratorRecords.forEach(Handler); 576 } 577 578 /// Output unit selector. 579 class OutputUnitVariantPtr { 580 public: 581 OutputUnitVariantPtr(CompileUnit *U); 582 OutputUnitVariantPtr(TypeUnit *U); 583 584 /// Accessor for common functionality. 585 DwarfUnit *operator->(); 586 587 bool isCompileUnit(); 588 589 bool isTypeUnit(); 590 591 /// Returns CompileUnit if applicable. 592 CompileUnit *getAsCompileUnit(); 593 594 /// Returns TypeUnit if applicable. 595 TypeUnit *getAsTypeUnit(); 596 597 protected: 598 PointerUnion<CompileUnit *, TypeUnit *> Ptr; 599 }; 600 601 private: 602 /// Navigate DWARF tree recursively and set die properties. 603 void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry, 604 bool IsODRUnavailableFunctionScope); 605 606 struct LinkedLocationExpressionsWithOffsetPatches { 607 DWARFLocationExpression Expression; 608 OffsetsPtrVector Patches; 609 }; 610 using LinkedLocationExpressionsVector = 611 SmallVector<LinkedLocationExpressionsWithOffsetPatches>; 612 613 /// Emit debug locations. 614 void emitLocations(DebugSectionKind LocationSectionKind); 615 616 /// Emit location list header. 617 uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection); 618 619 /// Emit location list fragment. 620 uint64_t emitLocListFragment( 621 const LinkedLocationExpressionsVector &LinkedLocationExpression, 622 SectionDescriptor &OutLocationSection); 623 624 /// Emit the .debug_addr section fragment for current unit. 625 Error emitDebugAddrSection(); 626 627 /// Emit .debug_aranges. 628 void emitAranges(AddressRanges &LinkedFunctionRanges); 629 630 /// Clone and emit .debug_ranges/.debug_rnglists. 631 void cloneAndEmitRangeList(DebugSectionKind RngSectionKind, 632 AddressRanges &LinkedFunctionRanges); 633 634 /// Emit range list header. 635 uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection); 636 637 /// Emit range list fragment. 638 void emitRangeListFragment(const AddressRanges &LinkedRanges, 639 SectionDescriptor &OutRangeSection); 640 641 /// Insert the new line info sequence \p Seq into the current 642 /// set of already linked line info \p Rows. 643 void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, 644 std::vector<DWARFDebugLine::Row> &Rows); 645 646 /// Emits body for both macro sections. 647 void emitMacroTableImpl(const DWARFDebugMacro *MacroTable, 648 uint64_t OffsetToMacroTable, bool hasDWARFv5Header); 649 650 /// Creates DIE which would be placed into the "Plain" compile unit. 651 DIE *createPlainDIEandCloneAttributes( 652 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator, 653 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment, 654 std::optional<int64_t> &VarAddressAdjustment); 655 656 /// Creates DIE which would be placed into the "Type" compile unit. 657 TypeEntry *createTypeDIEandCloneAttributes( 658 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator, 659 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit); 660 661 /// Create output DIE inside specified \p TypeDescriptor. 662 DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor, 663 DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag, 664 bool IsDeclaration, bool IsParentDeclaration); 665 666 /// Enumerate \p DieEntry children and assign names for them. 667 Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry, 668 SyntheticTypeNameBuilder &NameBuilder); 669 670 /// DWARFFile containing this compile unit. 671 DWARFFile &File; 672 673 /// Pointer to the paired compile unit from the input DWARF. 674 DWARFUnit *OrigUnit = nullptr; 675 676 /// The DW_AT_language of this unit. 677 std::optional<uint16_t> Language; 678 679 /// Line table for this unit. 680 const DWARFDebugLine::LineTable *LineTablePtr = nullptr; 681 682 /// Cached resolved paths from the line table. 683 /// The key is <UniqueUnitID, FileIdx>. 684 using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>; 685 ResolvedPathsMap ResolvedFullPaths; 686 StringMap<StringEntry *> ResolvedParentPaths; 687 688 /// Maps an address into the index inside .debug_addr section. 689 IndexedValuesMap<uint64_t> DebugAddrIndexMap; 690 691 std::unique_ptr<DependencyTracker> Dependencies; 692 693 /// \defgroup Data Members accessed asinchronously. 694 /// 695 /// @{ 696 OffsetToUnitTy getUnitFromOffset; 697 698 std::optional<uint64_t> LowPc; 699 uint64_t HighPc = 0; 700 701 /// Flag indicating whether type de-duplication is forbidden. 702 bool NoODR = true; 703 704 /// The ranges in that map are the PC ranges for functions in this unit, 705 /// associated with the PC offset to apply to the addresses to get 706 /// the linked address. 707 RangesTy Ranges; 708 std::mutex RangesMutex; 709 710 /// The DW_AT_low_pc of each DW_TAG_label. 711 using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>; 712 LabelMapTy Labels; 713 std::mutex LabelsMutex; 714 715 /// This field keeps current stage of overall compile unit processing. 716 std::atomic<Stage> Stage; 717 718 /// DIE info indexed by DIE index. 719 SmallVector<DIEInfo> DieInfoArray; 720 SmallVector<uint64_t> OutDieOffsetArray; 721 SmallVector<TypeEntry *> TypeEntries; 722 723 /// The list of accelerator records for this unit. 724 ArrayList<AccelInfo> AcceleratorRecords; 725 /// @} 726 }; 727 728 /// \returns list of attributes referencing type DIEs which might be 729 /// deduplicated. 730 /// Note: it does not include DW_AT_containing_type attribute to avoid 731 /// infinite recursion. 732 ArrayRef<dwarf::Attribute> getODRAttributes(); 733 734 } // end of namespace parallel 735 } // end of namespace dwarf_linker 736 } // end of namespace llvm 737 738 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H 739