问题描述
使用LLVM-5.0,我实现了一个最小的测试用例,该用例创建了一个函数的汇编,该函数在运行时返回32位整数"42"并执行该函数.
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.
使用llvm::ExecutionEngine
,我能够在运行时生成以下代码(与gdb一起显示):
Using llvm::ExecutionEngine
I was able to generate the following code at runtime (displayed with gdb):
0x7ffff7ff5000 mov $0x2a,%eax
0x7ffff7ff5005 retq
调用函数会产生
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ff5000 in ?? ()
我的工作原理是LLVM在其上写代码的内存页面不可执行.
My working theory is that the memory page LLVM wrote the code on is not executable.
这真的是DEP问题吗?如果是,如何使LLVM的JITed函数真正可执行?
Is this really a DEP problem? If yes how can I make JITed functions from LLVM actually executable?
附录:实际测试用例
#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方法.
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;
因此,我将使用addModule(std::move(module))
,然后使用getFunctionAddress(functionName)
.这应该通过更改内存的权限来完成"代码生成.
Therefore I would use addModule(std::move(module))
followed by getFunctionAddress(functionName)
. This should "finalize" code generation by changing the permissions for the memory.
这篇关于无法执行LLVM的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!