Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
35266 views
1
//===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
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/ExecutionEngine/Orc/DebugUtils.h"
10
11
#include "llvm/ExecutionEngine/Orc/Core.h"
12
#include "llvm/Support/CommandLine.h"
13
#include "llvm/Support/Debug.h"
14
#include "llvm/Support/FileSystem.h"
15
#include "llvm/Support/Format.h"
16
#include "llvm/Support/MemoryBuffer.h"
17
#include "llvm/Support/Path.h"
18
#include "llvm/Support/raw_ostream.h"
19
20
#define DEBUG_TYPE "orc"
21
22
using namespace llvm;
23
24
namespace {
25
26
#ifndef NDEBUG
27
28
cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
29
cl::desc("debug print hidden symbols defined by "
30
"materialization units"),
31
cl::Hidden);
32
33
cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
34
cl::desc("debug print callable symbols defined by "
35
"materialization units"),
36
cl::Hidden);
37
38
cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
39
cl::desc("debug print data symbols defined by "
40
"materialization units"),
41
cl::Hidden);
42
43
#endif // NDEBUG
44
45
// SetPrinter predicate that prints every element.
46
template <typename T> struct PrintAll {
47
bool operator()(const T &E) { return true; }
48
};
49
50
bool anyPrintSymbolOptionSet() {
51
#ifndef NDEBUG
52
return PrintHidden || PrintCallable || PrintData;
53
#else
54
return false;
55
#endif // NDEBUG
56
}
57
58
bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
59
#ifndef NDEBUG
60
// Bail out early if this is a hidden symbol and we're not printing hiddens.
61
if (!PrintHidden && !Flags.isExported())
62
return false;
63
64
// Return true if this is callable and we're printing callables.
65
if (PrintCallable && Flags.isCallable())
66
return true;
67
68
// Return true if this is data and we're printing data.
69
if (PrintData && !Flags.isCallable())
70
return true;
71
72
// otherwise return false.
73
return false;
74
#else
75
return false;
76
#endif // NDEBUG
77
}
78
79
// Prints a sequence of items, filtered by an user-supplied predicate.
80
template <typename Sequence,
81
typename Pred = PrintAll<typename Sequence::value_type>>
82
class SequencePrinter {
83
public:
84
SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
85
Pred ShouldPrint = Pred())
86
: S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
87
ShouldPrint(std::move(ShouldPrint)) {}
88
89
void printTo(llvm::raw_ostream &OS) const {
90
bool PrintComma = false;
91
OS << OpenSeq;
92
for (auto &E : S) {
93
if (ShouldPrint(E)) {
94
if (PrintComma)
95
OS << ',';
96
OS << ' ' << E;
97
PrintComma = true;
98
}
99
}
100
OS << ' ' << CloseSeq;
101
}
102
103
private:
104
const Sequence &S;
105
char OpenSeq;
106
char CloseSeq;
107
mutable Pred ShouldPrint;
108
};
109
110
template <typename Sequence, typename Pred>
111
SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
112
char CloseSeq, Pred P = Pred()) {
113
return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
114
}
115
116
// Render a SequencePrinter by delegating to its printTo method.
117
template <typename Sequence, typename Pred>
118
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
119
const SequencePrinter<Sequence, Pred> &Printer) {
120
Printer.printTo(OS);
121
return OS;
122
}
123
124
struct PrintSymbolFlagsMapElemsMatchingCLOpts {
125
bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
126
return flagsMatchCLOpts(KV.second);
127
}
128
};
129
130
struct PrintSymbolMapElemsMatchingCLOpts {
131
bool operator()(const orc::SymbolMap::value_type &KV) {
132
return flagsMatchCLOpts(KV.second.getFlags());
133
}
134
};
135
136
} // end anonymous namespace
137
138
namespace llvm {
139
namespace orc {
140
141
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
142
return OS << *Sym;
143
}
144
145
raw_ostream &operator<<(raw_ostream &OS, NonOwningSymbolStringPtr Sym) {
146
return OS << *Sym;
147
}
148
149
raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
150
return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
151
}
152
153
raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
154
return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
155
}
156
157
raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
158
return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
159
}
160
161
raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
162
if (Flags.hasError())
163
OS << "[*ERROR*]";
164
if (Flags.isCallable())
165
OS << "[Callable]";
166
else
167
OS << "[Data]";
168
if (Flags.isWeak())
169
OS << "[Weak]";
170
else if (Flags.isCommon())
171
OS << "[Common]";
172
173
if (!Flags.isExported())
174
OS << "[Hidden]";
175
176
return OS;
177
}
178
179
raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
180
return OS << Sym.getAddress() << " " << Sym.getFlags();
181
}
182
183
raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
184
return OS << "(\"" << KV.first << "\", " << KV.second << ")";
185
}
186
187
raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
188
return OS << "(\"" << KV.first << "\": " << KV.second << ")";
189
}
190
191
raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
192
return OS << printSequence(SymbolFlags, '{', '}',
193
PrintSymbolFlagsMapElemsMatchingCLOpts());
194
}
195
196
raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
197
return OS << printSequence(Symbols, '{', '}',
198
PrintSymbolMapElemsMatchingCLOpts());
199
}
200
201
raw_ostream &operator<<(raw_ostream &OS,
202
const SymbolDependenceMap::value_type &KV) {
203
return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
204
}
205
206
raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
207
return OS << printSequence(Deps, '{', '}',
208
PrintAll<SymbolDependenceMap::value_type>());
209
}
210
211
raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
212
OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
213
if (anyPrintSymbolOptionSet())
214
OS << ", " << MU.getSymbols();
215
return OS << ")";
216
}
217
218
raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
219
switch (K) {
220
case LookupKind::Static:
221
return OS << "Static";
222
case LookupKind::DLSym:
223
return OS << "DLSym";
224
}
225
llvm_unreachable("Invalid lookup kind");
226
}
227
228
raw_ostream &operator<<(raw_ostream &OS,
229
const JITDylibLookupFlags &JDLookupFlags) {
230
switch (JDLookupFlags) {
231
case JITDylibLookupFlags::MatchExportedSymbolsOnly:
232
return OS << "MatchExportedSymbolsOnly";
233
case JITDylibLookupFlags::MatchAllSymbols:
234
return OS << "MatchAllSymbols";
235
}
236
llvm_unreachable("Invalid JITDylib lookup flags");
237
}
238
239
raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
240
switch (LookupFlags) {
241
case SymbolLookupFlags::RequiredSymbol:
242
return OS << "RequiredSymbol";
243
case SymbolLookupFlags::WeaklyReferencedSymbol:
244
return OS << "WeaklyReferencedSymbol";
245
}
246
llvm_unreachable("Invalid symbol lookup flags");
247
}
248
249
raw_ostream &operator<<(raw_ostream &OS,
250
const SymbolLookupSet::value_type &KV) {
251
return OS << "(" << KV.first << ", " << KV.second << ")";
252
}
253
254
raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
255
return OS << printSequence(LookupSet, '{', '}',
256
PrintAll<SymbolLookupSet::value_type>());
257
}
258
259
raw_ostream &operator<<(raw_ostream &OS,
260
const JITDylibSearchOrder &SearchOrder) {
261
OS << "[";
262
if (!SearchOrder.empty()) {
263
assert(SearchOrder.front().first &&
264
"JITDylibList entries must not be null");
265
OS << " (\"" << SearchOrder.front().first->getName() << "\", "
266
<< SearchOrder.begin()->second << ")";
267
for (auto &KV : llvm::drop_begin(SearchOrder)) {
268
assert(KV.first && "JITDylibList entries must not be null");
269
OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
270
}
271
}
272
OS << " ]";
273
return OS;
274
}
275
276
raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
277
OS << "{";
278
for (auto &KV : Aliases)
279
OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
280
<< KV.second.AliasFlags;
281
OS << " }";
282
return OS;
283
}
284
285
raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
286
switch (S) {
287
case SymbolState::Invalid:
288
return OS << "Invalid";
289
case SymbolState::NeverSearched:
290
return OS << "Never-Searched";
291
case SymbolState::Materializing:
292
return OS << "Materializing";
293
case SymbolState::Resolved:
294
return OS << "Resolved";
295
case SymbolState::Emitted:
296
return OS << "Emitted";
297
case SymbolState::Ready:
298
return OS << "Ready";
299
}
300
llvm_unreachable("Invalid state");
301
}
302
303
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
304
std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
305
SmallVector<std::pair<StringRef, int>, 0> Vec;
306
for (auto &KV : SSP.Pool)
307
Vec.emplace_back(KV.first(), KV.second);
308
llvm::sort(Vec, less_first());
309
for (auto &[K, V] : Vec)
310
OS << K << ": " << V << "\n";
311
return OS;
312
}
313
314
DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
315
: DumpDir(std::move(DumpDir)),
316
IdentifierOverride(std::move(IdentifierOverride)) {
317
318
/// Discard any trailing separators.
319
while (!this->DumpDir.empty() &&
320
sys::path::is_separator(this->DumpDir.back()))
321
this->DumpDir.pop_back();
322
}
323
324
Expected<std::unique_ptr<MemoryBuffer>>
325
DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
326
size_t Idx = 1;
327
328
std::string DumpPathStem;
329
raw_string_ostream(DumpPathStem)
330
<< DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
331
332
std::string DumpPath = DumpPathStem + ".o";
333
while (sys::fs::exists(DumpPath)) {
334
DumpPath.clear();
335
raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
336
}
337
338
LLVM_DEBUG({
339
dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
340
<< " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
341
<< DumpPath << "\n";
342
});
343
344
std::error_code EC;
345
raw_fd_ostream DumpStream(DumpPath, EC);
346
if (EC)
347
return errorCodeToError(EC);
348
DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
349
350
return std::move(Obj);
351
}
352
353
StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
354
if (!IdentifierOverride.empty())
355
return IdentifierOverride;
356
StringRef Identifier = B.getBufferIdentifier();
357
Identifier.consume_back(".o");
358
return Identifier;
359
}
360
361
} // End namespace orc.
362
} // End namespace llvm.
363
364