xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp (revision 1edc20b76953d9ef571b0bcf89b206b98ed13d9b)
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/FormatVariadic.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  // Register debug object, return error message or null for success.
70  static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
71    LLVM_DEBUG({
72      dbgs() << "Registering debug object with GDB JIT interface "
73             << formatv("([{0:x16} -- {1:x16}])",
74                        reinterpret_cast<uintptr_t>(ObjAddr),
75                        reinterpret_cast<uintptr_t>(ObjAddr + Size))
76             << "\n";
77    });
78  
79    jit_code_entry *E = new jit_code_entry;
80    E->symfile_addr = ObjAddr;
81    E->symfile_size = Size;
82    E->prev_entry = nullptr;
83  
84    // Serialize rendezvous with the debugger as well as access to shared data.
85    static std::mutex JITDebugLock;
86    std::lock_guard<std::mutex> Lock(JITDebugLock);
87  
88    // Insert this entry at the head of the list.
89    jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
90    E->next_entry = NextEntry;
91    if (NextEntry) {
92      NextEntry->prev_entry = E;
93    }
94  
95    __jit_debug_descriptor.first_entry = E;
96    __jit_debug_descriptor.relevant_entry = E;
97  
98    // Run into the rendezvous breakpoint.
99    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
100    __jit_debug_register_code();
101  }
102  
103  extern "C" orc::shared::CWrapperFunctionResult
104  llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
105    using namespace orc::shared;
106    return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
107               Data, Size,
108               [](ExecutorAddrRange R) {
109                 registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
110                                          R.size());
111                 return Error::success();
112               })
113        .release();
114  }
115  
116  extern "C" orc::shared::CWrapperFunctionResult
117  llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
118    using namespace orc::shared;
119    return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
120               Data, Size,
121               [](ExecutorAddrRange R) {
122                 registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
123                                          R.size());
124                 return Error::success();
125               })
126        .release();
127  }
128