91 lines · cpp
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-exception6//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 200920static constexpr uint32_t JitDescriptorVersion = 1;21 22extern "C" {23 24// We put information about the JITed function in this global, which the25// debugger reads. Make sure to specify the version statically, because the26// debugger checks the version before we can set it during runtime.27LLVM_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 in31// this function.32LLVM_ABI LLVM_ALWAYS_EXPORT LLVM_ATTRIBUTE_NOINLINE void33__jit_debug_register_code() {34 // The noinline and the asm prevent calls to this function from being35 // optimized out.36#if !defined(_MSC_VER)37 asm volatile("" ::: "memory");38#endif39}40}41 42using namespace llvm;43using namespace llvm::orc;44 45// Register debug object, return error message or null for success.46static 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 76extern "C" orc::shared::CWrapperFunctionResult77llvm_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