Cannot execute function JITed by LLVM

那年仲夏 提交于 2019-12-11 09:41:29

问题


Using LLVM-5.0 I implemented a minimal testcase that creates assembly for a function returning the 32bit integer "42" at runtime and executes it.

Using llvm::ExecutionEngine I was able to generate the following code at runtime (displayed with gdb):

0x7ffff7ff5000  mov    $0x2a,%eax                                                                                                                                                                             
0x7ffff7ff5005  retq

Calling the function yields

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

My working theory is that the memory page LLVM wrote the code on is not executable.

Is this really a DEP problem? If yes how can I make JITed functions from LLVM actually executable?

Appendix: The actual testcase

#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;
}

回答1:


The method getPointerToFunction is deprecated for the MCJIT execution engine according to the sources.

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

Therefore I would use addModule(std::move(module)) followed by getFunctionAddress(functionName). This should "finalize" code generation by changing the permissions for the memory.



来源:https://stackoverflow.com/questions/46884340/cannot-execute-function-jited-by-llvm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!