brintos

brintos / llvm-project-archived public Read only

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