Home | History | Annotate | Line # | Download | only in DWARFLinker
      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 StringRef 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 
     40 void 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 
     72 uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
     73   NextUnitOffset = StartOffset;
     74   if (NewUnit) {
     75     NextUnitOffset += (DwarfVersion >= 5) ? 12 : 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.
     83 void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
     84                                        DeclContext *Ctxt, PatchLocation Attr) {
     85   ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
     86 }
     87 
     88 void 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 
    102 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
    103   Labels.insert({LabelLowPc, PcOffset});
    104 }
    105 
    106 void 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 
    117 void 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 
    124 void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
    125   LocationAttributes.emplace_back(Attr, PcOffset);
    126 }
    127 
    128 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
    129                                           DwarfStringPoolEntryRef Name) {
    130   Namespaces.emplace_back(Name, Die);
    131 }
    132 
    133 void CompileUnit::addObjCAccelerator(const DIE *Die,
    134                                      DwarfStringPoolEntryRef Name,
    135                                      bool SkipPubSection) {
    136   ObjC.emplace_back(Name, Die, SkipPubSection);
    137 }
    138 
    139 void CompileUnit::addNameAccelerator(const DIE *Die,
    140                                      DwarfStringPoolEntryRef Name,
    141                                      bool SkipPubSection) {
    142   Pubnames.emplace_back(Name, Die, SkipPubSection);
    143 }
    144 
    145 void 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