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