Home | History | Annotate | Download | only in dsymutil
      1 //===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "CompileUnit.h"
     11 #include "DeclContext.h"
     12 
     13 namespace llvm {
     14 namespace dsymutil {
     15 
     16 /// Check if the DIE at \p Idx is in the scope of a function.
     17 static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
     18   while (Idx) {
     19     if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
     20       return true;
     21     Idx = U.getInfo(Idx).ParentIdx;
     22   }
     23   return false;
     24 }
     25 
     26 void CompileUnit::markEverythingAsKept() {
     27   unsigned Idx = 0;
     28 
     29   setHasInterestingContent();
     30 
     31   for (auto &I : Info) {
     32     // Mark everything that wasn't explicit marked for pruning.
     33     I.Keep = !I.Prune;
     34     auto DIE = OrigUnit.getDIEAtIndex(Idx++);
     35 
     36     // Try to guess which DIEs must go to the accelerator tables. We do that
     37     // just for variables, because functions will be handled depending on
     38     // whether they carry a DW_AT_low_pc attribute or not.
     39     if (DIE.getTag() != dwarf::DW_TAG_variable &&
     40         DIE.getTag() != dwarf::DW_TAG_constant)
     41       continue;
     42 
     43     Optional<DWARFFormValue> Value;
     44     if (!(Value = DIE.find(dwarf::DW_AT_location))) {
     45       if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
     46           !inFunctionScope(*this, I.ParentIdx))
     47         I.InDebugMap = true;
     48       continue;
     49     }
     50     if (auto Block = Value->getAsBlock()) {
     51       if (Block->size() > OrigUnit.getAddressByteSize() &&
     52           (*Block)[0] == dwarf::DW_OP_addr)
     53         I.InDebugMap = true;
     54     }
     55   }
     56 }
     57 
     58 uint64_t CompileUnit::computeNextUnitOffset() {
     59   NextUnitOffset = StartOffset + 11 /* Header size */;
     60   // The root DIE might be null, meaning that the Unit had nothing to
     61   // contribute to the linked output. In that case, we will emit the
     62   // unit header without any actual DIE.
     63   if (NewUnit)
     64     NextUnitOffset += NewUnit->getUnitDie().getSize();
     65   return NextUnitOffset;
     66 }
     67 
     68 /// Keep track of a forward cross-cu reference from this unit
     69 /// to \p Die that lives in \p RefUnit.
     70 void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
     71                                        DeclContext *Ctxt, PatchLocation Attr) {
     72   ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
     73 }
     74 
     75 void CompileUnit::fixupForwardReferences() {
     76   for (const auto &Ref : ForwardDIEReferences) {
     77     DIE *RefDie;
     78     const CompileUnit *RefUnit;
     79     PatchLocation Attr;
     80     DeclContext *Ctxt;
     81     std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
     82     if (Ctxt && Ctxt->getCanonicalDIEOffset())
     83       Attr.set(Ctxt->getCanonicalDIEOffset());
     84     else
     85       Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
     86   }
     87 }
     88 
     89 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
     90   Labels.insert({LabelLowPc, PcOffset});
     91 }
     92 
     93 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
     94                                    int64_t PcOffset) {
     95   Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
     96   this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
     97   this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
     98 }
     99 
    100 void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
    101   if (Die.getTag() != dwarf::DW_TAG_compile_unit)
    102     RangeAttributes.push_back(Attr);
    103   else
    104     UnitRangeAttribute = Attr;
    105 }
    106 
    107 void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
    108   LocationAttributes.emplace_back(Attr, PcOffset);
    109 }
    110 
    111 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
    112                                           DwarfStringPoolEntryRef Name) {
    113   Namespaces.emplace_back(Name, Die);
    114 }
    115 
    116 void CompileUnit::addObjCAccelerator(const DIE *Die,
    117                                      DwarfStringPoolEntryRef Name,
    118                                      bool SkipPubSection) {
    119   ObjC.emplace_back(Name, Die, SkipPubSection);
    120 }
    121 
    122 void CompileUnit::addNameAccelerator(const DIE *Die,
    123                                      DwarfStringPoolEntryRef Name,
    124                                      bool SkipPubSection) {
    125   Pubnames.emplace_back(Name, Die, SkipPubSection);
    126 }
    127 
    128 void CompileUnit::addTypeAccelerator(const DIE *Die,
    129                                      DwarfStringPoolEntryRef Name,
    130                                      bool ObjcClassImplementation,
    131                                      uint32_t QualifiedNameHash) {
    132   Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
    133 }
    134 
    135 } // namespace dsymutil
    136 } // namespace llvm
    137