ExecutionUtils.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //===---- ExecutionUtils.cpp - Utilities for executing functions in lli ---===//
  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 "ExecutionUtils.h"
  9. #include "llvm/Support/FileSystem.h"
  10. #include "llvm/Support/FormatVariadic.h"
  11. #include "llvm/Support/raw_ostream.h"
  12. #include <cstdint>
  13. #include <vector>
  14. // Declarations follow the GDB JIT interface (version 1, 2009) and must match
  15. // those of the DYLD used for testing. See:
  16. //
  17. // llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
  18. // llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
  19. //
  20. typedef enum {
  21. JIT_NOACTION = 0,
  22. JIT_REGISTER_FN,
  23. JIT_UNREGISTER_FN
  24. } jit_actions_t;
  25. struct jit_code_entry {
  26. struct jit_code_entry *next_entry;
  27. struct jit_code_entry *prev_entry;
  28. const char *symfile_addr;
  29. uint64_t symfile_size;
  30. };
  31. struct jit_descriptor {
  32. uint32_t version;
  33. // This should be jit_actions_t, but we want to be specific about the
  34. // bit-width.
  35. uint32_t action_flag;
  36. struct jit_code_entry *relevant_entry;
  37. struct jit_code_entry *first_entry;
  38. };
  39. namespace llvm {
  40. template <typename... Ts> static void outsv(const char *Fmt, Ts &&...Vals) {
  41. outs() << formatv(Fmt, Vals...);
  42. }
  43. static const char *actionFlagToStr(uint32_t ActionFlag) {
  44. switch (ActionFlag) {
  45. case JIT_NOACTION:
  46. return "JIT_NOACTION";
  47. case JIT_REGISTER_FN:
  48. return "JIT_REGISTER_FN";
  49. case JIT_UNREGISTER_FN:
  50. return "JIT_UNREGISTER_FN";
  51. }
  52. return "<invalid action_flag>";
  53. }
  54. // Sample output:
  55. //
  56. // Reading __jit_debug_descriptor at 0x0000000000404048
  57. //
  58. // Version: 0
  59. // Action: JIT_REGISTER_FN
  60. //
  61. // Entry Symbol File Size Previous Entry
  62. // [ 0] 0x0000000000451290 0x0000000000002000 200 0x0000000000000000
  63. // [ 1] 0x0000000000451260 0x0000000000001000 100 0x0000000000451290
  64. // ...
  65. //
  66. static void dumpDebugDescriptor(void *Addr) {
  67. outsv("Reading __jit_debug_descriptor at {0}\n\n", Addr);
  68. jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
  69. outsv("Version: {0}\n", Descriptor->version);
  70. outsv("Action: {0}\n\n", actionFlagToStr(Descriptor->action_flag));
  71. outsv("{0,11} {1,24} {2,15} {3,14}\n", "Entry", "Symbol File", "Size",
  72. "Previous Entry");
  73. unsigned Idx = 0;
  74. for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
  75. outsv("[{0,2}] {1:X16} {2:X16} {3,8:D} {4}\n", Idx++, Entry,
  76. reinterpret_cast<const void *>(Entry->symfile_addr),
  77. Entry->symfile_size, Entry->prev_entry);
  78. }
  79. static LLIBuiltinFunctionGenerator *Generator = nullptr;
  80. static void dumpDebugObjects(void *Addr) {
  81. jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
  82. for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
  83. Generator->appendDebugObject(Entry->symfile_addr, Entry->symfile_size);
  84. }
  85. LLIBuiltinFunctionGenerator::LLIBuiltinFunctionGenerator(
  86. std::vector<BuiltinFunctionKind> Enabled, orc::MangleAndInterner &Mangle)
  87. : TestOut(nullptr) {
  88. Generator = this;
  89. for (BuiltinFunctionKind F : Enabled) {
  90. switch (F) {
  91. case BuiltinFunctionKind::DumpDebugDescriptor:
  92. expose(Mangle("__dump_jit_debug_descriptor"), &dumpDebugDescriptor);
  93. break;
  94. case BuiltinFunctionKind::DumpDebugObjects:
  95. expose(Mangle("__dump_jit_debug_objects"), &dumpDebugObjects);
  96. TestOut = createToolOutput();
  97. break;
  98. }
  99. }
  100. }
  101. Error LLIBuiltinFunctionGenerator::tryToGenerate(
  102. orc::LookupState &LS, orc::LookupKind K, orc::JITDylib &JD,
  103. orc::JITDylibLookupFlags JDLookupFlags,
  104. const orc::SymbolLookupSet &Symbols) {
  105. orc::SymbolMap NewSymbols;
  106. for (const auto &NameFlags : Symbols) {
  107. auto It = BuiltinFunctions.find(NameFlags.first);
  108. if (It != BuiltinFunctions.end())
  109. NewSymbols.insert(*It);
  110. }
  111. if (NewSymbols.empty())
  112. return Error::success();
  113. return JD.define(absoluteSymbols(std::move(NewSymbols)));
  114. }
  115. // static
  116. std::unique_ptr<ToolOutputFile>
  117. LLIBuiltinFunctionGenerator::createToolOutput() {
  118. std::error_code EC;
  119. auto TestOut = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);
  120. if (EC) {
  121. errs() << "Error creating tool output file: " << EC.message() << '\n';
  122. exit(1);
  123. }
  124. return TestOut;
  125. }
  126. } // namespace llvm