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;
operator ()llvm::dsymutil::CFDeleter28 
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))) {
CFString(CFStringRef CFStr=nullptr)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()) {
GetLength() const51       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;
UTF8(CFStringRef CFStr,std::string & Str)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 
CFBundle(StringRef Path)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);
GetIdentifier() const96   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);
GetValueForInfoDictionaryKey(CFStringRef key) const103   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 
SetFromPath(StringRef Path)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