Esempio n. 1
0
bool
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
                                           ExecutionContext &exe_ctx,
                                           lldb::ClangExpressionVariableSP &result,
                                           lldb::addr_t function_stack_bottom,
                                           lldb::addr_t function_stack_top)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
        log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");

    if (!m_dematerializer_sp)
    {
        error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
        return false;
    }

    Error dematerialize_error;

    m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);

    if (!dematerialize_error.Success())
    {
        error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
        return false;
    }

    if (result)
        result->TransferAddress();

    m_dematerializer_sp.reset();

    return true;
}
Esempio n. 2
0
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, 
                                            lldb::addr_t &func_addr, 
                                            lldb::addr_t &func_end, 
                                            ExecutionContext &exe_ctx,
                                            IRForTarget::StaticDataAllocator *data_allocator,
                                            bool &evaluated_statically,
                                            lldb::ClangExpressionVariableSP &const_result,
                                            ExecutionPolicy execution_policy)
{
    func_allocation_addr = LLDB_INVALID_ADDRESS;
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    std::auto_ptr<llvm::ExecutionEngine> execution_engine;
    
    Error err;
    
    llvm::Module *module = m_code_generator->ReleaseModule();

    if (!module)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }
    
    // Find the actual name of the function (it's often mangled somehow)
    
    std::string function_name;
    
    if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
        return err;
    }
    else
    {
        if (log)
            log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName());
    }
    
    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
    
    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = &target->GetDebugger().GetErrorStream();
    
        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  execution_policy,
                                  const_result,
                                  data_allocator,
                                  error_stream,
                                  function_name.c_str());
        
        ir_for_target.runOnModule(*module);
        
        Error &interpreter_error(ir_for_target.getInterpreterError());
        
        if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success())
        {
            if (const_result)
                const_result->TransferAddress();
            evaluated_statically = true;
            err.Clear();
            return err;
        }
        
        Process *process = exe_ctx.GetProcessPtr();

        if (!process || execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorToGenericError();
            if (execution_policy == eExecutionPolicyAlways)
                err.SetErrorString("Execution needed to run in the target, but the target can't be run");
            else
                err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString());

            return err;
        }
        
        if (execution_policy != eExecutionPolicyNever &&
            m_expr.NeedsValidation() && 
            process)
        {
            if (!process->GetDynamicCheckers())
            {                
                DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
                
                StreamString install_errors;
                
                if (!dynamic_checkers->Install(install_errors, exe_ctx))
                {
                    if (install_errors.GetString().empty())
                        err.SetErrorString ("couldn't install checkers, unknown error");
                    else
                        err.SetErrorString (install_errors.GetString().c_str());
                    
                    return err;
                }
                
                process->SetDynamicCheckers(dynamic_checkers);
                
                if (log)
                    log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
            }
            
            IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str());
        
            if (!ir_dynamic_checks.runOnModule(*module))
            {
                err.SetErrorToGenericError();
                err.SetErrorString("Couldn't add dynamic checks to the expression");
                return err;
            }
        }
    }
    
    // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called 
    // below so we don't need to free it.
    RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager();
    
    std::string error_string;

    if (log)
    {
        std::string s;
        raw_string_ostream oss(s);
        
        module->print(oss, NULL);
        
        oss.flush();
        
        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }
    
    EngineBuilder builder(module);
    builder.setEngineKind(EngineKind::JIT)
        .setErrorStr(&error_string)
        .setRelocationModel(llvm::Reloc::PIC_)
        .setJITMemoryManager(jit_memory_manager)
        .setOptLevel(CodeGenOpt::Less)
        .setAllocateGVsWithCode(true)
        .setCodeModel(CodeModel::Small)
        .setUseMCJIT(true);
    execution_engine.reset(builder.create());
        
    if (!execution_engine.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return err;
    }
    
    execution_engine->DisableLazyCompilation();
    
    llvm::Function *function = module->getFunction (function_name.c_str());
    
    // We don't actually need the function pointer here, this just forces it to get resolved.
    
    void *fun_ptr = execution_engine->getPointerToFunction(function);
        
    // Errors usually cause failures in the JIT, but if we're lucky we get here.
    
    if (!function)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str());
        return err;
    }
    
    if (!fun_ptr)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str());
        return err;
    }
    
    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr));
    

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
    {
        err.SetErrorToGenericError();
        err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
        return err;
    }
        
    jit_memory_manager->CommitAllocations(*process);
    jit_memory_manager->ReportAllocations(*execution_engine);
    jit_memory_manager->WriteData(*process);
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos != end; pos++)
    {
        (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr);
    
        if (!(*pos).m_name.compare(function_name.c_str()))
        {
            RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr);
            func_end = func_range.first + func_range.second;
            func_addr = (*pos).m_remote_addr;
        }
    }
    
    if (log)
    {
        log->Printf("Code can be run in the target.");
        
        StreamString disassembly_stream;
        
        Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager);
        
        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }
    }
    
    execution_engine.reset();
    
    err.Clear();
    return err;
}