DWARFLinkerCompileUnit.cpp 5.0 KB

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