DWARFLinkerCompileUnit.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //===- DWARFLinkerCompileUnit.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. #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
  9. #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
  10. #include "llvm/Support/FormatVariadic.h"
  11. namespace llvm {
  12. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  13. LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
  14. llvm::errs() << "{\n";
  15. llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n';
  16. llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
  17. llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n';
  18. llvm::errs() << " ParentIdx: " << ParentIdx << '\n';
  19. llvm::errs() << " Keep: " << Keep << '\n';
  20. llvm::errs() << " InDebugMap: " << InDebugMap << '\n';
  21. llvm::errs() << " Prune: " << Prune << '\n';
  22. llvm::errs() << " Incomplete: " << Incomplete << '\n';
  23. llvm::errs() << " InModuleScope: " << InModuleScope << '\n';
  24. llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n';
  25. llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n';
  26. llvm::errs() << "}\n";
  27. }
  28. #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  29. /// Check if the DIE at \p Idx is in the scope of a function.
  30. static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
  31. while (Idx) {
  32. if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
  33. return true;
  34. Idx = U.getInfo(Idx).ParentIdx;
  35. }
  36. return false;
  37. }
  38. uint16_t CompileUnit::getLanguage() {
  39. if (!Language) {
  40. DWARFDie CU = getOrigUnit().getUnitDIE();
  41. Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
  42. }
  43. return Language;
  44. }
  45. StringRef CompileUnit::getSysRoot() {
  46. if (SysRoot.empty()) {
  47. DWARFDie CU = getOrigUnit().getUnitDIE();
  48. SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
  49. }
  50. return SysRoot;
  51. }
  52. void CompileUnit::markEverythingAsKept() {
  53. unsigned Idx = 0;
  54. for (auto &I : Info) {
  55. // Mark everything that wasn't explicit marked for pruning.
  56. I.Keep = !I.Prune;
  57. auto DIE = OrigUnit.getDIEAtIndex(Idx++);
  58. // Try to guess which DIEs must go to the accelerator tables. We do that
  59. // just for variables, because functions will be handled depending on
  60. // whether they carry a DW_AT_low_pc attribute or not.
  61. if (DIE.getTag() != dwarf::DW_TAG_variable &&
  62. DIE.getTag() != dwarf::DW_TAG_constant)
  63. continue;
  64. std::optional<DWARFFormValue> Value;
  65. if (!(Value = DIE.find(dwarf::DW_AT_location))) {
  66. if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
  67. !inFunctionScope(*this, I.ParentIdx))
  68. I.InDebugMap = true;
  69. continue;
  70. }
  71. if (auto Block = Value->getAsBlock()) {
  72. if (Block->size() > OrigUnit.getAddressByteSize() &&
  73. (*Block)[0] == dwarf::DW_OP_addr)
  74. I.InDebugMap = true;
  75. }
  76. }
  77. }
  78. uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
  79. NextUnitOffset = StartOffset;
  80. if (NewUnit) {
  81. NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
  82. NextUnitOffset += NewUnit->getUnitDie().getSize();
  83. }
  84. return NextUnitOffset;
  85. }
  86. /// Keep track of a forward cross-cu reference from this unit
  87. /// to \p Die that lives in \p RefUnit.
  88. void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
  89. DeclContext *Ctxt, PatchLocation Attr) {
  90. ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
  91. }
  92. void CompileUnit::fixupForwardReferences() {
  93. for (const auto &Ref : ForwardDIEReferences) {
  94. DIE *RefDie;
  95. const CompileUnit *RefUnit;
  96. PatchLocation Attr;
  97. DeclContext *Ctxt;
  98. std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
  99. if (Ctxt && Ctxt->hasCanonicalDIE()) {
  100. assert(Ctxt->getCanonicalDIEOffset() &&
  101. "Canonical die offset is not set");
  102. Attr.set(Ctxt->getCanonicalDIEOffset());
  103. } else {
  104. assert(RefDie->getOffset() && "Referenced die offset is not set");
  105. Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
  106. }
  107. }
  108. }
  109. void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
  110. Labels.insert({LabelLowPc, PcOffset});
  111. }
  112. void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
  113. int64_t PcOffset) {
  114. Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
  115. if (LowPc)
  116. LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
  117. else
  118. LowPc = FuncLowPc + PcOffset;
  119. this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
  120. }
  121. void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
  122. if (Die.getTag() != dwarf::DW_TAG_compile_unit)
  123. RangeAttributes.push_back(Attr);
  124. else
  125. UnitRangeAttribute = Attr;
  126. }
  127. void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
  128. LocationAttributes.emplace_back(Attr, PcOffset);
  129. }
  130. void CompileUnit::addNamespaceAccelerator(const DIE *Die,
  131. DwarfStringPoolEntryRef Name) {
  132. Namespaces.emplace_back(Name, Die);
  133. }
  134. void CompileUnit::addObjCAccelerator(const DIE *Die,
  135. DwarfStringPoolEntryRef Name,
  136. bool SkipPubSection) {
  137. ObjC.emplace_back(Name, Die, SkipPubSection);
  138. }
  139. void CompileUnit::addNameAccelerator(const DIE *Die,
  140. DwarfStringPoolEntryRef Name,
  141. bool SkipPubSection) {
  142. Pubnames.emplace_back(Name, Die, SkipPubSection);
  143. }
  144. void CompileUnit::addTypeAccelerator(const DIE *Die,
  145. DwarfStringPoolEntryRef Name,
  146. bool ObjcClassImplementation,
  147. uint32_t QualifiedNameHash) {
  148. Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
  149. }
  150. } // namespace llvm