xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1480093f4SDimitry Andric //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric 
9480093f4SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
10*5ffd83dbSDimitry Andric 
11*5ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
12*5ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
13480093f4SDimitry Andric #include "llvm/Support/Debug.h"
14*5ffd83dbSDimitry Andric #include "llvm/Support/FileSystem.h"
15*5ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
16480093f4SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
17480093f4SDimitry Andric #include "llvm/Support/Path.h"
18480093f4SDimitry Andric #include "llvm/Support/raw_ostream.h"
19480093f4SDimitry Andric 
20480093f4SDimitry Andric #define DEBUG_TYPE "orc"
21480093f4SDimitry Andric 
22*5ffd83dbSDimitry Andric using namespace llvm;
23*5ffd83dbSDimitry Andric 
24*5ffd83dbSDimitry Andric namespace {
25*5ffd83dbSDimitry Andric 
26*5ffd83dbSDimitry Andric #ifndef NDEBUG
27*5ffd83dbSDimitry Andric 
28*5ffd83dbSDimitry Andric cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
29*5ffd83dbSDimitry Andric                           cl::desc("debug print hidden symbols defined by "
30*5ffd83dbSDimitry Andric                                    "materialization units"),
31*5ffd83dbSDimitry Andric                           cl::Hidden);
32*5ffd83dbSDimitry Andric 
33*5ffd83dbSDimitry Andric cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
34*5ffd83dbSDimitry Andric                             cl::desc("debug print callable symbols defined by "
35*5ffd83dbSDimitry Andric                                      "materialization units"),
36*5ffd83dbSDimitry Andric                             cl::Hidden);
37*5ffd83dbSDimitry Andric 
38*5ffd83dbSDimitry Andric cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
39*5ffd83dbSDimitry Andric                         cl::desc("debug print data symbols defined by "
40*5ffd83dbSDimitry Andric                                  "materialization units"),
41*5ffd83dbSDimitry Andric                         cl::Hidden);
42*5ffd83dbSDimitry Andric 
43*5ffd83dbSDimitry Andric #endif // NDEBUG
44*5ffd83dbSDimitry Andric 
45*5ffd83dbSDimitry Andric // SetPrinter predicate that prints every element.
46*5ffd83dbSDimitry Andric template <typename T> struct PrintAll {
47*5ffd83dbSDimitry Andric   bool operator()(const T &E) { return true; }
48*5ffd83dbSDimitry Andric };
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric bool anyPrintSymbolOptionSet() {
51*5ffd83dbSDimitry Andric #ifndef NDEBUG
52*5ffd83dbSDimitry Andric   return PrintHidden || PrintCallable || PrintData;
53*5ffd83dbSDimitry Andric #else
54*5ffd83dbSDimitry Andric   return false;
55*5ffd83dbSDimitry Andric #endif // NDEBUG
56*5ffd83dbSDimitry Andric }
57*5ffd83dbSDimitry Andric 
58*5ffd83dbSDimitry Andric bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
59*5ffd83dbSDimitry Andric #ifndef NDEBUG
60*5ffd83dbSDimitry Andric   // Bail out early if this is a hidden symbol and we're not printing hiddens.
61*5ffd83dbSDimitry Andric   if (!PrintHidden && !Flags.isExported())
62*5ffd83dbSDimitry Andric     return false;
63*5ffd83dbSDimitry Andric 
64*5ffd83dbSDimitry Andric   // Return true if this is callable and we're printing callables.
65*5ffd83dbSDimitry Andric   if (PrintCallable && Flags.isCallable())
66*5ffd83dbSDimitry Andric     return true;
67*5ffd83dbSDimitry Andric 
68*5ffd83dbSDimitry Andric   // Return true if this is data and we're printing data.
69*5ffd83dbSDimitry Andric   if (PrintData && !Flags.isCallable())
70*5ffd83dbSDimitry Andric     return true;
71*5ffd83dbSDimitry Andric 
72*5ffd83dbSDimitry Andric   // otherwise return false.
73*5ffd83dbSDimitry Andric   return false;
74*5ffd83dbSDimitry Andric #else
75*5ffd83dbSDimitry Andric   return false;
76*5ffd83dbSDimitry Andric #endif // NDEBUG
77*5ffd83dbSDimitry Andric }
78*5ffd83dbSDimitry Andric 
79*5ffd83dbSDimitry Andric // Prints a sequence of items, filtered by an user-supplied predicate.
80*5ffd83dbSDimitry Andric template <typename Sequence,
81*5ffd83dbSDimitry Andric           typename Pred = PrintAll<typename Sequence::value_type>>
82*5ffd83dbSDimitry Andric class SequencePrinter {
83*5ffd83dbSDimitry Andric public:
84*5ffd83dbSDimitry Andric   SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
85*5ffd83dbSDimitry Andric                   Pred ShouldPrint = Pred())
86*5ffd83dbSDimitry Andric       : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
87*5ffd83dbSDimitry Andric         ShouldPrint(std::move(ShouldPrint)) {}
88*5ffd83dbSDimitry Andric 
89*5ffd83dbSDimitry Andric   void printTo(llvm::raw_ostream &OS) const {
90*5ffd83dbSDimitry Andric     bool PrintComma = false;
91*5ffd83dbSDimitry Andric     OS << OpenSeq;
92*5ffd83dbSDimitry Andric     for (auto &E : S) {
93*5ffd83dbSDimitry Andric       if (ShouldPrint(E)) {
94*5ffd83dbSDimitry Andric         if (PrintComma)
95*5ffd83dbSDimitry Andric           OS << ',';
96*5ffd83dbSDimitry Andric         OS << ' ' << E;
97*5ffd83dbSDimitry Andric         PrintComma = true;
98*5ffd83dbSDimitry Andric       }
99*5ffd83dbSDimitry Andric     }
100*5ffd83dbSDimitry Andric     OS << ' ' << CloseSeq;
101*5ffd83dbSDimitry Andric   }
102*5ffd83dbSDimitry Andric 
103*5ffd83dbSDimitry Andric private:
104*5ffd83dbSDimitry Andric   const Sequence &S;
105*5ffd83dbSDimitry Andric   char OpenSeq;
106*5ffd83dbSDimitry Andric   char CloseSeq;
107*5ffd83dbSDimitry Andric   mutable Pred ShouldPrint;
108*5ffd83dbSDimitry Andric };
109*5ffd83dbSDimitry Andric 
110*5ffd83dbSDimitry Andric template <typename Sequence, typename Pred>
111*5ffd83dbSDimitry Andric SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
112*5ffd83dbSDimitry Andric                                               char CloseSeq, Pred P = Pred()) {
113*5ffd83dbSDimitry Andric   return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
114*5ffd83dbSDimitry Andric }
115*5ffd83dbSDimitry Andric 
116*5ffd83dbSDimitry Andric // Render a SequencePrinter by delegating to its printTo method.
117*5ffd83dbSDimitry Andric template <typename Sequence, typename Pred>
118*5ffd83dbSDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
119*5ffd83dbSDimitry Andric                               const SequencePrinter<Sequence, Pred> &Printer) {
120*5ffd83dbSDimitry Andric   Printer.printTo(OS);
121*5ffd83dbSDimitry Andric   return OS;
122*5ffd83dbSDimitry Andric }
123*5ffd83dbSDimitry Andric 
124*5ffd83dbSDimitry Andric struct PrintSymbolFlagsMapElemsMatchingCLOpts {
125*5ffd83dbSDimitry Andric   bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
126*5ffd83dbSDimitry Andric     return flagsMatchCLOpts(KV.second);
127*5ffd83dbSDimitry Andric   }
128*5ffd83dbSDimitry Andric };
129*5ffd83dbSDimitry Andric 
130*5ffd83dbSDimitry Andric struct PrintSymbolMapElemsMatchingCLOpts {
131*5ffd83dbSDimitry Andric   bool operator()(const orc::SymbolMap::value_type &KV) {
132*5ffd83dbSDimitry Andric     return flagsMatchCLOpts(KV.second.getFlags());
133*5ffd83dbSDimitry Andric   }
134*5ffd83dbSDimitry Andric };
135*5ffd83dbSDimitry Andric 
136*5ffd83dbSDimitry Andric } // end anonymous namespace
137*5ffd83dbSDimitry Andric 
138480093f4SDimitry Andric namespace llvm {
139480093f4SDimitry Andric namespace orc {
140480093f4SDimitry Andric 
141*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
142*5ffd83dbSDimitry Andric   return OS << *Sym;
143*5ffd83dbSDimitry Andric }
144*5ffd83dbSDimitry Andric 
145*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
146*5ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
147*5ffd83dbSDimitry Andric }
148*5ffd83dbSDimitry Andric 
149*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
150*5ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
151*5ffd83dbSDimitry Andric }
152*5ffd83dbSDimitry Andric 
153*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
154*5ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
155*5ffd83dbSDimitry Andric }
156*5ffd83dbSDimitry Andric 
157*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
158*5ffd83dbSDimitry Andric   if (Flags.hasError())
159*5ffd83dbSDimitry Andric     OS << "[*ERROR*]";
160*5ffd83dbSDimitry Andric   if (Flags.isCallable())
161*5ffd83dbSDimitry Andric     OS << "[Callable]";
162*5ffd83dbSDimitry Andric   else
163*5ffd83dbSDimitry Andric     OS << "[Data]";
164*5ffd83dbSDimitry Andric   if (Flags.isWeak())
165*5ffd83dbSDimitry Andric     OS << "[Weak]";
166*5ffd83dbSDimitry Andric   else if (Flags.isCommon())
167*5ffd83dbSDimitry Andric     OS << "[Common]";
168*5ffd83dbSDimitry Andric 
169*5ffd83dbSDimitry Andric   if (!Flags.isExported())
170*5ffd83dbSDimitry Andric     OS << "[Hidden]";
171*5ffd83dbSDimitry Andric 
172*5ffd83dbSDimitry Andric   return OS;
173*5ffd83dbSDimitry Andric }
174*5ffd83dbSDimitry Andric 
175*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
176*5ffd83dbSDimitry Andric   return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
177*5ffd83dbSDimitry Andric             << Sym.getFlags();
178*5ffd83dbSDimitry Andric }
179*5ffd83dbSDimitry Andric 
180*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
181*5ffd83dbSDimitry Andric   return OS << "(\"" << KV.first << "\", " << KV.second << ")";
182*5ffd83dbSDimitry Andric }
183*5ffd83dbSDimitry Andric 
184*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
185*5ffd83dbSDimitry Andric   return OS << "(\"" << KV.first << "\": " << KV.second << ")";
186*5ffd83dbSDimitry Andric }
187*5ffd83dbSDimitry Andric 
188*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
189*5ffd83dbSDimitry Andric   return OS << printSequence(SymbolFlags, '{', '}',
190*5ffd83dbSDimitry Andric                              PrintSymbolFlagsMapElemsMatchingCLOpts());
191*5ffd83dbSDimitry Andric }
192*5ffd83dbSDimitry Andric 
193*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
194*5ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '{', '}',
195*5ffd83dbSDimitry Andric                              PrintSymbolMapElemsMatchingCLOpts());
196*5ffd83dbSDimitry Andric }
197*5ffd83dbSDimitry Andric 
198*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
199*5ffd83dbSDimitry Andric                         const SymbolDependenceMap::value_type &KV) {
200*5ffd83dbSDimitry Andric   return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
201*5ffd83dbSDimitry Andric }
202*5ffd83dbSDimitry Andric 
203*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
204*5ffd83dbSDimitry Andric   return OS << printSequence(Deps, '{', '}',
205*5ffd83dbSDimitry Andric                              PrintAll<SymbolDependenceMap::value_type>());
206*5ffd83dbSDimitry Andric }
207*5ffd83dbSDimitry Andric 
208*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
209*5ffd83dbSDimitry Andric   OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
210*5ffd83dbSDimitry Andric   if (anyPrintSymbolOptionSet())
211*5ffd83dbSDimitry Andric     OS << ", " << MU.getSymbols();
212*5ffd83dbSDimitry Andric   return OS << ")";
213*5ffd83dbSDimitry Andric }
214*5ffd83dbSDimitry Andric 
215*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
216*5ffd83dbSDimitry Andric   switch (K) {
217*5ffd83dbSDimitry Andric   case LookupKind::Static:
218*5ffd83dbSDimitry Andric     return OS << "Static";
219*5ffd83dbSDimitry Andric   case LookupKind::DLSym:
220*5ffd83dbSDimitry Andric     return OS << "DLSym";
221*5ffd83dbSDimitry Andric   }
222*5ffd83dbSDimitry Andric   llvm_unreachable("Invalid lookup kind");
223*5ffd83dbSDimitry Andric }
224*5ffd83dbSDimitry Andric 
225*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
226*5ffd83dbSDimitry Andric                         const JITDylibLookupFlags &JDLookupFlags) {
227*5ffd83dbSDimitry Andric   switch (JDLookupFlags) {
228*5ffd83dbSDimitry Andric   case JITDylibLookupFlags::MatchExportedSymbolsOnly:
229*5ffd83dbSDimitry Andric     return OS << "MatchExportedSymbolsOnly";
230*5ffd83dbSDimitry Andric   case JITDylibLookupFlags::MatchAllSymbols:
231*5ffd83dbSDimitry Andric     return OS << "MatchAllSymbols";
232*5ffd83dbSDimitry Andric   }
233*5ffd83dbSDimitry Andric   llvm_unreachable("Invalid JITDylib lookup flags");
234*5ffd83dbSDimitry Andric }
235*5ffd83dbSDimitry Andric 
236*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
237*5ffd83dbSDimitry Andric   switch (LookupFlags) {
238*5ffd83dbSDimitry Andric   case SymbolLookupFlags::RequiredSymbol:
239*5ffd83dbSDimitry Andric     return OS << "RequiredSymbol";
240*5ffd83dbSDimitry Andric   case SymbolLookupFlags::WeaklyReferencedSymbol:
241*5ffd83dbSDimitry Andric     return OS << "WeaklyReferencedSymbol";
242*5ffd83dbSDimitry Andric   }
243*5ffd83dbSDimitry Andric   llvm_unreachable("Invalid symbol lookup flags");
244*5ffd83dbSDimitry Andric }
245*5ffd83dbSDimitry Andric 
246*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
247*5ffd83dbSDimitry Andric                         const SymbolLookupSet::value_type &KV) {
248*5ffd83dbSDimitry Andric   return OS << "(" << KV.first << ", " << KV.second << ")";
249*5ffd83dbSDimitry Andric }
250*5ffd83dbSDimitry Andric 
251*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
252*5ffd83dbSDimitry Andric   return OS << printSequence(LookupSet, '{', '}',
253*5ffd83dbSDimitry Andric                              PrintAll<SymbolLookupSet::value_type>());
254*5ffd83dbSDimitry Andric }
255*5ffd83dbSDimitry Andric 
256*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
257*5ffd83dbSDimitry Andric                         const JITDylibSearchOrder &SearchOrder) {
258*5ffd83dbSDimitry Andric   OS << "[";
259*5ffd83dbSDimitry Andric   if (!SearchOrder.empty()) {
260*5ffd83dbSDimitry Andric     assert(SearchOrder.front().first &&
261*5ffd83dbSDimitry Andric            "JITDylibList entries must not be null");
262*5ffd83dbSDimitry Andric     OS << " (\"" << SearchOrder.front().first->getName() << "\", "
263*5ffd83dbSDimitry Andric        << SearchOrder.begin()->second << ")";
264*5ffd83dbSDimitry Andric     for (auto &KV :
265*5ffd83dbSDimitry Andric          make_range(std::next(SearchOrder.begin(), 1), SearchOrder.end())) {
266*5ffd83dbSDimitry Andric       assert(KV.first && "JITDylibList entries must not be null");
267*5ffd83dbSDimitry Andric       OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
268*5ffd83dbSDimitry Andric     }
269*5ffd83dbSDimitry Andric   }
270*5ffd83dbSDimitry Andric   OS << " ]";
271*5ffd83dbSDimitry Andric   return OS;
272*5ffd83dbSDimitry Andric }
273*5ffd83dbSDimitry Andric 
274*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
275*5ffd83dbSDimitry Andric   OS << "{";
276*5ffd83dbSDimitry Andric   for (auto &KV : Aliases)
277*5ffd83dbSDimitry Andric     OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
278*5ffd83dbSDimitry Andric        << KV.second.AliasFlags;
279*5ffd83dbSDimitry Andric   OS << " }";
280*5ffd83dbSDimitry Andric   return OS;
281*5ffd83dbSDimitry Andric }
282*5ffd83dbSDimitry Andric 
283*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
284*5ffd83dbSDimitry Andric   switch (S) {
285*5ffd83dbSDimitry Andric   case SymbolState::Invalid:
286*5ffd83dbSDimitry Andric     return OS << "Invalid";
287*5ffd83dbSDimitry Andric   case SymbolState::NeverSearched:
288*5ffd83dbSDimitry Andric     return OS << "Never-Searched";
289*5ffd83dbSDimitry Andric   case SymbolState::Materializing:
290*5ffd83dbSDimitry Andric     return OS << "Materializing";
291*5ffd83dbSDimitry Andric   case SymbolState::Resolved:
292*5ffd83dbSDimitry Andric     return OS << "Resolved";
293*5ffd83dbSDimitry Andric   case SymbolState::Emitted:
294*5ffd83dbSDimitry Andric     return OS << "Emitted";
295*5ffd83dbSDimitry Andric   case SymbolState::Ready:
296*5ffd83dbSDimitry Andric     return OS << "Ready";
297*5ffd83dbSDimitry Andric   }
298*5ffd83dbSDimitry Andric   llvm_unreachable("Invalid state");
299*5ffd83dbSDimitry Andric }
300*5ffd83dbSDimitry Andric 
301480093f4SDimitry Andric DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
302480093f4SDimitry Andric     : DumpDir(std::move(DumpDir)),
303480093f4SDimitry Andric       IdentifierOverride(std::move(IdentifierOverride)) {
304480093f4SDimitry Andric 
305480093f4SDimitry Andric   /// Discard any trailing separators.
306480093f4SDimitry Andric   while (!this->DumpDir.empty() &&
307480093f4SDimitry Andric          sys::path::is_separator(this->DumpDir.back()))
308480093f4SDimitry Andric     this->DumpDir.pop_back();
309480093f4SDimitry Andric }
310480093f4SDimitry Andric 
311480093f4SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>>
312480093f4SDimitry Andric DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
313480093f4SDimitry Andric   size_t Idx = 1;
314480093f4SDimitry Andric 
315480093f4SDimitry Andric   std::string DumpPathStem;
316480093f4SDimitry Andric   raw_string_ostream(DumpPathStem)
317480093f4SDimitry Andric       << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
318480093f4SDimitry Andric 
319480093f4SDimitry Andric   std::string DumpPath = DumpPathStem + ".o";
320480093f4SDimitry Andric   while (sys::fs::exists(DumpPath)) {
321480093f4SDimitry Andric     DumpPath.clear();
322480093f4SDimitry Andric     raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
323480093f4SDimitry Andric   }
324480093f4SDimitry Andric 
325480093f4SDimitry Andric   LLVM_DEBUG({
326480093f4SDimitry Andric     dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
327480093f4SDimitry Andric            << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
328480093f4SDimitry Andric            << DumpPath << "\n";
329480093f4SDimitry Andric   });
330480093f4SDimitry Andric 
331480093f4SDimitry Andric   std::error_code EC;
332480093f4SDimitry Andric   raw_fd_ostream DumpStream(DumpPath, EC);
333480093f4SDimitry Andric   if (EC)
334480093f4SDimitry Andric     return errorCodeToError(EC);
335480093f4SDimitry Andric   DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
336480093f4SDimitry Andric 
337480093f4SDimitry Andric   return std::move(Obj);
338480093f4SDimitry Andric }
339480093f4SDimitry Andric 
340480093f4SDimitry Andric StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
341480093f4SDimitry Andric   if (!IdentifierOverride.empty())
342480093f4SDimitry Andric     return IdentifierOverride;
343480093f4SDimitry Andric   StringRef Identifier = B.getBufferIdentifier();
344480093f4SDimitry Andric   Identifier.consume_back(".o");
345480093f4SDimitry Andric   return Identifier;
346480093f4SDimitry Andric }
347480093f4SDimitry Andric 
348480093f4SDimitry Andric } // End namespace orc.
349480093f4SDimitry Andric } // End namespace llvm.
350