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