无法执行由 LLVM JITed 的函数

Cannot execute function JITed by LLVM

我使用 LLVM-5.0 实现了一个最小的测试用例,它为一个在运行时返回 32 位整数“42”的函数创建程序集并执行它。

使用 llvm::ExecutionEngine 我能够在运行时生成以下代码(用 gdb 显示):

0x7ffff7ff5000  mov    [=10=]x2a,%eax                                                                                                                                                                             
0x7ffff7ff5005  retq

调用函数产生

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ff5000 in ?? ()

我的工作理论是 LLVM 写入代码的内存页面不可执行。

这真的是 DEP 问题吗?如果是,我如何使 LLVM 中的 JITed 函数真正可执行?

附录:实际测试用例

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Verifier.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/TargetSelect.h>

#include <iostream>

int main() {
    // Initialize global state
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    llvm::InitializeNativeTargetAsmParser();

    // Initialize local state
    llvm::LLVMContext context;

    // Create the module that will be compiled
    std::unique_ptr<llvm::Module> module(new llvm::Module("jit", context));

    // Create function type
    std::vector<llvm::Type*> arg_types;
    llvm::FunctionType* func_type = llvm::FunctionType::get(llvm::Type::getInt32Ty(context), arg_types, false);

    // Create actual function
    llvm::Function* func = llvm::Function::Create(func_type, llvm::Function::LinkageTypes::ExternalLinkage, "anon", module.get());

    // Define function body
    llvm::IRBuilder<> builder(context);
    llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", func);
    builder.SetInsertPoint(block);
    builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 42));

    // Verify function
    llvm::verifyFunction(*func);

    // Build the execution engine
    std::string error;
    llvm::EngineBuilder engine_builder(std::move(module));
    engine_builder.setErrorStr(&error);
    engine_builder.setEngineKind(llvm::EngineKind::JIT);
    std::unique_ptr<llvm::ExecutionEngine> engine(engine_builder.create());
    if (!engine) {
        std::cerr << error << std::endl;
        return 1;
    }

    // Get a pointer to the JITed function
    void* jit_ptr = engine->getPointerToFunction(func);
    auto function = reinterpret_cast<int32_t(*)()>(jit_ptr);

    // Execute the JITed function
    std::cout << function() << std::endl;
    return 0;
}

根据消息来源,MCJIT 执行引擎不推荐使用方法 getPointerToFunction。

  /// getPointerToFunction - (...)
  /// This function is deprecated for the MCJIT execution engine.  Use
  /// getFunctionAddress instead.
  virtual void *getPointerToFunction(Function *F) = 0;

因此我会使用 addModule(std::move(module)),然后是 getFunctionAddress(functionName)。这应该 "finalize" 通过更改内存权限来生成代码。