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