JITLoaderGDB.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //===- JITLoaderGDB.h - Register objects via GDB JIT interface -*- C++ -*-===//
  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/TargetProcess/JITLoaderGDB.h"
  9. #include "llvm/ExecutionEngine/JITSymbol.h"
  10. #include "llvm/Support/BinaryStreamReader.h"
  11. #include "llvm/Support/FormatVariadic.h"
  12. #include "llvm/Support/ManagedStatic.h"
  13. #include <cstdint>
  14. #include <mutex>
  15. #include <utility>
  16. #define DEBUG_TYPE "orc"
  17. // First version as landed in August 2009
  18. static constexpr uint32_t JitDescriptorVersion = 1;
  19. // Keep in sync with gdb/gdb/jit.h
  20. extern "C" {
  21. typedef enum {
  22. JIT_NOACTION = 0,
  23. JIT_REGISTER_FN,
  24. JIT_UNREGISTER_FN
  25. } jit_actions_t;
  26. struct jit_code_entry {
  27. struct jit_code_entry *next_entry;
  28. struct jit_code_entry *prev_entry;
  29. const char *symfile_addr;
  30. uint64_t symfile_size;
  31. };
  32. struct jit_descriptor {
  33. uint32_t version;
  34. // This should be jit_actions_t, but we want to be specific about the
  35. // bit-width.
  36. uint32_t action_flag;
  37. struct jit_code_entry *relevant_entry;
  38. struct jit_code_entry *first_entry;
  39. };
  40. // We put information about the JITed function in this global, which the
  41. // debugger reads. Make sure to specify the version statically, because the
  42. // debugger checks the version before we can set it during runtime.
  43. struct jit_descriptor __jit_debug_descriptor = {JitDescriptorVersion, 0,
  44. nullptr, nullptr};
  45. // Debuggers that implement the GDB JIT interface put a special breakpoint in
  46. // this function.
  47. LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
  48. // The noinline and the asm prevent calls to this function from being
  49. // optimized out.
  50. #if !defined(_MSC_VER)
  51. asm volatile("" ::: "memory");
  52. #endif
  53. }
  54. }
  55. using namespace llvm;
  56. using namespace llvm::orc;
  57. // Serialize rendezvous with the debugger as well as access to shared data.
  58. ManagedStatic<std::mutex> JITDebugLock;
  59. // Register debug object, return error message or null for success.
  60. static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
  61. LLVM_DEBUG({
  62. dbgs() << "Registering debug object with GDB JIT interface "
  63. << formatv("([{0:x16} -- {1:x16}])",
  64. reinterpret_cast<uintptr_t>(ObjAddr),
  65. reinterpret_cast<uintptr_t>(ObjAddr + Size))
  66. << "\n";
  67. });
  68. jit_code_entry *E = new jit_code_entry;
  69. E->symfile_addr = ObjAddr;
  70. E->symfile_size = Size;
  71. E->prev_entry = nullptr;
  72. std::lock_guard<std::mutex> Lock(*JITDebugLock);
  73. // Insert this entry at the head of the list.
  74. jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
  75. E->next_entry = NextEntry;
  76. if (NextEntry) {
  77. NextEntry->prev_entry = E;
  78. }
  79. __jit_debug_descriptor.first_entry = E;
  80. __jit_debug_descriptor.relevant_entry = E;
  81. // Run into the rendezvous breakpoint.
  82. __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
  83. __jit_debug_register_code();
  84. }
  85. extern "C" orc::shared::CWrapperFunctionResult
  86. llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
  87. using namespace orc::shared;
  88. return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
  89. Data, Size,
  90. [](ExecutorAddrRange R) {
  91. registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
  92. R.size());
  93. return Error::success();
  94. })
  95. .release();
  96. }
  97. extern "C" orc::shared::CWrapperFunctionResult
  98. llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
  99. using namespace orc::shared;
  100. return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
  101. Data, Size,
  102. [](ExecutorAddrRange R) {
  103. registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
  104. R.size());
  105. return Error::success();
  106. })
  107. .release();
  108. }