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 405 cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple, 406 TypeUnit *ArtificialTypeUnit); 407 408 /// Clone and emit debug locations(.debug_loc/.debug_loclists). 409 Error cloneAndEmitDebugLocations(); 410 411 /// Clone and emit ranges. 412 Error cloneAndEmitRanges(); 413 414 /// Clone and emit debug macros(.debug_macinfo/.debug_macro). 415 Error cloneAndEmitDebugMacro(); 416 417 // Clone input DIE entry. 418 std::pair<DIE *, TypeEntry *> 419 cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, 420 TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset, 421 std::optional<int64_t> FuncAddressAdjustment, 422 std::optional<int64_t> VarAddressAdjustment, 423 BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit); 424 425 // Clone and emit line table. 426 Error cloneAndEmitLineTable(const Triple &TargetTriple); 427 428 /// Clone attribute location axpression. 429 void cloneDieAttrExpression(const DWARFExpression &InputExpression, 430 SmallVectorImpl<uint8_t> &OutputExpression, 431 SectionDescriptor &Section, 432 std::optional<int64_t> VarAddressAdjustment, 433 OffsetsPtrVector &PatchesOffsets); 434 435 /// Returns index(inside .debug_addr) of an address. 436 uint64_t getDebugAddrIndex(uint64_t Addr) { 437 return DebugAddrIndexMap.getValueIndex(Addr); 438 } 439 440 /// Returns directory and file from the line table by index. 441 std::optional<std::pair<StringRef, StringRef>> 442 getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue); 443 444 /// Returns directory and file from the line table by index. 445 std::optional<std::pair<StringRef, StringRef>> 446 getDirAndFilenameFromLineTable(uint64_t FileIdx); 447 448 /// \defgroup Helper methods to access OrigUnit. 449 /// 450 /// @{ 451 452 /// Returns paired compile unit from input DWARF. 453 DWARFUnit &getOrigUnit() const { 454 assert(OrigUnit != nullptr); 455 return *OrigUnit; 456 } 457 458 const DWARFDebugInfoEntry * 459 getFirstChildEntry(const DWARFDebugInfoEntry *Die) const { 460 assert(OrigUnit != nullptr); 461 return OrigUnit->getFirstChildEntry(Die); 462 } 463 464 const DWARFDebugInfoEntry * 465 getSiblingEntry(const DWARFDebugInfoEntry *Die) const { 466 assert(OrigUnit != nullptr); 467 return OrigUnit->getSiblingEntry(Die); 468 } 469 470 DWARFDie getParent(const DWARFDebugInfoEntry *Die) { 471 assert(OrigUnit != nullptr); 472 return OrigUnit->getParent(Die); 473 } 474 475 DWARFDie getDIEAtIndex(unsigned Index) { 476 assert(OrigUnit != nullptr); 477 return OrigUnit->getDIEAtIndex(Index); 478 } 479 480 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const { 481 assert(OrigUnit != nullptr); 482 return OrigUnit->getDebugInfoEntry(Index); 483 } 484 485 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { 486 assert(OrigUnit != nullptr); 487 return OrigUnit->getUnitDIE(ExtractUnitDIEOnly); 488 } 489 490 DWARFDie getDIE(const DWARFDebugInfoEntry *Die) { 491 assert(OrigUnit != nullptr); 492 return DWARFDie(OrigUnit, Die); 493 } 494 495 uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const { 496 assert(OrigUnit != nullptr); 497 return OrigUnit->getDIEIndex(Die); 498 } 499 500 uint32_t getDIEIndex(const DWARFDie &Die) const { 501 assert(OrigUnit != nullptr); 502 return OrigUnit->getDIEIndex(Die); 503 } 504 505 std::optional<DWARFFormValue> find(uint32_t DieIdx, 506 ArrayRef<dwarf::Attribute> Attrs) const { 507 assert(OrigUnit != nullptr); 508 return find(OrigUnit->getDebugInfoEntry(DieIdx), Attrs); 509 } 510 511 std::optional<DWARFFormValue> find(const DWARFDebugInfoEntry *Die, 512 ArrayRef<dwarf::Attribute> Attrs) const { 513 if (!Die) 514 return std::nullopt; 515 auto AbbrevDecl = Die->getAbbreviationDeclarationPtr(); 516 if (AbbrevDecl) { 517 for (auto Attr : Attrs) { 518 if (auto Value = AbbrevDecl->getAttributeValue(Die->getOffset(), Attr, 519 *OrigUnit)) 520 return Value; 521 } 522 } 523 return std::nullopt; 524 } 525 526 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) { 527 return OrigUnit->getDIEIndexForOffset(Offset); 528 } 529 530 /// @} 531 532 /// \defgroup Methods used for reporting warnings and errors: 533 /// 534 /// @{ 535 536 void warn(const Twine &Warning, const DWARFDie *DIE = nullptr) { 537 GlobalData.warn(Warning, getUnitName(), DIE); 538 } 539 540 void warn(Error Warning, const DWARFDie *DIE = nullptr) { 541 handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) { 542 GlobalData.warn(Info.message(), getUnitName(), DIE); 543 }); 544 } 545 546 void warn(const Twine &Warning, const DWARFDebugInfoEntry *DieEntry) { 547 if (DieEntry != nullptr) { 548 DWARFDie DIE(&getOrigUnit(), DieEntry); 549 GlobalData.warn(Warning, getUnitName(), &DIE); 550 return; 551 } 552 553 GlobalData.warn(Warning, getUnitName()); 554 } 555 556 void error(const Twine &Err, const DWARFDie *DIE = nullptr) { 557 GlobalData.warn(Err, getUnitName(), DIE); 558 } 559 560 void error(Error Err, const DWARFDie *DIE = nullptr) { 561 handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) { 562 GlobalData.error(Info.message(), getUnitName(), DIE); 563 }); 564 } 565 566 /// @} 567 568 /// Save specified accelerator info \p Info. 569 void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) { 570 AcceleratorRecords.add(Info); 571 } 572 573 /// Enumerates all units accelerator records. 574 void 575 forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override { 576 AcceleratorRecords.forEach(Handler); 577 } 578 579 /// Output unit selector. 580 class OutputUnitVariantPtr { 581 public: 582 OutputUnitVariantPtr(CompileUnit *U); 583 OutputUnitVariantPtr(TypeUnit *U); 584 585 /// Accessor for common functionality. 586 DwarfUnit *operator->(); 587 588 bool isCompileUnit(); 589 590 bool isTypeUnit(); 591 592 /// Returns CompileUnit if applicable. 593 CompileUnit *getAsCompileUnit(); 594 595 /// Returns TypeUnit if applicable. 596 TypeUnit *getAsTypeUnit(); 597 598 protected: 599 PointerUnion<CompileUnit *, TypeUnit *> Ptr; 600 }; 601 602 private: 603 /// Navigate DWARF tree recursively and set die properties. 604 void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry, 605 bool IsODRUnavailableFunctionScope); 606 607 struct LinkedLocationExpressionsWithOffsetPatches { 608 DWARFLocationExpression Expression; 609 OffsetsPtrVector Patches; 610 }; 611 using LinkedLocationExpressionsVector = 612 SmallVector<LinkedLocationExpressionsWithOffsetPatches>; 613 614 /// Emit debug locations. 615 void emitLocations(DebugSectionKind LocationSectionKind); 616 617 /// Emit location list header. 618 uint64_t emitLocListHeader(SectionDescriptor &OutLocationSection); 619 620 /// Emit location list fragment. 621 uint64_t emitLocListFragment( 622 const LinkedLocationExpressionsVector &LinkedLocationExpression, 623 SectionDescriptor &OutLocationSection); 624 625 /// Emit the .debug_addr section fragment for current unit. 626 Error emitDebugAddrSection(); 627 628 /// Emit .debug_aranges. 629 void emitAranges(AddressRanges &LinkedFunctionRanges); 630 631 /// Clone and emit .debug_ranges/.debug_rnglists. 632 void cloneAndEmitRangeList(DebugSectionKind RngSectionKind, 633 AddressRanges &LinkedFunctionRanges); 634 635 /// Emit range list header. 636 uint64_t emitRangeListHeader(SectionDescriptor &OutRangeSection); 637 638 /// Emit range list fragment. 639 void emitRangeListFragment(const AddressRanges &LinkedRanges, 640 SectionDescriptor &OutRangeSection); 641 642 /// Insert the new line info sequence \p Seq into the current 643 /// set of already linked line info \p Rows. 644 void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, 645 std::vector<DWARFDebugLine::Row> &Rows); 646 647 /// Emits body for both macro sections. 648 void emitMacroTableImpl(const DWARFDebugMacro *MacroTable, 649 uint64_t OffsetToMacroTable, bool hasDWARFv5Header); 650 651 /// Creates DIE which would be placed into the "Plain" compile unit. 652 DIE *createPlainDIEandCloneAttributes( 653 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator, 654 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment, 655 std::optional<int64_t> &VarAddressAdjustment); 656 657 /// Creates DIE which would be placed into the "Type" compile unit. 658 TypeEntry *createTypeDIEandCloneAttributes( 659 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator, 660 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit); 661 662 /// Create output DIE inside specified \p TypeDescriptor. 663 DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor, 664 DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag, 665 bool IsDeclaration, bool IsParentDeclaration); 666 667 /// Enumerate \p DieEntry children and assign names for them. 668 Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry, 669 SyntheticTypeNameBuilder &NameBuilder); 670 671 /// DWARFFile containing this compile unit. 672 DWARFFile &File; 673 674 /// Pointer to the paired compile unit from the input DWARF. 675 DWARFUnit *OrigUnit = nullptr; 676 677 /// The DW_AT_language of this unit. 678 std::optional<uint16_t> Language; 679 680 /// Line table for this unit. 681 const DWARFDebugLine::LineTable *LineTablePtr = nullptr; 682 683 /// Cached resolved paths from the line table. 684 /// The key is <UniqueUnitID, FileIdx>. 685 using ResolvedPathsMap = DenseMap<unsigned, StringEntry *>; 686 ResolvedPathsMap ResolvedFullPaths; 687 StringMap<StringEntry *> ResolvedParentPaths; 688 689 /// Maps an address into the index inside .debug_addr section. 690 IndexedValuesMap<uint64_t> DebugAddrIndexMap; 691 692 std::unique_ptr<DependencyTracker> Dependencies; 693 694 /// \defgroup Data Members accessed asinchronously. 695 /// 696 /// @{ 697 OffsetToUnitTy getUnitFromOffset; 698 699 std::optional<uint64_t> LowPc; 700 uint64_t HighPc = 0; 701 702 /// Flag indicating whether type de-duplication is forbidden. 703 bool NoODR = true; 704 705 /// The ranges in that map are the PC ranges for functions in this unit, 706 /// associated with the PC offset to apply to the addresses to get 707 /// the linked address. 708 RangesTy Ranges; 709 std::mutex RangesMutex; 710 711 /// The DW_AT_low_pc of each DW_TAG_label. 712 using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>; 713 LabelMapTy Labels; 714 std::mutex LabelsMutex; 715 716 /// This field keeps current stage of overall compile unit processing. 717 std::atomic<Stage> Stage; 718 719 /// DIE info indexed by DIE index. 720 SmallVector<DIEInfo> DieInfoArray; 721 SmallVector<uint64_t> OutDieOffsetArray; 722 SmallVector<TypeEntry *> TypeEntries; 723 724 /// The list of accelerator records for this unit. 725 ArrayList<AccelInfo> AcceleratorRecords; 726 /// @} 727 }; 728 729 /// \returns list of attributes referencing type DIEs which might be 730 /// deduplicated. 731 /// Note: it does not include DW_AT_containing_type attribute to avoid 732 /// infinite recursion. 733 ArrayRef<dwarf::Attribute> getODRAttributes(); 734 735 } // end of namespace parallel 736 } // end of namespace dwarf_linker 737 } // end of namespace llvm 738 739 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H 740