DebugUtils.cpp 11 KB

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