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 using namespace llvm::orc; 68 69 // Serialize rendezvous with the debugger as well as access to shared data. 70 ManagedStatic<std::mutex> JITDebugLock; 71 72 // Register debug object, return error message or null for success. 73 static void registerJITLoaderGDBImpl(ExecutorAddrRange DebugObjRange) { 74 jit_code_entry *E = new jit_code_entry; 75 E->symfile_addr = DebugObjRange.Start.toPtr<const char *>(); 76 E->symfile_size = DebugObjRange.size().getValue(); 77 E->prev_entry = nullptr; 78 79 std::lock_guard<std::mutex> Lock(*JITDebugLock); 80 81 // Insert this entry at the head of the list. 82 jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry; 83 E->next_entry = NextEntry; 84 if (NextEntry) { 85 NextEntry->prev_entry = E; 86 } 87 88 __jit_debug_descriptor.first_entry = E; 89 __jit_debug_descriptor.relevant_entry = E; 90 91 // Run into the rendezvous breakpoint. 92 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; 93 __jit_debug_register_code(); 94 } 95 96 extern "C" orc::shared::CWrapperFunctionResult 97 llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) { 98 using namespace orc::shared; 99 return WrapperFunction<void(SPSExecutorAddrRange)>::handle( 100 Data, Size, registerJITLoaderGDBImpl) 101 .release(); 102 } 103