1 //===- JITLoaderGDB.h - Register objects via GDB JIT interface -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
11 #include "llvm/ExecutionEngine/JITSymbol.h"
12 #include "llvm/Support/BinaryStreamReader.h"
13 #include "llvm/Support/FormatVariadic.h"
14 #include "llvm/Support/ManagedStatic.h"
20 #define DEBUG_TYPE "orc"
22 // First version as landed in August 2009
23 static constexpr uint32_t JitDescriptorVersion
= 1;
25 // Keep in sync with gdb/gdb/jit.h
34 struct jit_code_entry
{
35 struct jit_code_entry
*next_entry
;
36 struct jit_code_entry
*prev_entry
;
37 const char *symfile_addr
;
38 uint64_t symfile_size
;
41 struct jit_descriptor
{
43 // This should be jit_actions_t, but we want to be specific about the
46 struct jit_code_entry
*relevant_entry
;
47 struct jit_code_entry
*first_entry
;
50 // We put information about the JITed function in this global, which the
51 // debugger reads. Make sure to specify the version statically, because the
52 // debugger checks the version before we can set it during runtime.
53 struct jit_descriptor __jit_debug_descriptor
= {JitDescriptorVersion
, 0,
56 // Debuggers that implement the GDB JIT interface put a special breakpoint in
58 LLVM_ATTRIBUTE_NOINLINE
void __jit_debug_register_code() {
59 // The noinline and the asm prevent calls to this function from being
61 #if !defined(_MSC_VER)
62 asm volatile("" ::: "memory");
68 using namespace llvm::orc
;
70 // Serialize rendezvous with the debugger as well as access to shared data.
71 ManagedStatic
<std::mutex
> JITDebugLock
;
73 // Register debug object, return error message or null for success.
74 static void registerJITLoaderGDBImpl(const char *ObjAddr
, size_t Size
) {
76 dbgs() << "Registering debug object with GDB JIT interface "
77 << formatv("([{0:x16} -- {1:x16}])",
78 reinterpret_cast<uintptr_t>(ObjAddr
),
79 reinterpret_cast<uintptr_t>(ObjAddr
+ Size
))
83 jit_code_entry
*E
= new jit_code_entry
;
84 E
->symfile_addr
= ObjAddr
;
85 E
->symfile_size
= Size
;
86 E
->prev_entry
= nullptr;
88 std::lock_guard
<std::mutex
> Lock(*JITDebugLock
);
90 // Insert this entry at the head of the list.
91 jit_code_entry
*NextEntry
= __jit_debug_descriptor
.first_entry
;
92 E
->next_entry
= NextEntry
;
94 NextEntry
->prev_entry
= E
;
97 __jit_debug_descriptor
.first_entry
= E
;
98 __jit_debug_descriptor
.relevant_entry
= E
;
100 // Run into the rendezvous breakpoint.
101 __jit_debug_descriptor
.action_flag
= JIT_REGISTER_FN
;
102 __jit_debug_register_code();
105 extern "C" orc::shared::CWrapperFunctionResult
106 llvm_orc_registerJITLoaderGDBAllocAction(const char *Data
, size_t Size
) {
107 using namespace orc::shared
;
108 return WrapperFunction
<SPSError(SPSExecutorAddrRange
)>::handle(
110 [](ExecutorAddrRange R
) {
111 registerJITLoaderGDBImpl(R
.Start
.toPtr
<const char *>(),
113 return Error::success();
118 extern "C" orc::shared::CWrapperFunctionResult
119 llvm_orc_registerJITLoaderGDBWrapper(const char *Data
, uint64_t Size
) {
120 using namespace orc::shared
;
121 return WrapperFunction
<SPSError(SPSExecutorAddrRange
)>::handle(
123 [](ExecutorAddrRange R
) {
124 registerJITLoaderGDBImpl(R
.Start
.toPtr
<const char *>(),
126 return Error::success();