123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
- #include "llvm/ExecutionEngine/Orc/Core.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Format.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/raw_ostream.h"
- #define DEBUG_TYPE "orc"
- using namespace llvm;
- namespace {
- #ifndef NDEBUG
- cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
- cl::desc("debug print hidden symbols defined by "
- "materialization units"),
- cl::Hidden);
- cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
- cl::desc("debug print callable symbols defined by "
- "materialization units"),
- cl::Hidden);
- cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
- cl::desc("debug print data symbols defined by "
- "materialization units"),
- cl::Hidden);
- #endif // NDEBUG
- // SetPrinter predicate that prints every element.
- template <typename T> struct PrintAll {
- bool operator()(const T &E) { return true; }
- };
- bool anyPrintSymbolOptionSet() {
- #ifndef NDEBUG
- return PrintHidden || PrintCallable || PrintData;
- #else
- return false;
- #endif // NDEBUG
- }
- bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
- #ifndef NDEBUG
- // Bail out early if this is a hidden symbol and we're not printing hiddens.
- if (!PrintHidden && !Flags.isExported())
- return false;
- // Return true if this is callable and we're printing callables.
- if (PrintCallable && Flags.isCallable())
- return true;
- // Return true if this is data and we're printing data.
- if (PrintData && !Flags.isCallable())
- return true;
- // otherwise return false.
- return false;
- #else
- return false;
- #endif // NDEBUG
- }
- // Prints a sequence of items, filtered by an user-supplied predicate.
- template <typename Sequence,
- typename Pred = PrintAll<typename Sequence::value_type>>
- class SequencePrinter {
- public:
- SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
- Pred ShouldPrint = Pred())
- : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
- ShouldPrint(std::move(ShouldPrint)) {}
- void printTo(llvm::raw_ostream &OS) const {
- bool PrintComma = false;
- OS << OpenSeq;
- for (auto &E : S) {
- if (ShouldPrint(E)) {
- if (PrintComma)
- OS << ',';
- OS << ' ' << E;
- PrintComma = true;
- }
- }
- OS << ' ' << CloseSeq;
- }
- private:
- const Sequence &S;
- char OpenSeq;
- char CloseSeq;
- mutable Pred ShouldPrint;
- };
- template <typename Sequence, typename Pred>
- SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
- char CloseSeq, Pred P = Pred()) {
- return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
- }
- // Render a SequencePrinter by delegating to its printTo method.
- template <typename Sequence, typename Pred>
- llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const SequencePrinter<Sequence, Pred> &Printer) {
- Printer.printTo(OS);
- return OS;
- }
- struct PrintSymbolFlagsMapElemsMatchingCLOpts {
- bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
- return flagsMatchCLOpts(KV.second);
- }
- };
- struct PrintSymbolMapElemsMatchingCLOpts {
- bool operator()(const orc::SymbolMap::value_type &KV) {
- return flagsMatchCLOpts(KV.second.getFlags());
- }
- };
- } // end anonymous namespace
- namespace llvm {
- namespace orc {
- raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
- return OS << *Sym;
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
- return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
- return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
- }
- raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
- return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
- }
- raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
- if (Flags.hasError())
- OS << "[*ERROR*]";
- if (Flags.isCallable())
- OS << "[Callable]";
- else
- OS << "[Data]";
- if (Flags.isWeak())
- OS << "[Weak]";
- else if (Flags.isCommon())
- OS << "[Common]";
- if (!Flags.isExported())
- OS << "[Hidden]";
- return OS;
- }
- raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
- return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
- << Sym.getFlags();
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
- return OS << "(\"" << KV.first << "\", " << KV.second << ")";
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
- return OS << "(\"" << KV.first << "\": " << KV.second << ")";
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
- return OS << printSequence(SymbolFlags, '{', '}',
- PrintSymbolFlagsMapElemsMatchingCLOpts());
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
- return OS << printSequence(Symbols, '{', '}',
- PrintSymbolMapElemsMatchingCLOpts());
- }
- raw_ostream &operator<<(raw_ostream &OS,
- const SymbolDependenceMap::value_type &KV) {
- return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
- return OS << printSequence(Deps, '{', '}',
- PrintAll<SymbolDependenceMap::value_type>());
- }
- raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
- OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
- if (anyPrintSymbolOptionSet())
- OS << ", " << MU.getSymbols();
- return OS << ")";
- }
- raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
- switch (K) {
- case LookupKind::Static:
- return OS << "Static";
- case LookupKind::DLSym:
- return OS << "DLSym";
- }
- llvm_unreachable("Invalid lookup kind");
- }
- raw_ostream &operator<<(raw_ostream &OS,
- const JITDylibLookupFlags &JDLookupFlags) {
- switch (JDLookupFlags) {
- case JITDylibLookupFlags::MatchExportedSymbolsOnly:
- return OS << "MatchExportedSymbolsOnly";
- case JITDylibLookupFlags::MatchAllSymbols:
- return OS << "MatchAllSymbols";
- }
- llvm_unreachable("Invalid JITDylib lookup flags");
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
- switch (LookupFlags) {
- case SymbolLookupFlags::RequiredSymbol:
- return OS << "RequiredSymbol";
- case SymbolLookupFlags::WeaklyReferencedSymbol:
- return OS << "WeaklyReferencedSymbol";
- }
- llvm_unreachable("Invalid symbol lookup flags");
- }
- raw_ostream &operator<<(raw_ostream &OS,
- const SymbolLookupSet::value_type &KV) {
- return OS << "(" << KV.first << ", " << KV.second << ")";
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
- return OS << printSequence(LookupSet, '{', '}',
- PrintAll<SymbolLookupSet::value_type>());
- }
- raw_ostream &operator<<(raw_ostream &OS,
- const JITDylibSearchOrder &SearchOrder) {
- OS << "[";
- if (!SearchOrder.empty()) {
- assert(SearchOrder.front().first &&
- "JITDylibList entries must not be null");
- OS << " (\"" << SearchOrder.front().first->getName() << "\", "
- << SearchOrder.begin()->second << ")";
- for (auto &KV : llvm::drop_begin(SearchOrder)) {
- assert(KV.first && "JITDylibList entries must not be null");
- OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
- }
- }
- OS << " ]";
- return OS;
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
- OS << "{";
- for (auto &KV : Aliases)
- OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
- << KV.second.AliasFlags;
- OS << " }";
- return OS;
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
- switch (S) {
- case SymbolState::Invalid:
- return OS << "Invalid";
- case SymbolState::NeverSearched:
- return OS << "Never-Searched";
- case SymbolState::Materializing:
- return OS << "Materializing";
- case SymbolState::Resolved:
- return OS << "Resolved";
- case SymbolState::Emitted:
- return OS << "Emitted";
- case SymbolState::Ready:
- return OS << "Ready";
- }
- llvm_unreachable("Invalid state");
- }
- raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
- std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
- for (auto &KV : SSP.Pool)
- OS << KV.first() << ": " << KV.second << "\n";
- return OS;
- }
- DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
- : DumpDir(std::move(DumpDir)),
- IdentifierOverride(std::move(IdentifierOverride)) {
- /// Discard any trailing separators.
- while (!this->DumpDir.empty() &&
- sys::path::is_separator(this->DumpDir.back()))
- this->DumpDir.pop_back();
- }
- Expected<std::unique_ptr<MemoryBuffer>>
- DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
- size_t Idx = 1;
- std::string DumpPathStem;
- raw_string_ostream(DumpPathStem)
- << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
- std::string DumpPath = DumpPathStem + ".o";
- while (sys::fs::exists(DumpPath)) {
- DumpPath.clear();
- raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
- }
- LLVM_DEBUG({
- dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
- << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
- << DumpPath << "\n";
- });
- std::error_code EC;
- raw_fd_ostream DumpStream(DumpPath, EC);
- if (EC)
- return errorCodeToError(EC);
- DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
- return std::move(Obj);
- }
- StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
- if (!IdentifierOverride.empty())
- return IdentifierOverride;
- StringRef Identifier = B.getBufferIdentifier();
- Identifier.consume_back(".o");
- return Identifier;
- }
- } // End namespace orc.
- } // End namespace llvm.
|