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 12namespace llvm { 13 14/// Check if the DIE at \p Idx is in the scope of a function. 15static 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 24uint16_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 32StringRef 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 40void CompileUnit::markEverythingAsKept() { 41 unsigned Idx = 0; 42 43 setHasInterestingContent(); 44 45 for (auto &I : Info) { 46 // Mark everything that wasn't explicit marked for pruning. 47 I.Keep = !I.Prune; 48 auto DIE = OrigUnit.getDIEAtIndex(Idx++); 49 50 // Try to guess which DIEs must go to the accelerator tables. We do that 51 // just for variables, because functions will be handled depending on 52 // whether they carry a DW_AT_low_pc attribute or not. 53 if (DIE.getTag() != dwarf::DW_TAG_variable && 54 DIE.getTag() != dwarf::DW_TAG_constant) 55 continue; 56 57 Optional<DWARFFormValue> Value; 58 if (!(Value = DIE.find(dwarf::DW_AT_location))) { 59 if ((Value = DIE.find(dwarf::DW_AT_const_value)) && 60 !inFunctionScope(*this, I.ParentIdx)) 61 I.InDebugMap = true; 62 continue; 63 } 64 if (auto Block = Value->getAsBlock()) { 65 if (Block->size() > OrigUnit.getAddressByteSize() && 66 (*Block)[0] == dwarf::DW_OP_addr) 67 I.InDebugMap = true; 68 } 69 } 70} 71 72uint64_t CompileUnit::computeNextUnitOffset() { 73 NextUnitOffset = StartOffset; 74 if (NewUnit) { 75 NextUnitOffset += 11 /* Header size */; 76 NextUnitOffset += NewUnit->getUnitDie().getSize(); 77 } 78 return NextUnitOffset; 79} 80 81/// Keep track of a forward cross-cu reference from this unit 82/// to \p Die that lives in \p RefUnit. 83void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, 84 DeclContext *Ctxt, PatchLocation Attr) { 85 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); 86} 87 88void CompileUnit::fixupForwardReferences() { 89 for (const auto &Ref : ForwardDIEReferences) { 90 DIE *RefDie; 91 const CompileUnit *RefUnit; 92 PatchLocation Attr; 93 DeclContext *Ctxt; 94 std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref; 95 if (Ctxt && Ctxt->getCanonicalDIEOffset()) 96 Attr.set(Ctxt->getCanonicalDIEOffset()); 97 else 98 Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); 99 } 100} 101 102void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) { 103 Labels.insert({LabelLowPc, PcOffset}); 104} 105 106void 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 117void 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 124void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) { 125 LocationAttributes.emplace_back(Attr, PcOffset); 126} 127 128void CompileUnit::addNamespaceAccelerator(const DIE *Die, 129 DwarfStringPoolEntryRef Name) { 130 Namespaces.emplace_back(Name, Die); 131} 132 133void CompileUnit::addObjCAccelerator(const DIE *Die, 134 DwarfStringPoolEntryRef Name, 135 bool SkipPubSection) { 136 ObjC.emplace_back(Name, Die, SkipPubSection); 137} 138 139void CompileUnit::addNameAccelerator(const DIE *Die, 140 DwarfStringPoolEntryRef Name, 141 bool SkipPubSection) { 142 Pubnames.emplace_back(Name, Die, SkipPubSection); 143} 144 145void 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