GDBRegistrationListener.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //===----- GDBRegistrationListener.cpp - Registers objects with GDB -------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/ADT/DenseMap.h"
  10. #include "llvm/ExecutionEngine/JITEventListener.h"
  11. #include "llvm/Object/ObjectFile.h"
  12. #include "llvm/Support/Compiler.h"
  13. #include "llvm/Support/ErrorHandling.h"
  14. #include "llvm/Support/ManagedStatic.h"
  15. #include "llvm/Support/Mutex.h"
  16. #include "llvm/Support/MutexGuard.h"
  17. using namespace llvm;
  18. using namespace llvm::object;
  19. // This must be kept 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 = { 1, 0, nullptr, nullptr };
  44. // Debuggers puts a breakpoint in this function.
  45. LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
  46. // The noinline and the asm prevent calls to this function from being
  47. // optimized out.
  48. #if !defined(_MSC_VER)
  49. asm volatile("":::"memory");
  50. #endif
  51. }
  52. }
  53. namespace {
  54. struct RegisteredObjectInfo {
  55. RegisteredObjectInfo() {}
  56. RegisteredObjectInfo(std::size_t Size, jit_code_entry *Entry,
  57. OwningBinary<ObjectFile> Obj)
  58. : Size(Size), Entry(Entry), Obj(std::move(Obj)) {}
  59. RegisteredObjectInfo(RegisteredObjectInfo &&Other)
  60. : Size(Other.Size), Entry(Other.Entry), Obj(std::move(Other.Obj)) {}
  61. RegisteredObjectInfo& operator=(RegisteredObjectInfo &&Other) {
  62. Size = Other.Size;
  63. Entry = Other.Entry;
  64. Obj = std::move(Other.Obj);
  65. return *this;
  66. }
  67. std::size_t Size;
  68. jit_code_entry *Entry;
  69. OwningBinary<ObjectFile> Obj;
  70. };
  71. // Buffer for an in-memory object file in executable memory
  72. typedef llvm::DenseMap< const char*, RegisteredObjectInfo>
  73. RegisteredObjectBufferMap;
  74. /// Global access point for the JIT debugging interface designed for use with a
  75. /// singleton toolbox. Handles thread-safe registration and deregistration of
  76. /// object files that are in executable memory managed by the client of this
  77. /// class.
  78. class GDBJITRegistrationListener : public JITEventListener {
  79. /// A map of in-memory object files that have been registered with the
  80. /// JIT interface.
  81. RegisteredObjectBufferMap ObjectBufferMap;
  82. public:
  83. /// Instantiates the JIT service.
  84. GDBJITRegistrationListener() : ObjectBufferMap() {}
  85. /// Unregisters each object that was previously registered and releases all
  86. /// internal resources.
  87. ~GDBJITRegistrationListener() override;
  88. /// Creates an entry in the JIT registry for the buffer @p Object,
  89. /// which must contain an object file in executable memory with any
  90. /// debug information for the debugger.
  91. void NotifyObjectEmitted(const ObjectFile &Object,
  92. const RuntimeDyld::LoadedObjectInfo &L) override;
  93. /// Removes the internal registration of @p Object, and
  94. /// frees associated resources.
  95. /// Returns true if @p Object was found in ObjectBufferMap.
  96. void NotifyFreeingObject(const ObjectFile &Object) override;
  97. private:
  98. /// Deregister the debug info for the given object file from the debugger
  99. /// and delete any temporary copies. This private method does not remove
  100. /// the function from Map so that it can be called while iterating over Map.
  101. void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
  102. };
  103. /// Lock used to serialize all jit registration events, since they
  104. /// modify global variables.
  105. ManagedStatic<sys::Mutex> JITDebugLock;
  106. /// Do the registration.
  107. void NotifyDebugger(jit_code_entry* JITCodeEntry) {
  108. __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
  109. // Insert this entry at the head of the list.
  110. JITCodeEntry->prev_entry = nullptr;
  111. jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
  112. JITCodeEntry->next_entry = NextEntry;
  113. if (NextEntry) {
  114. NextEntry->prev_entry = JITCodeEntry;
  115. }
  116. __jit_debug_descriptor.first_entry = JITCodeEntry;
  117. __jit_debug_descriptor.relevant_entry = JITCodeEntry;
  118. __jit_debug_register_code();
  119. }
  120. GDBJITRegistrationListener::~GDBJITRegistrationListener() {
  121. // Free all registered object files.
  122. llvm::MutexGuard locked(*JITDebugLock);
  123. for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(),
  124. E = ObjectBufferMap.end();
  125. I != E; ++I) {
  126. // Call the private method that doesn't update the map so our iterator
  127. // doesn't break.
  128. deregisterObjectInternal(I);
  129. }
  130. ObjectBufferMap.clear();
  131. }
  132. void GDBJITRegistrationListener::NotifyObjectEmitted(
  133. const ObjectFile &Object,
  134. const RuntimeDyld::LoadedObjectInfo &L) {
  135. OwningBinary<ObjectFile> DebugObj = L.getObjectForDebug(Object);
  136. // Bail out if debug objects aren't supported.
  137. if (!DebugObj.getBinary())
  138. return;
  139. const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart();
  140. size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize();
  141. const char *Key = Object.getMemoryBufferRef().getBufferStart();
  142. assert(Key && "Attempt to register a null object with a debugger.");
  143. llvm::MutexGuard locked(*JITDebugLock);
  144. assert(ObjectBufferMap.find(Key) == ObjectBufferMap.end() &&
  145. "Second attempt to perform debug registration.");
  146. jit_code_entry* JITCodeEntry = new jit_code_entry();
  147. if (!JITCodeEntry) {
  148. llvm::report_fatal_error(
  149. "Allocation failed when registering a JIT entry!\n");
  150. } else {
  151. JITCodeEntry->symfile_addr = Buffer;
  152. JITCodeEntry->symfile_size = Size;
  153. ObjectBufferMap[Key] = RegisteredObjectInfo(Size, JITCodeEntry,
  154. std::move(DebugObj));
  155. NotifyDebugger(JITCodeEntry);
  156. }
  157. }
  158. void GDBJITRegistrationListener::NotifyFreeingObject(const ObjectFile& Object) {
  159. const char *Key = Object.getMemoryBufferRef().getBufferStart();
  160. llvm::MutexGuard locked(*JITDebugLock);
  161. RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Key);
  162. if (I != ObjectBufferMap.end()) {
  163. deregisterObjectInternal(I);
  164. ObjectBufferMap.erase(I);
  165. }
  166. }
  167. void GDBJITRegistrationListener::deregisterObjectInternal(
  168. RegisteredObjectBufferMap::iterator I) {
  169. jit_code_entry*& JITCodeEntry = I->second.Entry;
  170. // Do the unregistration.
  171. {
  172. __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
  173. // Remove the jit_code_entry from the linked list.
  174. jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
  175. jit_code_entry* NextEntry = JITCodeEntry->next_entry;
  176. if (NextEntry) {
  177. NextEntry->prev_entry = PrevEntry;
  178. }
  179. if (PrevEntry) {
  180. PrevEntry->next_entry = NextEntry;
  181. }
  182. else {
  183. assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
  184. __jit_debug_descriptor.first_entry = NextEntry;
  185. }
  186. // Tell the debugger which entry we removed, and unregister the code.
  187. __jit_debug_descriptor.relevant_entry = JITCodeEntry;
  188. __jit_debug_register_code();
  189. }
  190. delete JITCodeEntry;
  191. JITCodeEntry = nullptr;
  192. }
  193. llvm::ManagedStatic<GDBJITRegistrationListener> GDBRegListener;
  194. } // end namespace
  195. namespace llvm {
  196. JITEventListener* JITEventListener::createGDBRegistrationListener() {
  197. return &*GDBRegListener;
  198. }
  199. } // namespace llvm