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