问题
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