Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
35292 views
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/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/DWARFExpression.h"
14
#include "llvm/Support/FormatVariadic.h"
15
16
namespace llvm {
17
18
using namespace dwarf_linker;
19
using namespace dwarf_linker::classic;
20
21
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
22
LLVM_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.
40
static 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
49
uint16_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
57
StringRef 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
65
void 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 that
75
// just for variables, because functions will be handled depending on
76
// 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
127
uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
128
NextUnitOffset = StartOffset;
129
if (NewUnit) {
130
NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
131
NextUnitOffset += NewUnit->getUnitDie().getSize();
132
}
133
return NextUnitOffset;
134
}
135
136
/// Keep track of a forward cross-cu reference from this unit
137
/// to \p Die that lives in \p RefUnit.
138
void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
139
DeclContext *Ctxt, PatchLocation Attr) {
140
ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
141
}
142
143
void 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
161
void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
162
Labels.insert({LabelLowPc, PcOffset});
163
}
164
165
void 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
else
171
LowPc = FuncLowPc + PcOffset;
172
this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
173
}
174
175
void 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
184
void CompileUnit::noteLocationAttribute(PatchLocation Attr) {
185
LocationAttributes.emplace_back(Attr);
186
}
187
188
void CompileUnit::addNamespaceAccelerator(const DIE *Die,
189
DwarfStringPoolEntryRef Name) {
190
Namespaces.emplace_back(Name, Die);
191
}
192
193
void CompileUnit::addObjCAccelerator(const DIE *Die,
194
DwarfStringPoolEntryRef Name,
195
bool SkipPubSection) {
196
ObjC.emplace_back(Name, Die, SkipPubSection);
197
}
198
199
void CompileUnit::addNameAccelerator(const DIE *Die,
200
DwarfStringPoolEntryRef Name,
201
bool SkipPubSection) {
202
Pubnames.emplace_back(Name, Die, SkipPubSection);
203
}
204
205
void CompileUnit::addTypeAccelerator(const DIE *Die,
206
DwarfStringPoolEntryRef Name,
207
bool ObjcClassImplementation,
208
uint32_t QualifiedNameHash) {
209
Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
210
}
211
212
} // namespace llvm
213
214