xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp (revision 3e11ae69abd17a80759ae1d9565d555f6a869304)
116f38ddaSLang Hames //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
216f38ddaSLang Hames //
316f38ddaSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
416f38ddaSLang Hames // See https://llvm.org/LICENSE.txt for license information.
516f38ddaSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
616f38ddaSLang Hames //
716f38ddaSLang Hames //===----------------------------------------------------------------------===//
816f38ddaSLang Hames 
916f38ddaSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1038a8760bSLang Hames 
1138a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/Core.h"
1238a8760bSLang Hames #include "llvm/Support/CommandLine.h"
1316f38ddaSLang Hames #include "llvm/Support/Debug.h"
14af450eabSReid Kleckner #include "llvm/Support/FileSystem.h"
1516f38ddaSLang Hames #include "llvm/Support/MemoryBuffer.h"
1616f38ddaSLang Hames #include "llvm/Support/Path.h"
1716f38ddaSLang Hames #include "llvm/Support/raw_ostream.h"
1816f38ddaSLang Hames 
1916f38ddaSLang Hames #define DEBUG_TYPE "orc"
2016f38ddaSLang Hames 
2138a8760bSLang Hames using namespace llvm;
2238a8760bSLang Hames 
2338a8760bSLang Hames namespace {
2438a8760bSLang Hames 
2538a8760bSLang Hames #ifndef NDEBUG
2638a8760bSLang Hames 
2738a8760bSLang Hames cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
2838a8760bSLang Hames                           cl::desc("debug print hidden symbols defined by "
2938a8760bSLang Hames                                    "materialization units"),
3038a8760bSLang Hames                           cl::Hidden);
3138a8760bSLang Hames 
3238a8760bSLang Hames cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
3338a8760bSLang Hames                             cl::desc("debug print callable symbols defined by "
3438a8760bSLang Hames                                      "materialization units"),
3538a8760bSLang Hames                             cl::Hidden);
3638a8760bSLang Hames 
3738a8760bSLang Hames cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
3838a8760bSLang Hames                         cl::desc("debug print data symbols defined by "
3938a8760bSLang Hames                                  "materialization units"),
4038a8760bSLang Hames                         cl::Hidden);
4138a8760bSLang Hames 
4238a8760bSLang Hames #endif // NDEBUG
4338a8760bSLang Hames 
4438a8760bSLang Hames // SetPrinter predicate that prints every element.
4538a8760bSLang Hames template <typename T> struct PrintAll {
4638a8760bSLang Hames   bool operator()(const T &E) { return true; }
4738a8760bSLang Hames };
4838a8760bSLang Hames 
4938a8760bSLang Hames bool anyPrintSymbolOptionSet() {
5038a8760bSLang Hames #ifndef NDEBUG
5138a8760bSLang Hames   return PrintHidden || PrintCallable || PrintData;
5238a8760bSLang Hames #else
5338a8760bSLang Hames   return false;
5438a8760bSLang Hames #endif // NDEBUG
5538a8760bSLang Hames }
5638a8760bSLang Hames 
5738a8760bSLang Hames bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
5838a8760bSLang Hames #ifndef NDEBUG
5938a8760bSLang Hames   // Bail out early if this is a hidden symbol and we're not printing hiddens.
6038a8760bSLang Hames   if (!PrintHidden && !Flags.isExported())
6138a8760bSLang Hames     return false;
6238a8760bSLang Hames 
6338a8760bSLang Hames   // Return true if this is callable and we're printing callables.
6438a8760bSLang Hames   if (PrintCallable && Flags.isCallable())
6538a8760bSLang Hames     return true;
6638a8760bSLang Hames 
6738a8760bSLang Hames   // Return true if this is data and we're printing data.
6838a8760bSLang Hames   if (PrintData && !Flags.isCallable())
6938a8760bSLang Hames     return true;
7038a8760bSLang Hames 
7138a8760bSLang Hames   // otherwise return false.
7238a8760bSLang Hames   return false;
7338a8760bSLang Hames #else
7438a8760bSLang Hames   return false;
7538a8760bSLang Hames #endif // NDEBUG
7638a8760bSLang Hames }
7738a8760bSLang Hames 
7838a8760bSLang Hames // Prints a sequence of items, filtered by an user-supplied predicate.
7938a8760bSLang Hames template <typename Sequence,
8038a8760bSLang Hames           typename Pred = PrintAll<typename Sequence::value_type>>
8138a8760bSLang Hames class SequencePrinter {
8238a8760bSLang Hames public:
8338a8760bSLang Hames   SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
8438a8760bSLang Hames                   Pred ShouldPrint = Pred())
8538a8760bSLang Hames       : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
8638a8760bSLang Hames         ShouldPrint(std::move(ShouldPrint)) {}
8738a8760bSLang Hames 
8838a8760bSLang Hames   void printTo(llvm::raw_ostream &OS) const {
8938a8760bSLang Hames     bool PrintComma = false;
9038a8760bSLang Hames     OS << OpenSeq;
9138a8760bSLang Hames     for (auto &E : S) {
9238a8760bSLang Hames       if (ShouldPrint(E)) {
9338a8760bSLang Hames         if (PrintComma)
9438a8760bSLang Hames           OS << ',';
9538a8760bSLang Hames         OS << ' ' << E;
9638a8760bSLang Hames         PrintComma = true;
9738a8760bSLang Hames       }
9838a8760bSLang Hames     }
9938a8760bSLang Hames     OS << ' ' << CloseSeq;
10038a8760bSLang Hames   }
10138a8760bSLang Hames 
10238a8760bSLang Hames private:
10338a8760bSLang Hames   const Sequence &S;
10438a8760bSLang Hames   char OpenSeq;
10538a8760bSLang Hames   char CloseSeq;
10638a8760bSLang Hames   mutable Pred ShouldPrint;
10738a8760bSLang Hames };
10838a8760bSLang Hames 
10938a8760bSLang Hames template <typename Sequence, typename Pred>
11038a8760bSLang Hames SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
11138a8760bSLang Hames                                               char CloseSeq, Pred P = Pred()) {
11238a8760bSLang Hames   return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
11338a8760bSLang Hames }
11438a8760bSLang Hames 
11538a8760bSLang Hames // Render a SequencePrinter by delegating to its printTo method.
11638a8760bSLang Hames template <typename Sequence, typename Pred>
11738a8760bSLang Hames llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
11838a8760bSLang Hames                               const SequencePrinter<Sequence, Pred> &Printer) {
11938a8760bSLang Hames   Printer.printTo(OS);
12038a8760bSLang Hames   return OS;
12138a8760bSLang Hames }
12238a8760bSLang Hames 
12338a8760bSLang Hames struct PrintSymbolFlagsMapElemsMatchingCLOpts {
12438a8760bSLang Hames   bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
12538a8760bSLang Hames     return flagsMatchCLOpts(KV.second);
12638a8760bSLang Hames   }
12738a8760bSLang Hames };
12838a8760bSLang Hames 
12938a8760bSLang Hames struct PrintSymbolMapElemsMatchingCLOpts {
13038a8760bSLang Hames   bool operator()(const orc::SymbolMap::value_type &KV) {
13138a8760bSLang Hames     return flagsMatchCLOpts(KV.second.getFlags());
13238a8760bSLang Hames   }
13338a8760bSLang Hames };
13438a8760bSLang Hames 
13538a8760bSLang Hames } // end anonymous namespace
13638a8760bSLang Hames 
13716f38ddaSLang Hames namespace llvm {
13816f38ddaSLang Hames namespace orc {
13916f38ddaSLang Hames 
14038a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
14138a8760bSLang Hames   return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
14238a8760bSLang Hames }
14338a8760bSLang Hames 
14438a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
14538a8760bSLang Hames   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
14638a8760bSLang Hames }
14738a8760bSLang Hames 
148cb84e482SLang Hames raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
149cb84e482SLang Hames   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
150cb84e482SLang Hames }
151cb84e482SLang Hames 
15238a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
15338a8760bSLang Hames   if (Flags.hasError())
15438a8760bSLang Hames     OS << "[*ERROR*]";
15538a8760bSLang Hames   if (Flags.isCallable())
15638a8760bSLang Hames     OS << "[Callable]";
15738a8760bSLang Hames   else
15838a8760bSLang Hames     OS << "[Data]";
15938a8760bSLang Hames   if (Flags.isWeak())
16038a8760bSLang Hames     OS << "[Weak]";
16138a8760bSLang Hames   else if (Flags.isCommon())
16238a8760bSLang Hames     OS << "[Common]";
16338a8760bSLang Hames 
16438a8760bSLang Hames   if (!Flags.isExported())
16538a8760bSLang Hames     OS << "[Hidden]";
16638a8760bSLang Hames 
16738a8760bSLang Hames   return OS;
16838a8760bSLang Hames }
16938a8760bSLang Hames 
1708b1771bdSLang Hames raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
1718b1771bdSLang Hames   return OS << Sym.getAddress() << " " << Sym.getFlags();
17238a8760bSLang Hames }
17338a8760bSLang Hames 
17438a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
17538a8760bSLang Hames   return OS << "(\"" << KV.first << "\", " << KV.second << ")";
17638a8760bSLang Hames }
17738a8760bSLang Hames 
17838a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
17938a8760bSLang Hames   return OS << "(\"" << KV.first << "\": " << KV.second << ")";
18038a8760bSLang Hames }
18138a8760bSLang Hames 
18238a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
18338a8760bSLang Hames   return OS << printSequence(SymbolFlags, '{', '}',
18438a8760bSLang Hames                              PrintSymbolFlagsMapElemsMatchingCLOpts());
18538a8760bSLang Hames }
18638a8760bSLang Hames 
18738a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
18838a8760bSLang Hames   return OS << printSequence(Symbols, '{', '}',
18938a8760bSLang Hames                              PrintSymbolMapElemsMatchingCLOpts());
19038a8760bSLang Hames }
19138a8760bSLang Hames 
19238a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
19338a8760bSLang Hames                         const SymbolDependenceMap::value_type &KV) {
19438a8760bSLang Hames   return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
19538a8760bSLang Hames }
19638a8760bSLang Hames 
19738a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
19838a8760bSLang Hames   return OS << printSequence(Deps, '{', '}',
19938a8760bSLang Hames                              PrintAll<SymbolDependenceMap::value_type>());
20038a8760bSLang Hames }
20138a8760bSLang Hames 
20238a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
20338a8760bSLang Hames   OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
20438a8760bSLang Hames   if (anyPrintSymbolOptionSet())
20538a8760bSLang Hames     OS << ", " << MU.getSymbols();
20638a8760bSLang Hames   return OS << ")";
20738a8760bSLang Hames }
20838a8760bSLang Hames 
20938a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
21038a8760bSLang Hames   switch (K) {
21138a8760bSLang Hames   case LookupKind::Static:
21238a8760bSLang Hames     return OS << "Static";
21338a8760bSLang Hames   case LookupKind::DLSym:
21438a8760bSLang Hames     return OS << "DLSym";
21538a8760bSLang Hames   }
21638a8760bSLang Hames   llvm_unreachable("Invalid lookup kind");
21738a8760bSLang Hames }
21838a8760bSLang Hames 
21938a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
22038a8760bSLang Hames                         const JITDylibLookupFlags &JDLookupFlags) {
22138a8760bSLang Hames   switch (JDLookupFlags) {
22238a8760bSLang Hames   case JITDylibLookupFlags::MatchExportedSymbolsOnly:
22338a8760bSLang Hames     return OS << "MatchExportedSymbolsOnly";
22438a8760bSLang Hames   case JITDylibLookupFlags::MatchAllSymbols:
22538a8760bSLang Hames     return OS << "MatchAllSymbols";
22638a8760bSLang Hames   }
22738a8760bSLang Hames   llvm_unreachable("Invalid JITDylib lookup flags");
22838a8760bSLang Hames }
22938a8760bSLang Hames 
23038a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
23138a8760bSLang Hames   switch (LookupFlags) {
23238a8760bSLang Hames   case SymbolLookupFlags::RequiredSymbol:
23338a8760bSLang Hames     return OS << "RequiredSymbol";
23438a8760bSLang Hames   case SymbolLookupFlags::WeaklyReferencedSymbol:
23538a8760bSLang Hames     return OS << "WeaklyReferencedSymbol";
23638a8760bSLang Hames   }
23738a8760bSLang Hames   llvm_unreachable("Invalid symbol lookup flags");
23838a8760bSLang Hames }
23938a8760bSLang Hames 
24038a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
24138a8760bSLang Hames                         const SymbolLookupSet::value_type &KV) {
24238a8760bSLang Hames   return OS << "(" << KV.first << ", " << KV.second << ")";
24338a8760bSLang Hames }
24438a8760bSLang Hames 
24538a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
24638a8760bSLang Hames   return OS << printSequence(LookupSet, '{', '}',
24738a8760bSLang Hames                              PrintAll<SymbolLookupSet::value_type>());
24838a8760bSLang Hames }
24938a8760bSLang Hames 
25038a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
25138a8760bSLang Hames                         const JITDylibSearchOrder &SearchOrder) {
25238a8760bSLang Hames   OS << "[";
25338a8760bSLang Hames   if (!SearchOrder.empty()) {
25438a8760bSLang Hames     assert(SearchOrder.front().first &&
25538a8760bSLang Hames            "JITDylibList entries must not be null");
25638a8760bSLang Hames     OS << " (\"" << SearchOrder.front().first->getName() << "\", "
25738a8760bSLang Hames        << SearchOrder.begin()->second << ")";
2584ed47858SKazu Hirata     for (auto &KV : llvm::drop_begin(SearchOrder)) {
25938a8760bSLang Hames       assert(KV.first && "JITDylibList entries must not be null");
26038a8760bSLang Hames       OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
26138a8760bSLang Hames     }
26238a8760bSLang Hames   }
26338a8760bSLang Hames   OS << " ]";
26438a8760bSLang Hames   return OS;
26538a8760bSLang Hames }
26638a8760bSLang Hames 
26738a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
26838a8760bSLang Hames   OS << "{";
26938a8760bSLang Hames   for (auto &KV : Aliases)
27038a8760bSLang Hames     OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
27138a8760bSLang Hames        << KV.second.AliasFlags;
27238a8760bSLang Hames   OS << " }";
27338a8760bSLang Hames   return OS;
27438a8760bSLang Hames }
27538a8760bSLang Hames 
27638a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
27738a8760bSLang Hames   switch (S) {
27838a8760bSLang Hames   case SymbolState::Invalid:
27938a8760bSLang Hames     return OS << "Invalid";
28038a8760bSLang Hames   case SymbolState::NeverSearched:
28138a8760bSLang Hames     return OS << "Never-Searched";
28238a8760bSLang Hames   case SymbolState::Materializing:
28338a8760bSLang Hames     return OS << "Materializing";
28438a8760bSLang Hames   case SymbolState::Resolved:
28538a8760bSLang Hames     return OS << "Resolved";
28638a8760bSLang Hames   case SymbolState::Emitted:
28738a8760bSLang Hames     return OS << "Emitted";
28838a8760bSLang Hames   case SymbolState::Ready:
28938a8760bSLang Hames     return OS << "Ready";
29038a8760bSLang Hames   }
29138a8760bSLang Hames   llvm_unreachable("Invalid state");
29238a8760bSLang Hames }
29338a8760bSLang Hames 
2943fcd3669SLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
2953fcd3669SLang Hames   std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
296*8bba3f0eSFangrui Song   SmallVector<std::pair<StringRef, int>, 0> Vec;
2973fcd3669SLang Hames   for (auto &KV : SSP.Pool)
298*8bba3f0eSFangrui Song     Vec.emplace_back(KV.first(), KV.second);
299*8bba3f0eSFangrui Song   llvm::sort(Vec, less_first());
300*8bba3f0eSFangrui Song   for (auto &[K, V] : Vec)
301*8bba3f0eSFangrui Song     OS << K << ": " << V << "\n";
3023fcd3669SLang Hames   return OS;
3033fcd3669SLang Hames }
3043fcd3669SLang Hames 
30516f38ddaSLang Hames DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
30616f38ddaSLang Hames     : DumpDir(std::move(DumpDir)),
30716f38ddaSLang Hames       IdentifierOverride(std::move(IdentifierOverride)) {
30816f38ddaSLang Hames 
30916f38ddaSLang Hames   /// Discard any trailing separators.
31016f38ddaSLang Hames   while (!this->DumpDir.empty() &&
31116f38ddaSLang Hames          sys::path::is_separator(this->DumpDir.back()))
31216f38ddaSLang Hames     this->DumpDir.pop_back();
31316f38ddaSLang Hames }
31416f38ddaSLang Hames 
31516f38ddaSLang Hames Expected<std::unique_ptr<MemoryBuffer>>
31616f38ddaSLang Hames DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
31716f38ddaSLang Hames   size_t Idx = 1;
31816f38ddaSLang Hames 
31916f38ddaSLang Hames   std::string DumpPathStem;
32016f38ddaSLang Hames   raw_string_ostream(DumpPathStem)
32116f38ddaSLang Hames       << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
32216f38ddaSLang Hames 
32316f38ddaSLang Hames   std::string DumpPath = DumpPathStem + ".o";
32416f38ddaSLang Hames   while (sys::fs::exists(DumpPath)) {
32516f38ddaSLang Hames     DumpPath.clear();
32616f38ddaSLang Hames     raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
32716f38ddaSLang Hames   }
32816f38ddaSLang Hames 
32916f38ddaSLang Hames   LLVM_DEBUG({
330c42e3851SHans Wennborg     dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
331c42e3851SHans Wennborg            << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
33216f38ddaSLang Hames            << DumpPath << "\n";
33316f38ddaSLang Hames   });
33416f38ddaSLang Hames 
33516f38ddaSLang Hames   std::error_code EC;
33616f38ddaSLang Hames   raw_fd_ostream DumpStream(DumpPath, EC);
33716f38ddaSLang Hames   if (EC)
33816f38ddaSLang Hames     return errorCodeToError(EC);
33916f38ddaSLang Hames   DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
34016f38ddaSLang Hames 
341c55cf4afSBill Wendling   return std::move(Obj);
34216f38ddaSLang Hames }
34316f38ddaSLang Hames 
34416f38ddaSLang Hames StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
34516f38ddaSLang Hames   if (!IdentifierOverride.empty())
34616f38ddaSLang Hames     return IdentifierOverride;
34716f38ddaSLang Hames   StringRef Identifier = B.getBufferIdentifier();
34816f38ddaSLang Hames   Identifier.consume_back(".o");
34916f38ddaSLang Hames   return Identifier;
35016f38ddaSLang Hames }
35116f38ddaSLang Hames 
35216f38ddaSLang Hames } // End namespace orc.
35316f38ddaSLang Hames } // End namespace llvm.
354