brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 6ced8c7 Raw
354 lines · cpp
1//===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/DebugUtils.h"10 11#include "llvm/ExecutionEngine/Orc/Core.h"12#include "llvm/Support/CommandLine.h"13#include "llvm/Support/Debug.h"14#include "llvm/Support/FileSystem.h"15#include "llvm/Support/MemoryBuffer.h"16#include "llvm/Support/Path.h"17#include "llvm/Support/raw_ostream.h"18 19#define DEBUG_TYPE "orc"20 21using namespace llvm;22 23namespace {24 25#ifndef NDEBUG26 27cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),28                          cl::desc("debug print hidden symbols defined by "29                                   "materialization units"),30                          cl::Hidden);31 32cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),33                            cl::desc("debug print callable symbols defined by "34                                     "materialization units"),35                            cl::Hidden);36 37cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),38                        cl::desc("debug print data symbols defined by "39                                 "materialization units"),40                        cl::Hidden);41 42#endif // NDEBUG43 44// SetPrinter predicate that prints every element.45template <typename T> struct PrintAll {46  bool operator()(const T &E) { return true; }47};48 49bool anyPrintSymbolOptionSet() {50#ifndef NDEBUG51  return PrintHidden || PrintCallable || PrintData;52#else53  return false;54#endif // NDEBUG55}56 57bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {58#ifndef NDEBUG59  // Bail out early if this is a hidden symbol and we're not printing hiddens.60  if (!PrintHidden && !Flags.isExported())61    return false;62 63  // Return true if this is callable and we're printing callables.64  if (PrintCallable && Flags.isCallable())65    return true;66 67  // Return true if this is data and we're printing data.68  if (PrintData && !Flags.isCallable())69    return true;70 71  // otherwise return false.72  return false;73#else74  return false;75#endif // NDEBUG76}77 78// Prints a sequence of items, filtered by an user-supplied predicate.79template <typename Sequence,80          typename Pred = PrintAll<typename Sequence::value_type>>81class SequencePrinter {82public:83  SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,84                  Pred ShouldPrint = Pred())85      : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),86        ShouldPrint(std::move(ShouldPrint)) {}87 88  void printTo(llvm::raw_ostream &OS) const {89    bool PrintComma = false;90    OS << OpenSeq;91    for (auto &E : S) {92      if (ShouldPrint(E)) {93        if (PrintComma)94          OS << ',';95        OS << ' ' << E;96        PrintComma = true;97      }98    }99    OS << ' ' << CloseSeq;100  }101 102private:103  const Sequence &S;104  char OpenSeq;105  char CloseSeq;106  mutable Pred ShouldPrint;107};108 109template <typename Sequence, typename Pred>110SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,111                                              char CloseSeq, Pred P = Pred()) {112  return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));113}114 115// Render a SequencePrinter by delegating to its printTo method.116template <typename Sequence, typename Pred>117llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,118                              const SequencePrinter<Sequence, Pred> &Printer) {119  Printer.printTo(OS);120  return OS;121}122 123struct PrintSymbolFlagsMapElemsMatchingCLOpts {124  bool operator()(const orc::SymbolFlagsMap::value_type &KV) {125    return flagsMatchCLOpts(KV.second);126  }127};128 129struct PrintSymbolMapElemsMatchingCLOpts {130  bool operator()(const orc::SymbolMap::value_type &KV) {131    return flagsMatchCLOpts(KV.second.getFlags());132  }133};134 135} // end anonymous namespace136 137namespace llvm {138namespace orc {139 140raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {141  return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());142}143 144raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {145  return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());146}147 148raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {149  return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());150}151 152raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {153  if (Flags.hasError())154    OS << "[*ERROR*]";155  if (Flags.isCallable())156    OS << "[Callable]";157  else158    OS << "[Data]";159  if (Flags.isWeak())160    OS << "[Weak]";161  else if (Flags.isCommon())162    OS << "[Common]";163 164  if (!Flags.isExported())165    OS << "[Hidden]";166 167  return OS;168}169 170raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {171  return OS << Sym.getAddress() << " " << Sym.getFlags();172}173 174raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {175  return OS << "(\"" << KV.first << "\", " << KV.second << ")";176}177 178raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {179  return OS << "(\"" << KV.first << "\": " << KV.second << ")";180}181 182raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {183  return OS << printSequence(SymbolFlags, '{', '}',184                             PrintSymbolFlagsMapElemsMatchingCLOpts());185}186 187raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {188  return OS << printSequence(Symbols, '{', '}',189                             PrintSymbolMapElemsMatchingCLOpts());190}191 192raw_ostream &operator<<(raw_ostream &OS,193                        const SymbolDependenceMap::value_type &KV) {194  return OS << "(" << KV.first->getName() << ", " << KV.second << ")";195}196 197raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {198  return OS << printSequence(Deps, '{', '}',199                             PrintAll<SymbolDependenceMap::value_type>());200}201 202raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {203  OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";204  if (anyPrintSymbolOptionSet())205    OS << ", " << MU.getSymbols();206  return OS << ")";207}208 209raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {210  switch (K) {211  case LookupKind::Static:212    return OS << "Static";213  case LookupKind::DLSym:214    return OS << "DLSym";215  }216  llvm_unreachable("Invalid lookup kind");217}218 219raw_ostream &operator<<(raw_ostream &OS,220                        const JITDylibLookupFlags &JDLookupFlags) {221  switch (JDLookupFlags) {222  case JITDylibLookupFlags::MatchExportedSymbolsOnly:223    return OS << "MatchExportedSymbolsOnly";224  case JITDylibLookupFlags::MatchAllSymbols:225    return OS << "MatchAllSymbols";226  }227  llvm_unreachable("Invalid JITDylib lookup flags");228}229 230raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {231  switch (LookupFlags) {232  case SymbolLookupFlags::RequiredSymbol:233    return OS << "RequiredSymbol";234  case SymbolLookupFlags::WeaklyReferencedSymbol:235    return OS << "WeaklyReferencedSymbol";236  }237  llvm_unreachable("Invalid symbol lookup flags");238}239 240raw_ostream &operator<<(raw_ostream &OS,241                        const SymbolLookupSet::value_type &KV) {242  return OS << "(" << KV.first << ", " << KV.second << ")";243}244 245raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {246  return OS << printSequence(LookupSet, '{', '}',247                             PrintAll<SymbolLookupSet::value_type>());248}249 250raw_ostream &operator<<(raw_ostream &OS,251                        const JITDylibSearchOrder &SearchOrder) {252  OS << "[";253  if (!SearchOrder.empty()) {254    assert(SearchOrder.front().first &&255           "JITDylibList entries must not be null");256    OS << " (\"" << SearchOrder.front().first->getName() << "\", "257       << SearchOrder.begin()->second << ")";258    for (auto &KV : llvm::drop_begin(SearchOrder)) {259      assert(KV.first && "JITDylibList entries must not be null");260      OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";261    }262  }263  OS << " ]";264  return OS;265}266 267raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {268  OS << "{";269  for (auto &KV : Aliases)270    OS << " " << *KV.first << ": " << KV.second.Aliasee << " "271       << KV.second.AliasFlags;272  OS << " }";273  return OS;274}275 276raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {277  switch (S) {278  case SymbolState::Invalid:279    return OS << "Invalid";280  case SymbolState::NeverSearched:281    return OS << "Never-Searched";282  case SymbolState::Materializing:283    return OS << "Materializing";284  case SymbolState::Resolved:285    return OS << "Resolved";286  case SymbolState::Emitted:287    return OS << "Emitted";288  case SymbolState::Ready:289    return OS << "Ready";290  }291  llvm_unreachable("Invalid state");292}293 294raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {295  std::lock_guard<std::mutex> Lock(SSP.PoolMutex);296  SmallVector<std::pair<StringRef, int>, 0> Vec;297  for (auto &KV : SSP.Pool)298    Vec.emplace_back(KV.first(), KV.second);299  llvm::sort(Vec, less_first());300  for (auto &[K, V] : Vec)301    OS << K << ": " << V << "\n";302  return OS;303}304 305DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)306    : DumpDir(std::move(DumpDir)),307      IdentifierOverride(std::move(IdentifierOverride)) {308 309  /// Discard any trailing separators.310  while (!this->DumpDir.empty() &&311         sys::path::is_separator(this->DumpDir.back()))312    this->DumpDir.pop_back();313}314 315Expected<std::unique_ptr<MemoryBuffer>>316DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {317  size_t Idx = 1;318 319  std::string DumpPathStem;320  raw_string_ostream(DumpPathStem)321      << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);322 323  std::string DumpPath = DumpPathStem + ".o";324  while (sys::fs::exists(DumpPath)) {325    DumpPath.clear();326    raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";327  }328 329  LLVM_DEBUG({330    dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()331           << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "332           << DumpPath << "\n";333  });334 335  std::error_code EC;336  raw_fd_ostream DumpStream(DumpPath, EC);337  if (EC)338    return errorCodeToError(EC);339  DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());340 341  return std::move(Obj);342}343 344StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {345  if (!IdentifierOverride.empty())346    return IdentifierOverride;347  StringRef Identifier = B.getBufferIdentifier();348  Identifier.consume_back(".o");349  return Identifier;350}351 352} // End namespace orc.353} // End namespace llvm.354