【问题标题】:Cannot execute function JITed by LLVM无法执行 LLVM 的 JIT 函数
【发布时间】:2017-10-23 20:02:51
【问题描述】:

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

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

0x7ffff7ff5000  mov    $0x2a,%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;
}

【问题讨论】:

    标签: llvm jit data-execution-prevention


    【解决方案1】:

    根据来源,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)。这应该通过更改内存的权限来“完成”代码生成。

    【讨论】:

      猜你喜欢
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 2015-05-05
      • 2011-09-03
      • 2011-03-31
      • 2023-03-19
      • 2011-05-24
      • 1970-01-01
      相关资源
      最近更新 更多