1*1db9f3b2SDimitry Andric //===- DWARFLinkerCompileUnit.cpp -----------------------------------------===// 2*1db9f3b2SDimitry Andric // 3*1db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*1db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*1db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*1db9f3b2SDimitry Andric // 7*1db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 8*1db9f3b2SDimitry Andric 9*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h" 10*1db9f3b2SDimitry Andric #include "llvm/ADT/StringExtras.h" 11*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h" 12*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 14*1db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h" 15*1db9f3b2SDimitry Andric 16*1db9f3b2SDimitry Andric namespace llvm { 17*1db9f3b2SDimitry Andric 18*1db9f3b2SDimitry Andric using namespace dwarf_linker; 19*1db9f3b2SDimitry Andric using namespace dwarf_linker::classic; 20*1db9f3b2SDimitry Andric 21*1db9f3b2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 22*1db9f3b2SDimitry Andric LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() { 23*1db9f3b2SDimitry Andric llvm::errs() << "{\n"; 24*1db9f3b2SDimitry Andric llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n'; 25*1db9f3b2SDimitry Andric llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n'; 26*1db9f3b2SDimitry Andric llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n'; 27*1db9f3b2SDimitry Andric llvm::errs() << " ParentIdx: " << ParentIdx << '\n'; 28*1db9f3b2SDimitry Andric llvm::errs() << " Keep: " << Keep << '\n'; 29*1db9f3b2SDimitry Andric llvm::errs() << " InDebugMap: " << InDebugMap << '\n'; 30*1db9f3b2SDimitry Andric llvm::errs() << " Prune: " << Prune << '\n'; 31*1db9f3b2SDimitry Andric llvm::errs() << " Incomplete: " << Incomplete << '\n'; 32*1db9f3b2SDimitry Andric llvm::errs() << " InModuleScope: " << InModuleScope << '\n'; 33*1db9f3b2SDimitry Andric llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n'; 34*1db9f3b2SDimitry Andric llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n'; 35*1db9f3b2SDimitry Andric llvm::errs() << "}\n"; 36*1db9f3b2SDimitry Andric } 37*1db9f3b2SDimitry Andric #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 38*1db9f3b2SDimitry Andric 39*1db9f3b2SDimitry Andric /// Check if the DIE at \p Idx is in the scope of a function. 40*1db9f3b2SDimitry Andric static bool inFunctionScope(CompileUnit &U, unsigned Idx) { 41*1db9f3b2SDimitry Andric while (Idx) { 42*1db9f3b2SDimitry Andric if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram) 43*1db9f3b2SDimitry Andric return true; 44*1db9f3b2SDimitry Andric Idx = U.getInfo(Idx).ParentIdx; 45*1db9f3b2SDimitry Andric } 46*1db9f3b2SDimitry Andric return false; 47*1db9f3b2SDimitry Andric } 48*1db9f3b2SDimitry Andric 49*1db9f3b2SDimitry Andric uint16_t CompileUnit::getLanguage() { 50*1db9f3b2SDimitry Andric if (!Language) { 51*1db9f3b2SDimitry Andric DWARFDie CU = getOrigUnit().getUnitDIE(); 52*1db9f3b2SDimitry Andric Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0); 53*1db9f3b2SDimitry Andric } 54*1db9f3b2SDimitry Andric return Language; 55*1db9f3b2SDimitry Andric } 56*1db9f3b2SDimitry Andric 57*1db9f3b2SDimitry Andric StringRef CompileUnit::getSysRoot() { 58*1db9f3b2SDimitry Andric if (SysRoot.empty()) { 59*1db9f3b2SDimitry Andric DWARFDie CU = getOrigUnit().getUnitDIE(); 60*1db9f3b2SDimitry Andric SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str(); 61*1db9f3b2SDimitry Andric } 62*1db9f3b2SDimitry Andric return SysRoot; 63*1db9f3b2SDimitry Andric } 64*1db9f3b2SDimitry Andric 65*1db9f3b2SDimitry Andric void CompileUnit::markEverythingAsKept() { 66*1db9f3b2SDimitry Andric unsigned Idx = 0; 67*1db9f3b2SDimitry Andric 68*1db9f3b2SDimitry Andric for (auto &I : Info) { 69*1db9f3b2SDimitry Andric // Mark everything that wasn't explicit marked for pruning. 70*1db9f3b2SDimitry Andric I.Keep = !I.Prune; 71*1db9f3b2SDimitry Andric auto DIE = OrigUnit.getDIEAtIndex(Idx++); 72*1db9f3b2SDimitry Andric DWARFUnit *U = DIE.getDwarfUnit(); 73*1db9f3b2SDimitry Andric 74*1db9f3b2SDimitry Andric // Try to guess which DIEs must go to the accelerator tables. We do that 75*1db9f3b2SDimitry Andric // just for variables, because functions will be handled depending on 76*1db9f3b2SDimitry Andric // whether they carry a DW_AT_low_pc attribute or not. 77*1db9f3b2SDimitry Andric if (DIE.getTag() != dwarf::DW_TAG_variable && 78*1db9f3b2SDimitry Andric DIE.getTag() != dwarf::DW_TAG_constant) 79*1db9f3b2SDimitry Andric continue; 80*1db9f3b2SDimitry Andric 81*1db9f3b2SDimitry Andric std::optional<DWARFFormValue> Value; 82*1db9f3b2SDimitry Andric if (!(Value = DIE.find(dwarf::DW_AT_location))) { 83*1db9f3b2SDimitry Andric if ((Value = DIE.find(dwarf::DW_AT_const_value)) && 84*1db9f3b2SDimitry Andric !inFunctionScope(*this, I.ParentIdx)) 85*1db9f3b2SDimitry Andric I.InDebugMap = true; 86*1db9f3b2SDimitry Andric continue; 87*1db9f3b2SDimitry Andric } 88*1db9f3b2SDimitry Andric 89*1db9f3b2SDimitry Andric if (auto ExprLockBlock = Value->getAsBlock()) { 90*1db9f3b2SDimitry Andric // Parse 'exprloc' expression. 91*1db9f3b2SDimitry Andric DataExtractor Data(toStringRef(*ExprLockBlock), 92*1db9f3b2SDimitry Andric U->getContext().isLittleEndian(), 93*1db9f3b2SDimitry Andric U->getAddressByteSize()); 94*1db9f3b2SDimitry Andric DWARFExpression Expression(Data, U->getAddressByteSize(), 95*1db9f3b2SDimitry Andric U->getFormParams().Format); 96*1db9f3b2SDimitry Andric 97*1db9f3b2SDimitry Andric for (DWARFExpression::iterator It = Expression.begin(); 98*1db9f3b2SDimitry Andric (It != Expression.end()) && !I.InDebugMap; ++It) { 99*1db9f3b2SDimitry Andric DWARFExpression::iterator NextIt = It; 100*1db9f3b2SDimitry Andric ++NextIt; 101*1db9f3b2SDimitry Andric 102*1db9f3b2SDimitry Andric switch (It->getCode()) { 103*1db9f3b2SDimitry Andric case dwarf::DW_OP_const2u: 104*1db9f3b2SDimitry Andric case dwarf::DW_OP_const4u: 105*1db9f3b2SDimitry Andric case dwarf::DW_OP_const8u: 106*1db9f3b2SDimitry Andric case dwarf::DW_OP_const2s: 107*1db9f3b2SDimitry Andric case dwarf::DW_OP_const4s: 108*1db9f3b2SDimitry Andric case dwarf::DW_OP_const8s: 109*1db9f3b2SDimitry Andric if (NextIt == Expression.end() || 110*1db9f3b2SDimitry Andric NextIt->getCode() != dwarf::DW_OP_form_tls_address) 111*1db9f3b2SDimitry Andric break; 112*1db9f3b2SDimitry Andric [[fallthrough]]; 113*1db9f3b2SDimitry Andric case dwarf::DW_OP_constx: 114*1db9f3b2SDimitry Andric case dwarf::DW_OP_addr: 115*1db9f3b2SDimitry Andric case dwarf::DW_OP_addrx: 116*1db9f3b2SDimitry Andric I.InDebugMap = true; 117*1db9f3b2SDimitry Andric break; 118*1db9f3b2SDimitry Andric default: 119*1db9f3b2SDimitry Andric // Nothing to do. 120*1db9f3b2SDimitry Andric break; 121*1db9f3b2SDimitry Andric } 122*1db9f3b2SDimitry Andric } 123*1db9f3b2SDimitry Andric } 124*1db9f3b2SDimitry Andric } 125*1db9f3b2SDimitry Andric } 126*1db9f3b2SDimitry Andric 127*1db9f3b2SDimitry Andric uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) { 128*1db9f3b2SDimitry Andric NextUnitOffset = StartOffset; 129*1db9f3b2SDimitry Andric if (NewUnit) { 130*1db9f3b2SDimitry Andric NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size 131*1db9f3b2SDimitry Andric NextUnitOffset += NewUnit->getUnitDie().getSize(); 132*1db9f3b2SDimitry Andric } 133*1db9f3b2SDimitry Andric return NextUnitOffset; 134*1db9f3b2SDimitry Andric } 135*1db9f3b2SDimitry Andric 136*1db9f3b2SDimitry Andric /// Keep track of a forward cross-cu reference from this unit 137*1db9f3b2SDimitry Andric /// to \p Die that lives in \p RefUnit. 138*1db9f3b2SDimitry Andric void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, 139*1db9f3b2SDimitry Andric DeclContext *Ctxt, PatchLocation Attr) { 140*1db9f3b2SDimitry Andric ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); 141*1db9f3b2SDimitry Andric } 142*1db9f3b2SDimitry Andric 143*1db9f3b2SDimitry Andric void CompileUnit::fixupForwardReferences() { 144*1db9f3b2SDimitry Andric for (const auto &Ref : ForwardDIEReferences) { 145*1db9f3b2SDimitry Andric DIE *RefDie; 146*1db9f3b2SDimitry Andric const CompileUnit *RefUnit; 147*1db9f3b2SDimitry Andric PatchLocation Attr; 148*1db9f3b2SDimitry Andric DeclContext *Ctxt; 149*1db9f3b2SDimitry Andric std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref; 150*1db9f3b2SDimitry Andric if (Ctxt && Ctxt->hasCanonicalDIE()) { 151*1db9f3b2SDimitry Andric assert(Ctxt->getCanonicalDIEOffset() && 152*1db9f3b2SDimitry Andric "Canonical die offset is not set"); 153*1db9f3b2SDimitry Andric Attr.set(Ctxt->getCanonicalDIEOffset()); 154*1db9f3b2SDimitry Andric } else { 155*1db9f3b2SDimitry Andric assert(RefDie->getOffset() && "Referenced die offset is not set"); 156*1db9f3b2SDimitry Andric Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); 157*1db9f3b2SDimitry Andric } 158*1db9f3b2SDimitry Andric } 159*1db9f3b2SDimitry Andric } 160*1db9f3b2SDimitry Andric 161*1db9f3b2SDimitry Andric void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) { 162*1db9f3b2SDimitry Andric Labels.insert({LabelLowPc, PcOffset}); 163*1db9f3b2SDimitry Andric } 164*1db9f3b2SDimitry Andric 165*1db9f3b2SDimitry Andric void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, 166*1db9f3b2SDimitry Andric int64_t PcOffset) { 167*1db9f3b2SDimitry Andric Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset); 168*1db9f3b2SDimitry Andric if (LowPc) 169*1db9f3b2SDimitry Andric LowPc = std::min(*LowPc, FuncLowPc + PcOffset); 170*1db9f3b2SDimitry Andric else 171*1db9f3b2SDimitry Andric LowPc = FuncLowPc + PcOffset; 172*1db9f3b2SDimitry Andric this->HighPc = std::max(HighPc, FuncHighPc + PcOffset); 173*1db9f3b2SDimitry Andric } 174*1db9f3b2SDimitry Andric 175*1db9f3b2SDimitry Andric void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) { 176*1db9f3b2SDimitry Andric if (Die.getTag() == dwarf::DW_TAG_compile_unit) { 177*1db9f3b2SDimitry Andric UnitRangeAttribute = Attr; 178*1db9f3b2SDimitry Andric return; 179*1db9f3b2SDimitry Andric } 180*1db9f3b2SDimitry Andric 181*1db9f3b2SDimitry Andric RangeAttributes.emplace_back(Attr); 182*1db9f3b2SDimitry Andric } 183*1db9f3b2SDimitry Andric 184*1db9f3b2SDimitry Andric void CompileUnit::noteLocationAttribute(PatchLocation Attr) { 185*1db9f3b2SDimitry Andric LocationAttributes.emplace_back(Attr); 186*1db9f3b2SDimitry Andric } 187*1db9f3b2SDimitry Andric 188*1db9f3b2SDimitry Andric void CompileUnit::addNamespaceAccelerator(const DIE *Die, 189*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef Name) { 190*1db9f3b2SDimitry Andric Namespaces.emplace_back(Name, Die); 191*1db9f3b2SDimitry Andric } 192*1db9f3b2SDimitry Andric 193*1db9f3b2SDimitry Andric void CompileUnit::addObjCAccelerator(const DIE *Die, 194*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef Name, 195*1db9f3b2SDimitry Andric bool SkipPubSection) { 196*1db9f3b2SDimitry Andric ObjC.emplace_back(Name, Die, SkipPubSection); 197*1db9f3b2SDimitry Andric } 198*1db9f3b2SDimitry Andric 199*1db9f3b2SDimitry Andric void CompileUnit::addNameAccelerator(const DIE *Die, 200*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef Name, 201*1db9f3b2SDimitry Andric bool SkipPubSection) { 202*1db9f3b2SDimitry Andric Pubnames.emplace_back(Name, Die, SkipPubSection); 203*1db9f3b2SDimitry Andric } 204*1db9f3b2SDimitry Andric 205*1db9f3b2SDimitry Andric void CompileUnit::addTypeAccelerator(const DIE *Die, 206*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef Name, 207*1db9f3b2SDimitry Andric bool ObjcClassImplementation, 208*1db9f3b2SDimitry Andric uint32_t QualifiedNameHash) { 209*1db9f3b2SDimitry Andric Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation); 210*1db9f3b2SDimitry Andric } 211*1db9f3b2SDimitry Andric 212*1db9f3b2SDimitry Andric } // namespace llvm 213