xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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/Support/Compiler.h"
12 #include "llvm/Support/FormatVariadic.h"
13 
14 #include <cstdint>
15 #include <mutex>
16 
17 #define DEBUG_TYPE "orc"
18 
19 // First version as landed in August 2009
20 static constexpr uint32_t JitDescriptorVersion = 1;
21 
22 extern "C" {
23 
24 // We put information about the JITed function in this global, which the
25 // debugger reads.  Make sure to specify the version statically, because the
26 // debugger checks the version before we can set it during runtime.
27 LLVM_ABI LLVM_ALWAYS_EXPORT struct jit_descriptor __jit_debug_descriptor = {
28     JitDescriptorVersion, 0, nullptr, nullptr};
29 
30 // Debuggers that implement the GDB JIT interface put a special breakpoint in
31 // this function.
32 LLVM_ABI LLVM_ALWAYS_EXPORT LLVM_ATTRIBUTE_NOINLINE void
33 __jit_debug_register_code() {
34   // The noinline and the asm prevent calls to this function from being
35   // optimized out.
36 #if !defined(_MSC_VER)
37   asm volatile("" ::: "memory");
38 #endif
39 }
40 }
41 
42 using namespace llvm;
43 using namespace llvm::orc;
44 
45 // Register debug object, return error message or null for success.
46 static void appendJITDebugDescriptor(const char *ObjAddr, size_t Size) {
47   LLVM_DEBUG({
48     dbgs() << "Adding debug object to GDB JIT interface "
49            << formatv("([{0:x16} -- {1:x16}])",
50                       reinterpret_cast<uintptr_t>(ObjAddr),
51                       reinterpret_cast<uintptr_t>(ObjAddr + Size))
52            << "\n";
53   });
54 
55   jit_code_entry *E = new jit_code_entry;
56   E->symfile_addr = ObjAddr;
57   E->symfile_size = Size;
58   E->prev_entry = nullptr;
59 
60   // Serialize rendezvous with the debugger as well as access to shared data.
61   static std::mutex JITDebugLock;
62   std::lock_guard<std::mutex> Lock(JITDebugLock);
63 
64   // Insert this entry at the head of the list.
65   jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
66   E->next_entry = NextEntry;
67   if (NextEntry) {
68     NextEntry->prev_entry = E;
69   }
70 
71   __jit_debug_descriptor.first_entry = E;
72   __jit_debug_descriptor.relevant_entry = E;
73   __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
74 }
75 
76 extern "C" orc::shared::CWrapperFunctionResult
77 llvm_orc_registerJITLoaderGDBAllocAction(const char *ArgData, size_t ArgSize) {
78   using namespace orc::shared;
79   return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
80              ArgData, ArgSize,
81              [](ExecutorAddrRange R, bool AutoRegisterCode) {
82                appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
83                                         R.size());
84                // Run into the rendezvous breakpoint.
85                if (AutoRegisterCode)
86                  __jit_debug_register_code();
87                return Error::success();
88              })
89       .release();
90 }
91 
92 extern "C" orc::shared::CWrapperFunctionResult
93 llvm_orc_registerJITLoaderGDBWrapper(const char *ArgData, size_t ArgSize) {
94   using namespace orc::shared;
95   return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
96              ArgData, ArgSize,
97              [](ExecutorAddrRange R, bool AutoRegisterCode) {
98                appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
99                                         R.size());
100                // Run into the rendezvous breakpoint.
101                if (AutoRegisterCode)
102                  __jit_debug_register_code();
103                return Error::success();
104              })
105       .release();
106 }
107