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