From 3567c43fb5fa297de0d6a3bc663a6445b39f4d2c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 15 Jan 2021 20:54:00 +0300 Subject: [PATCH] LLVM: generate trampolines for "null" functions Embed name into the trampoline for easier debugging. Only warn about it during the compilation phase. --- Utilities/JIT.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/Utilities/JIT.cpp b/Utilities/JIT.cpp index a8ff9785da..83c27cf094 100644 --- a/Utilities/JIT.cpp +++ b/Utilities/JIT.cpp @@ -305,6 +305,49 @@ const bool jit_initialize = []() -> bool return true; }(); +[[noreturn]] static void null(const char* name) +{ + fmt::throw_exception("Null function: %s", name); +} + +static shared_mutex null_mtx; + +static std::unordered_map null_funcs; + +static u64 make_null_function(const std::string& name) +{ + std::lock_guard lock(null_mtx); + + if (u64& func_ptr = null_funcs[name]) [[likely]] + { + // Already exists + return func_ptr; + } + else + { + using namespace asmjit; + + // Build a "null" function that contains its name + const auto func = build_function_asm([&](X86Assembler& c, auto& args) + { + Label data = c.newLabel(); + c.lea(args[0], x86::qword_ptr(data, 0)); + c.jmp(imm_ptr(&null)); + c.align(kAlignCode, 16); + c.bind(data); + + // Copy function name bytes + for (char ch : name) + c.db(ch); + c.db(0); + c.align(kAlignData, 16); + }); + + func_ptr = reinterpret_cast(func); + return func_ptr; + } +} + // Simple memory manager struct MemoryManager1 : llvm::RTDyldMemoryManager { @@ -327,19 +370,14 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager utils::memory_release(ptr, c_max_size * 2); } - [[noreturn]] static void null() - { - fmt::throw_exception("Null function"); - } - llvm::JITSymbol findSymbol(const std::string& name) override { u64 addr = RTDyldMemoryManager::getSymbolAddress(name); if (!addr) { - jit_log.fatal("Function '%s' linked but not found.", name); - addr = reinterpret_cast(&null); + jit_log.error("Function '%s' linked but not found.", name); + addr = make_null_function(name); } return {addr, llvm::JITSymbolFlags::Exported}; @@ -409,6 +447,19 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager { } + llvm::JITSymbol findSymbol(const std::string& name) override + { + u64 addr = RTDyldMemoryManager::getSymbolAddress(name); + + if (!addr) + { + jit_log.error("Function '%s' linked but not found.", name); + addr = make_null_function(name); + } + + return {addr, llvm::JITSymbolFlags::Exported}; + } + u8* allocateCodeSection(uptr size, uint align, uint sec_id, llvm::StringRef sec_name) override { return jit_runtime::alloc(size, align, true);