1 //===-- JITDebugRegisterer.h - Register debug symbols for JIT -------------===// 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 // 10 // This file defines a JITDebugRegisterer object that is used by the JIT to 11 // register debug info with debuggers like GDB. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H 16 #define LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H 17 18 #include "llvm/ADT/DenseMap.h" 19 #include "llvm/Support/DataTypes.h" 20 #include <string> 21 22 // This must be kept in sync with gdb/gdb/jit.h . 23 extern "C" { 24 25 typedef enum { 26 JIT_NOACTION = 0, 27 JIT_REGISTER_FN, 28 JIT_UNREGISTER_FN 29 } jit_actions_t; 30 31 struct jit_code_entry { 32 struct jit_code_entry *next_entry; 33 struct jit_code_entry *prev_entry; 34 const char *symfile_addr; 35 uint64_t symfile_size; 36 }; 37 38 struct jit_descriptor { 39 uint32_t version; 40 // This should be jit_actions_t, but we want to be specific about the 41 // bit-width. 42 uint32_t action_flag; 43 struct jit_code_entry *relevant_entry; 44 struct jit_code_entry *first_entry; 45 }; 46 47 } 48 49 namespace llvm { 50 51 class ELFSection; 52 class Function; 53 class TargetMachine; 54 55 56 /// This class encapsulates information we want to send to the debugger. 57 /// 58 struct DebugInfo { 59 uint8_t *FnStart; 60 uint8_t *FnEnd; 61 uint8_t *EhStart; 62 uint8_t *EhEnd; 63 DebugInfoDebugInfo64 DebugInfo() : FnStart(0), FnEnd(0), EhStart(0), EhEnd(0) {} 65 }; 66 67 typedef DenseMap< const Function*, std::pair<std::string, jit_code_entry*> > 68 RegisteredFunctionsMap; 69 70 /// This class registers debug info for JITed code with an attached debugger. 71 /// Without proper debug info, GDB can't do things like source level debugging 72 /// or even produce a proper stack trace on linux-x86_64. To use this class, 73 /// whenever a function is JITed, create a DebugInfo struct and pass it to the 74 /// RegisterFunction method. The method will then do whatever is necessary to 75 /// inform the debugger about the JITed function. 76 class JITDebugRegisterer { 77 78 TargetMachine &TM; 79 80 /// FnMap - A map of functions that have been registered to the associated 81 /// temporary files. Used for cleanup. 82 RegisteredFunctionsMap FnMap; 83 84 /// MakeELF - Builds the ELF file in memory and returns a std::string that 85 /// contains the ELF. 86 std::string MakeELF(const Function *F, DebugInfo &I); 87 88 public: 89 JITDebugRegisterer(TargetMachine &tm); 90 91 /// ~JITDebugRegisterer - Unregisters all code and frees symbol files. 92 /// 93 ~JITDebugRegisterer(); 94 95 /// RegisterFunction - Register debug info for the given function with an 96 /// attached debugger. Clients must call UnregisterFunction on all 97 /// registered functions before deleting them to free the associated symbol 98 /// file and unregister it from the debugger. 99 void RegisterFunction(const Function *F, DebugInfo &I); 100 101 /// UnregisterFunction - Unregister the debug info for the given function 102 /// from the debugger and free associated memory. 103 void UnregisterFunction(const Function *F); 104 105 private: 106 /// UnregisterFunctionInternal - Unregister the debug info for the given 107 /// function from the debugger and delete any temporary files. The private 108 /// version of this method does not remove the function from FnMap so that it 109 /// can be called while iterating over FnMap. 110 void UnregisterFunctionInternal(RegisteredFunctionsMap::iterator I); 111 112 }; 113 114 } // end namespace llvm 115 116 #endif // LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H 117