Lang Hames ef391df2b6 [ORC] Rename ExecutorAddress to ExecutorAddr.
Removing the 'ess' suffix improves the ergonomics without sacrificing clarity.
Since this class is likely to be used more frequently in the future it's worth
some short term pain to fix this now.
2021-09-23 20:35:17 -07:00

102 lines
3.1 KiB
C++

//===- JITLoaderGDB.h - Register objects via GDB JIT interface -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/ManagedStatic.h"
#include <cstdint>
#include <mutex>
#include <utility>
#define DEBUG_TYPE "orc"
// First version as landed in August 2009
static constexpr uint32_t JitDescriptorVersion = 1;
// Keep in sync with gdb/gdb/jit.h
extern "C" {
typedef enum {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} jit_actions_t;
struct jit_code_entry {
struct jit_code_entry *next_entry;
struct jit_code_entry *prev_entry;
const char *symfile_addr;
uint64_t symfile_size;
};
struct jit_descriptor {
uint32_t version;
// This should be jit_actions_t, but we want to be specific about the
// bit-width.
uint32_t action_flag;
struct jit_code_entry *relevant_entry;
struct jit_code_entry *first_entry;
};
// We put information about the JITed function in this global, which the
// debugger reads. Make sure to specify the version statically, because the
// debugger checks the version before we can set it during runtime.
struct jit_descriptor __jit_debug_descriptor = {JitDescriptorVersion, 0,
nullptr, nullptr};
// Debuggers that implement the GDB JIT interface put a special breakpoint in
// this function.
LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
// The noinline and the asm prevent calls to this function from being
// optimized out.
#if !defined(_MSC_VER)
asm volatile("" ::: "memory");
#endif
}
}
using namespace llvm;
// Serialize rendezvous with the debugger as well as access to shared data.
ManagedStatic<std::mutex> JITDebugLock;
// Register debug object, return error message or null for success.
static void registerJITLoaderGDBImpl(JITTargetAddress Addr, uint64_t Size) {
jit_code_entry *E = new jit_code_entry;
E->symfile_addr = jitTargetAddressToPointer<const char *>(Addr);
E->symfile_size = Size;
E->prev_entry = nullptr;
std::lock_guard<std::mutex> Lock(*JITDebugLock);
// Insert this entry at the head of the list.
jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
E->next_entry = NextEntry;
if (NextEntry) {
NextEntry->prev_entry = E;
}
__jit_debug_descriptor.first_entry = E;
__jit_debug_descriptor.relevant_entry = E;
// Run into the rendezvous breakpoint.
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
__jit_debug_register_code();
}
extern "C" orc::shared::detail::CWrapperFunctionResult
llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
using namespace orc::shared;
return WrapperFunction<void(SPSExecutorAddr, uint64_t)>::handle(
Data, Size, registerJITLoaderGDBImpl)
.release();
}