Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
35266 views
//===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/DebugUtils.h"910#include "llvm/ExecutionEngine/Orc/Core.h"11#include "llvm/Support/CommandLine.h"12#include "llvm/Support/Debug.h"13#include "llvm/Support/FileSystem.h"14#include "llvm/Support/Format.h"15#include "llvm/Support/MemoryBuffer.h"16#include "llvm/Support/Path.h"17#include "llvm/Support/raw_ostream.h"1819#define DEBUG_TYPE "orc"2021using namespace llvm;2223namespace {2425#ifndef NDEBUG2627cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),28cl::desc("debug print hidden symbols defined by "29"materialization units"),30cl::Hidden);3132cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),33cl::desc("debug print callable symbols defined by "34"materialization units"),35cl::Hidden);3637cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),38cl::desc("debug print data symbols defined by "39"materialization units"),40cl::Hidden);4142#endif // NDEBUG4344// SetPrinter predicate that prints every element.45template <typename T> struct PrintAll {46bool operator()(const T &E) { return true; }47};4849bool anyPrintSymbolOptionSet() {50#ifndef NDEBUG51return PrintHidden || PrintCallable || PrintData;52#else53return false;54#endif // NDEBUG55}5657bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {58#ifndef NDEBUG59// Bail out early if this is a hidden symbol and we're not printing hiddens.60if (!PrintHidden && !Flags.isExported())61return false;6263// Return true if this is callable and we're printing callables.64if (PrintCallable && Flags.isCallable())65return true;6667// Return true if this is data and we're printing data.68if (PrintData && !Flags.isCallable())69return true;7071// otherwise return false.72return false;73#else74return false;75#endif // NDEBUG76}7778// Prints a sequence of items, filtered by an user-supplied predicate.79template <typename Sequence,80typename Pred = PrintAll<typename Sequence::value_type>>81class SequencePrinter {82public:83SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,84Pred ShouldPrint = Pred())85: S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),86ShouldPrint(std::move(ShouldPrint)) {}8788void printTo(llvm::raw_ostream &OS) const {89bool PrintComma = false;90OS << OpenSeq;91for (auto &E : S) {92if (ShouldPrint(E)) {93if (PrintComma)94OS << ',';95OS << ' ' << E;96PrintComma = true;97}98}99OS << ' ' << CloseSeq;100}101102private:103const Sequence &S;104char OpenSeq;105char CloseSeq;106mutable Pred ShouldPrint;107};108109template <typename Sequence, typename Pred>110SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,111char CloseSeq, Pred P = Pred()) {112return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));113}114115// Render a SequencePrinter by delegating to its printTo method.116template <typename Sequence, typename Pred>117llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,118const SequencePrinter<Sequence, Pred> &Printer) {119Printer.printTo(OS);120return OS;121}122123struct PrintSymbolFlagsMapElemsMatchingCLOpts {124bool operator()(const orc::SymbolFlagsMap::value_type &KV) {125return flagsMatchCLOpts(KV.second);126}127};128129struct PrintSymbolMapElemsMatchingCLOpts {130bool operator()(const orc::SymbolMap::value_type &KV) {131return flagsMatchCLOpts(KV.second.getFlags());132}133};134135} // end anonymous namespace136137namespace llvm {138namespace orc {139140raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {141return OS << *Sym;142}143144raw_ostream &operator<<(raw_ostream &OS, NonOwningSymbolStringPtr Sym) {145return OS << *Sym;146}147148raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {149return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());150}151152raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {153return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());154}155156raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {157return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());158}159160raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {161if (Flags.hasError())162OS << "[*ERROR*]";163if (Flags.isCallable())164OS << "[Callable]";165else166OS << "[Data]";167if (Flags.isWeak())168OS << "[Weak]";169else if (Flags.isCommon())170OS << "[Common]";171172if (!Flags.isExported())173OS << "[Hidden]";174175return OS;176}177178raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {179return OS << Sym.getAddress() << " " << Sym.getFlags();180}181182raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {183return OS << "(\"" << KV.first << "\", " << KV.second << ")";184}185186raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {187return OS << "(\"" << KV.first << "\": " << KV.second << ")";188}189190raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {191return OS << printSequence(SymbolFlags, '{', '}',192PrintSymbolFlagsMapElemsMatchingCLOpts());193}194195raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {196return OS << printSequence(Symbols, '{', '}',197PrintSymbolMapElemsMatchingCLOpts());198}199200raw_ostream &operator<<(raw_ostream &OS,201const SymbolDependenceMap::value_type &KV) {202return OS << "(" << KV.first->getName() << ", " << KV.second << ")";203}204205raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {206return OS << printSequence(Deps, '{', '}',207PrintAll<SymbolDependenceMap::value_type>());208}209210raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {211OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";212if (anyPrintSymbolOptionSet())213OS << ", " << MU.getSymbols();214return OS << ")";215}216217raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {218switch (K) {219case LookupKind::Static:220return OS << "Static";221case LookupKind::DLSym:222return OS << "DLSym";223}224llvm_unreachable("Invalid lookup kind");225}226227raw_ostream &operator<<(raw_ostream &OS,228const JITDylibLookupFlags &JDLookupFlags) {229switch (JDLookupFlags) {230case JITDylibLookupFlags::MatchExportedSymbolsOnly:231return OS << "MatchExportedSymbolsOnly";232case JITDylibLookupFlags::MatchAllSymbols:233return OS << "MatchAllSymbols";234}235llvm_unreachable("Invalid JITDylib lookup flags");236}237238raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {239switch (LookupFlags) {240case SymbolLookupFlags::RequiredSymbol:241return OS << "RequiredSymbol";242case SymbolLookupFlags::WeaklyReferencedSymbol:243return OS << "WeaklyReferencedSymbol";244}245llvm_unreachable("Invalid symbol lookup flags");246}247248raw_ostream &operator<<(raw_ostream &OS,249const SymbolLookupSet::value_type &KV) {250return OS << "(" << KV.first << ", " << KV.second << ")";251}252253raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {254return OS << printSequence(LookupSet, '{', '}',255PrintAll<SymbolLookupSet::value_type>());256}257258raw_ostream &operator<<(raw_ostream &OS,259const JITDylibSearchOrder &SearchOrder) {260OS << "[";261if (!SearchOrder.empty()) {262assert(SearchOrder.front().first &&263"JITDylibList entries must not be null");264OS << " (\"" << SearchOrder.front().first->getName() << "\", "265<< SearchOrder.begin()->second << ")";266for (auto &KV : llvm::drop_begin(SearchOrder)) {267assert(KV.first && "JITDylibList entries must not be null");268OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";269}270}271OS << " ]";272return OS;273}274275raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {276OS << "{";277for (auto &KV : Aliases)278OS << " " << *KV.first << ": " << KV.second.Aliasee << " "279<< KV.second.AliasFlags;280OS << " }";281return OS;282}283284raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {285switch (S) {286case SymbolState::Invalid:287return OS << "Invalid";288case SymbolState::NeverSearched:289return OS << "Never-Searched";290case SymbolState::Materializing:291return OS << "Materializing";292case SymbolState::Resolved:293return OS << "Resolved";294case SymbolState::Emitted:295return OS << "Emitted";296case SymbolState::Ready:297return OS << "Ready";298}299llvm_unreachable("Invalid state");300}301302raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {303std::lock_guard<std::mutex> Lock(SSP.PoolMutex);304SmallVector<std::pair<StringRef, int>, 0> Vec;305for (auto &KV : SSP.Pool)306Vec.emplace_back(KV.first(), KV.second);307llvm::sort(Vec, less_first());308for (auto &[K, V] : Vec)309OS << K << ": " << V << "\n";310return OS;311}312313DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)314: DumpDir(std::move(DumpDir)),315IdentifierOverride(std::move(IdentifierOverride)) {316317/// Discard any trailing separators.318while (!this->DumpDir.empty() &&319sys::path::is_separator(this->DumpDir.back()))320this->DumpDir.pop_back();321}322323Expected<std::unique_ptr<MemoryBuffer>>324DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {325size_t Idx = 1;326327std::string DumpPathStem;328raw_string_ostream(DumpPathStem)329<< DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);330331std::string DumpPath = DumpPathStem + ".o";332while (sys::fs::exists(DumpPath)) {333DumpPath.clear();334raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";335}336337LLVM_DEBUG({338dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()339<< " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "340<< DumpPath << "\n";341});342343std::error_code EC;344raw_fd_ostream DumpStream(DumpPath, EC);345if (EC)346return errorCodeToError(EC);347DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());348349return std::move(Obj);350}351352StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {353if (!IdentifierOverride.empty())354return IdentifierOverride;355StringRef Identifier = B.getBufferIdentifier();356Identifier.consume_back(".o");357return Identifier;358}359360} // End namespace orc.361} // End namespace llvm.362363364