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.
inFunctionScope(CompileUnit & U,unsigned Idx)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
markEverythingAsKept()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
computeNextUnitOffset()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.
noteForwardReference(DIE * Die,const CompileUnit * RefUnit,DeclContext * Ctxt,PatchLocation Attr)70 void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
71 DeclContext *Ctxt, PatchLocation Attr) {
72 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
73 }
74
fixupForwardReferences()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
addLabelLowPc(uint64_t LabelLowPc,int64_t PcOffset)89 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
90 Labels.insert({LabelLowPc, PcOffset});
91 }
92
addFunctionRange(uint64_t FuncLowPc,uint64_t FuncHighPc,int64_t PcOffset)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
noteRangeAttribute(const DIE & Die,PatchLocation Attr)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
noteLocationAttribute(PatchLocation Attr,int64_t PcOffset)107 void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
108 LocationAttributes.emplace_back(Attr, PcOffset);
109 }
110
addNamespaceAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name)111 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
112 DwarfStringPoolEntryRef Name) {
113 Namespaces.emplace_back(Name, Die);
114 }
115
addObjCAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool SkipPubSection)116 void CompileUnit::addObjCAccelerator(const DIE *Die,
117 DwarfStringPoolEntryRef Name,
118 bool SkipPubSection) {
119 ObjC.emplace_back(Name, Die, SkipPubSection);
120 }
121
addNameAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool SkipPubSection)122 void CompileUnit::addNameAccelerator(const DIE *Die,
123 DwarfStringPoolEntryRef Name,
124 bool SkipPubSection) {
125 Pubnames.emplace_back(Name, Die, SkipPubSection);
126 }
127
addTypeAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool ObjcClassImplementation,uint32_t QualifiedNameHash)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