2017-10-23 3 views
1

Mit LLVM-5.0 habe ich einen minimalen Testfall implementiert, der eine Assembly für eine Funktion erstellt, die zur Laufzeit die 32-Bit-Ganzzahl "42" zurückgibt und ausführt.Kann die Funktion JITed von LLVM nicht ausführen

Mit llvm::ExecutionEngine konnte ich den folgenden Code zur Laufzeit (angezeigt mit GDB) erzeugen:

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

die Funktion Ausbeuten Aufruf

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

Meine Arbeits Theorie ist, dass die Speicherseite LLVM schrieb Der Code ist nicht ausführbar.

Ist das wirklich ein DEP-Problem? Wenn ja, wie kann ich JITed-Funktionen von LLVM tatsächlich ausführbar machen?

Anhang: Die eigentliche Testfall

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

Antwort

1

Verfahren getPointerToFunction für die MCJIT Ausführungs-Engine weiterentwickelt, wird entsprechend der Quellen.

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

Deshalb würde ich addModule(std::move(module)) von getFunctionAddress(functionName) gefolgt verwenden. Dies sollte die Codegenerierung "finalisieren", indem die Berechtigungen für den Speicher geändert werden.

Verwandte Themen