Пример #1
0
bool
DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx)
{
    Error error;
    m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text,
                                                                                     lldb::eLanguageTypeC,
                                                                                     VALID_POINTER_CHECK_NAME,
                                                                                     error));
    if (error.Fail())
        return false;

    if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
        return false;

    Process *process = exe_ctx.GetProcessPtr();

    if (process)
    {
        ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime();

        if (objc_language_runtime)
        {
            m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME));

            if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
                return false;
        }
    }

    return true;
}
Пример #2
0
SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
                                ThreadPlan *new_plan) {
  SBError sb_error;

  Process *process = exe_ctx.GetProcessPtr();
  if (!process) {
    sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
    return sb_error;
  }

  Thread *thread = exe_ctx.GetThreadPtr();
  if (!thread) {
    sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
    return sb_error;
  }

  // User level plans should be Master Plans so they can be interrupted, other
  // plans executed, and
  // then a "continue" will resume the plan.
  if (new_plan != NULL) {
    new_plan->SetIsMasterPlan(true);
    new_plan->SetOkayToDiscard(false);
  }

  // Why do we need to set the current thread by ID here???
  process->GetThreadList().SetSelectedThreadByID(thread->GetID());

  if (process->GetTarget().GetDebugger().GetAsyncExecution())
    sb_error.ref() = process->Resume();
  else
    sb_error.ref() = process->ResumeSynchronous(NULL);

  return sb_error;
}
Пример #3
0
  bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
                    RegisterContext *reg_ctx, const RegisterInfo *reg_info) {
    if (reg_info) {
      RegisterValue reg_value;

      if (reg_ctx->ReadRegister(reg_info, reg_value)) {
        strm.Indent();

        bool prefix_with_altname = (bool)m_command_options.alternate_name;
        bool prefix_with_name = !prefix_with_altname;
        reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname,
                       m_format_options.GetFormat(), 8);
        if ((reg_info->encoding == eEncodingUint) ||
            (reg_info->encoding == eEncodingSint)) {
          Process *process = exe_ctx.GetProcessPtr();
          if (process && reg_info->byte_size == process->GetAddressByteSize()) {
            addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
            if (reg_addr != LLDB_INVALID_ADDRESS) {
              Address so_reg_addr;
              if (exe_ctx.GetTargetRef()
                      .GetSectionLoadList()
                      .ResolveLoadAddress(reg_addr, so_reg_addr)) {
                strm.PutCString("  ");
                so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(),
                                 Address::DumpStyleResolvedDescription);
              }
            }
          }
        }
        strm.EOL();
        return true;
      }
    }
    return false;
  }
Пример #4
0
bool
DynamicCheckerFunctions::Install(Stream &error_stream,
                                 ExecutionContext &exe_ctx)
{
    m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text,
                                                         VALID_POINTER_CHECK_NAME));
    if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
        return false;
    
    Process *process = exe_ctx.GetProcessPtr();

    if (process)
    {
        ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime();
        
        if (objc_language_runtime)
        {
            m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME));
            
            if (!m_objc_object_check->Install(error_stream, exe_ctx))
                return false;
        }
    }
        
    return true;
}
Пример #5
0
bool
ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
    // Read the return value - it is the last field in the struct:
    // FIXME: How does clang tell us there's no return value?  We need to handle that case.
    // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject
    // to fetch the value.  That way we can fetch any values we need.
    
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
    
    if (log)
        log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
    
    Process *process = exe_ctx.GetProcessPtr();
    
    if (process == NULL)
        return false;

    lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
    
    if (process != jit_process_sp.get())
        return false;
                
    Error error;
    ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error);

    if (error.Fail())
        return false;

    ret_value.SetCompilerType(m_function_return_type);
    ret_value.SetValueType(Value::eValueTypeScalar);
    return true;
}
Пример #6
0
lldb::ExpressionResults
GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                            ExecutionContext &exe_ctx,
                            const EvaluateExpressionOptions &options,
                            lldb::UserExpressionSP &shared_ptr_to_me,
                            lldb::ExpressionVariableSP &result) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
  lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();
  Target *target = exe_ctx.GetTargetPtr();

  if (target == nullptr || process == nullptr ||
      process->GetState() != lldb::eStateStopped) {
    if (execution_policy == eExecutionPolicyAlways) {
      if (log)
        log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
                    "but is not constant ==");

      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression needed to run but couldn't");

      return execution_results;
    }
  }

  m_interpreter->set_use_dynamic(options.GetUseDynamic());
  ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
  Error err = m_interpreter->error();
  m_interpreter.reset();

  if (!result_val_sp) {
    const char *error_cstr = err.AsCString();
    if (error_cstr && error_cstr[0])
      diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
    else
      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression can't be interpreted or run");
    return lldb::eExpressionDiscarded;
  }
  result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
  result->m_live_sp = result->m_frozen_sp = result_val_sp;
  result->m_flags |= ExpressionVariable::EVIsProgramReference;
  PersistentExpressionState *pv =
      target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
  if (pv != nullptr) {
    result->SetName(pv->GetNextPersistentVariableName());
    pv->AddVariable(result);
  }
  return lldb::eExpressionCompleted;
}
Пример #7
0
bool
ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
    Process *process = exe_ctx.GetProcessPtr();

    if (!process)
        return false;
    
    lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
    
    if (process != jit_process_sp.get())
        return false;
    
    if (!m_compiled)
        return false;

    if (m_JITted)
        return true;
        
    bool can_interpret = false; // should stay that way
    
    Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
                                                    m_jit_end_addr,
                                                    m_execution_unit_sp,
                                                    exe_ctx, 
                                                    can_interpret,
                                                    eExecutionPolicyAlways));
    
    if (!jit_error.Success())
        return false;
    
    if (m_parser->GetGenerateDebugInfo())
    {
        lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
        
        if (jit_module_sp)
        {
            ConstString const_func_name(FunctionName());
            FileSpec jit_file;
            jit_file.GetFilename() = const_func_name;
            jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
            m_jit_module_wp = jit_module_sp;
            process->GetTarget().GetImages().Append(jit_module_sp);
        }
    }
    if (process && m_jit_start_addr)
        m_jit_process_wp = process->shared_from_this();
    
    m_JITted = true;

    return true;
}
Пример #8
0
bool
FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager)
{
    Process *process = exe_ctx.GetProcessPtr();

    if (!process)
        return false;
    
    lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
    
    if (process != jit_process_sp.get())
        return false;
    
    if (!m_compiled)
        return false;

    if (m_JITted)
        return true;
        
    bool can_interpret = false; // should stay that way
    
    Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
                                                    m_jit_end_addr,
                                                    m_execution_unit_sp,
                                                    exe_ctx, 
                                                    can_interpret,
                                                    eExecutionPolicyAlways));
    
    if (!jit_error.Success())
        return false;
    
    if (m_parser->GetGenerateDebugInfo())
        m_execution_unit_sp->CreateJITModule(FunctionName());

    if (process && m_jit_start_addr)
        m_jit_process_wp = process->shared_from_this();
    
    m_JITted = true;

    return true;
}
Пример #9
0
bool
ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
    Process *process = exe_ctx.GetProcessPtr();

    if (!process)
        return false;
        
    if (process != m_jit_process_sp.get())
        return false;
    
    if (!m_compiled)
        return false;

    if (m_JITted)
        return true;
    
    lldb::ClangExpressionVariableSP const_result;
    
    bool evaluated_statically = false; // should stay that way
    
    Error jit_error (m_parser->PrepareForExecution (m_jit_alloc,
                                                    m_jit_start_addr,
                                                    m_jit_end_addr,
                                                    exe_ctx, 
                                                    NULL,
                                                    evaluated_statically,
                                                    const_result,
                                                    eExecutionPolicyAlways));
    
    if (!jit_error.Success())
        return false;
    if (process && m_jit_alloc != LLDB_INVALID_ADDRESS)
        m_jit_process_sp = process->shared_from_this();

    return true;
}
Пример #10
0
bool
ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
    // Read the return value - it is the last field in the struct:
    // FIXME: How does clang tell us there's no return value?  We need to handle that case.
    // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject
    // to fetch the value.  That way we can fetch any values we need.
    Process *process = exe_ctx.GetProcessPtr();
    
    if (process == NULL)
        return false;
    if (process != m_jit_process_sp.get())
        return false;
                
    Error error;
    ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error);

    if (error.Fail())
        return false;

    ret_value.SetContext (Value::eContextTypeClangType, m_function_return_qual_type);
    ret_value.SetValueType(Value::eValueTypeScalar);
    return true;
}
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] error_stream
///     A stream to print parse errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool
ClangUtilityFunction::Install (Stream &error_stream,
                               ExecutionContext &exe_ctx)
{
    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
    {
        error_stream.PutCString("error: already installed\n");
        return false;
    }
    
    ////////////////////////////////////
    // Set up the target and compiler
    //
    
    Target *target = exe_ctx.GetTargetPtr();
    
    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }
    
    Process *process = exe_ctx.GetProcessPtr();
    
    if (!process)
    {
        error_stream.PutCString ("error: invalid process\n");
        return false;
    }
        
    //////////////////////////
    // Parse the expression
    //
    
    bool keep_result_in_memory = false;
    
    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
    
    if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
        return false;
    }
        
    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);
    
    unsigned num_errors = parser.Parse (error_stream);
    
    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
        
        m_expr_decl_map.reset();
        
        return false;
    }
    
    //////////////////////////////////
    // JIT the output of the parser
    //
        
    bool can_interpret = false; // should stay that way
    
    Error jit_error = parser.PrepareForExecution (m_jit_start_addr, 
                                                  m_jit_end_addr,
                                                  m_execution_unit_ap,
                                                  exe_ctx,
                                                  can_interpret,
                                                  eExecutionPolicyAlways);
    
    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
    
#if 0
	// jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr, 
                    m_function_name.c_str(), 
                    m_function_text.c_str());
#endif

    m_expr_decl_map->DidParse();
    
    m_expr_decl_map.reset();
    
    if (jit_error.Success())
    {
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
Пример #12
0
ExecutionResults
ClangUserExpression::Execute (Stream &error_stream,
                              ExecutionContext &exe_ctx,
                              bool unwind_on_error,
                              bool ignore_breakpoints,
                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                              lldb::ClangExpressionVariableSP &result,
                              bool run_others,
                              uint32_t timeout_usec)
{
    // The expression log is quite verbose, and if you're just tracking the execution of the
    // expression, it's quite convenient to have these logs come out with the STEP log as well.
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
    {
        lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
                
        lldb::addr_t object_ptr = 0;
        lldb::addr_t cmd_ptr = 0;
        
        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
        {
            error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
            return eExecutionSetupError;
        }
        
        lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
        lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
        
        if (m_can_interpret)
        {            
            llvm::Module *module = m_execution_unit_ap->GetModule();
            llvm::Function *function = m_execution_unit_ap->GetFunction();
            
            if (!module || !function)
            {
                error_stream.Printf("Supposed to interpret, but nothing is there");
                return eExecutionSetupError;
            }

            Error interpreter_error;
            
            llvm::SmallVector <lldb::addr_t, 3> args;
            
            if (m_needs_object_ptr)
            {
                args.push_back(object_ptr);
                
                if (m_objectivec)
                    args.push_back(cmd_ptr);
            }
            
            args.push_back(struct_address);
            
            function_stack_bottom = m_stack_frame_bottom;
            function_stack_top = m_stack_frame_top;
            
            IRInterpreter::Interpret (*module,
                                      *function,
                                      args,
                                      *m_execution_unit_ap.get(),
                                      interpreter_error,
                                      function_stack_bottom,
                                      function_stack_top);
            
            if (!interpreter_error.Success())
            {
                error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
                return eExecutionDiscarded;
            }
        }
        else
        {
            const bool stop_others = true;
            const bool try_all_threads = run_others;
            
            Address wrapper_address (m_jit_start_addr);
            lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), 
                                                                              wrapper_address, 
                                                                              struct_address, 
                                                                              stop_others, 
                                                                              unwind_on_error,
                                                                              ignore_breakpoints,
                                                                              (m_needs_object_ptr ? &object_ptr : NULL),
                                                                              ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
                                                                              shared_ptr_to_me));
            
            if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
                return eExecutionSetupError;
            
            lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();

            function_stack_bottom = function_stack_pointer - Host::GetPageSize();
            function_stack_top = function_stack_pointer;
            
            if (log)
                log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
            
            if (exe_ctx.GetProcessPtr())
                exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
                
            ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, 
                                                                                       call_plan_sp, 
                                                                                       stop_others, 
                                                                                       try_all_threads, 
                                                                                       unwind_on_error,
                                                                                       ignore_breakpoints,
                                                                                       timeout_usec, 
                                                                                       error_stream);
            
            if (exe_ctx.GetProcessPtr())
                exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
                
            if (log)
                log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");

            if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
            {
                const char *error_desc = NULL;
                
                if (call_plan_sp)
                {
                    lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
                    if (real_stop_info_sp)
                        error_desc = real_stop_info_sp->GetDescription();
                }
                if (error_desc)
                    error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
                else
                    error_stream.Printf ("Execution was interrupted.");
                    
                if ((execution_result == eExecutionInterrupted && unwind_on_error)
                    || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
                    error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
                else
                    error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");

                return execution_result;
            }
            else if (execution_result != eExecutionCompleted)
            {
                error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
                return execution_result;
            }
        }
        
        if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
        {
            return eExecutionCompleted;
        }
        else
        {
            return eExecutionSetupError;
        }
    }
    else
    {
        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
        return eExecutionSetupError;
    }
}
Пример #13
0
ExecutionResults
ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
                                        lldb_private::ExecutionPolicy execution_policy,
                                        lldb::LanguageType language,
                                        ResultType desired_type,
                                        bool unwind_on_error,
                                        bool ignore_breakpoints,
                                        const char *expr_cstr,
                                        const char *expr_prefix,
                                        lldb::ValueObjectSP &result_valobj_sp,
                                        Error &error,
                                        bool run_others,
                                        uint32_t timeout_usec)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    ExecutionResults execution_results = eExecutionSetupError;
    
    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
            
            error.SetErrorString ("expression needed to run but couldn't");
            
            return execution_results;
        }
    }
    
    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;
    
    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));

    StreamString error_stream;
        
    if (log)
        log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
    
    const bool keep_expression_in_memory = true;
    
    if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
    {
        if (error_stream.GetString().empty())
            error.SetErrorString ("expression failed to parse, unknown error");
        else
            error.SetErrorString (error_stream.GetString().c_str());
    }
    else
    {
        lldb::ClangExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
            
            if (error_stream.GetString().empty())
                error.SetErrorString ("expression needed to run but couldn't");
        }
        else
        {    
            error_stream.GetString().clear();
            
            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");

            execution_results = user_expression_sp->Execute (error_stream, 
                                                             exe_ctx, 
                                                             unwind_on_error,
                                                             ignore_breakpoints,
                                                             user_expression_sp, 
                                                             expr_result,
                                                             run_others,
                                                             timeout_usec);
            
            if (execution_results != eExecutionCompleted)
            {
                if (log)
                    log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
                
                if (error_stream.GetString().empty())
                    error.SetErrorString ("expression failed to execute, unknown error");
                else
                    error.SetErrorString (error_stream.GetString().c_str());
            }
            else 
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();
                    
                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
                    
                    error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }
    
    if (result_valobj_sp.get() == NULL)
        result_valobj_sp = ValueObjectConstResult::Create (NULL, error);

    return execution_results;
}
Пример #14
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    StackFrame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
    {
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    }
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;

    const FormatEntity::Entry *disassembly_format = NULL;
    FormatEntity::Entry format;
    if (exe_ctx.HasTargetScope())
    {
        disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat ();
    }
    else
    {
        FormatEntity::Parse("${addr}: ", format);
        disassembly_format = &format;
    }

    // First pass: step through the list of instructions, 
    // find how long the initial addresses strings are, insert padding 
    // in the second pass so the opcodes all line up nicely.
    size_t address_text_size = 0;
    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol;
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
                if (resolved_mask)
                {
                    StreamString strmstr;
                    Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr);
                    size_t cur_line = strmstr.GetSizeOfLastLine();
                    if (cur_line > address_text_size)
                        address_text_size = cur_line;
                }
                sc.Clear(false);
            }
        }
    }

    for (size_t i = 0; i < num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}
Пример #15
0
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] diagnostic_manager
///     A diagnostic manager to report errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
                                   ExecutionContext &exe_ctx) {
  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
    diagnostic_manager.PutCString(eDiagnosticSeverityWarning,
                                  "already installed");
    return false;
  }

  ////////////////////////////////////
  // Set up the target and compiler
  //

  Target *target = exe_ctx.GetTargetPtr();

  if (!target) {
    diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
    return false;
  }

  Process *process = exe_ctx.GetProcessPtr();

  if (!process) {
    diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process");
    return false;
  }

  //////////////////////////
  // Parse the expression
  //

  bool keep_result_in_memory = false;

  ResetDeclMap(exe_ctx, keep_result_in_memory);

  if (!DeclMap()->WillParse(exe_ctx, NULL)) {
    diagnostic_manager.PutCString(
        eDiagnosticSeverityError,
        "current process state is unsuitable for expression parsing");
    return false;
  }

  const bool generate_debug_info = true;
  ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
                               generate_debug_info);

  unsigned num_errors = parser.Parse(diagnostic_manager);

  if (num_errors) {
    ResetDeclMap();

    return false;
  }

  //////////////////////////////////
  // JIT the output of the parser
  //

  bool can_interpret = false; // should stay that way

  Error jit_error = parser.PrepareForExecution(
      m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
      can_interpret, eExecutionPolicyAlways);

  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
    m_jit_process_wp = process->shared_from_this();
    if (parser.GetGenerateDebugInfo())
      m_execution_unit_sp->CreateJITModule(FunctionName());
  }

#if 0
	// jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr, 
                    m_function_name.c_str(), 
                    m_function_text.c_str());
#endif

  DeclMap()->DidParse();

  ResetDeclMap();

  if (jit_error.Success()) {
    return true;
  } else {
    const char *error_cstr = jit_error.AsCString();
    if (error_cstr && error_cstr[0]) {
      diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
    } else {
      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression can't be interpreted or run");
    }
    return false;
  }
}
Пример #16
0
lldb_private::Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
                                            lldb::addr_t &func_end,
                                            lldb::IRExecutionUnitSP &execution_unit_sp,
                                            ExecutionContext &exe_ctx,
                                            bool &can_interpret,
                                            ExecutionPolicy execution_policy)
{
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    lldb_private::Error err;

    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());

    if (!llvm_module_ap.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }

    ConstString function_name;

    if (execution_policy != eExecutionPolicyTopLevel)
    {
        // Find the actual name of the function (it's often mangled somehow)

        if (!FindFunctionInModule(function_name, llvm_module_ap.get(), 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.AsCString(), m_expr.FunctionName());
        }
    }

    SymbolContext sc;

    if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP())
    {
        sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
    }
    else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP())
    {
        sc.target_sp = target_sp;
    }

    LLVMUserExpression::IRPasses custom_passes;
    {
        auto lang = m_expr.Language();
        if (log)
            log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__,
                        Language::GetNameForLanguageType(lang));

        if (lang != lldb::eLanguageTypeUnknown)
        {
            auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang);
            if (runtime)
                runtime->GetIRPasses(custom_passes);
        }
    }

    if (custom_passes.EarlyPasses)
    {
        if (log)
            log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__,
                        m_expr.FunctionName());

        custom_passes.EarlyPasses->run(*llvm_module_ap);
    }

    execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
                                                 llvm_module_ap, // handed off here
                                                 function_name,
                                                 exe_ctx.GetTargetSP(),
                                                 sc,
                                                 m_compiler->getTargetOpts().Features));

    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
    ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL

    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = target->GetDebugger().GetErrorFile().get();

        IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream,
                                  function_name.AsCString());

        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

        Process *process = exe_ctx.GetProcessPtr();

        if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel)
        {
            lldb_private::Error interpret_error;

            bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
            can_interpret =
                IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
                                            interpret_error, interpret_function_calls);

            if (!can_interpret && execution_policy == eExecutionPolicyNever)
            {
                err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
                return err;
            }
        }

        if (!ir_can_run)
        {
            err.SetErrorString("The expression could not be prepared to run in the target");
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyAlways)
        {
            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyTopLevel)
        {
            err.SetErrorString(
                "Top-level code needs to be inserted into a runnable target, but the target can't be run");
            return err;
        }

        if (execution_policy == eExecutionPolicyAlways ||
            (execution_policy != eExecutionPolicyTopLevel && !can_interpret))
        {
            if (m_expr.NeedsValidation() && process)
            {
                if (!process->GetDynamicCheckers())
                {
                    DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();

                    DiagnosticManager install_diagnostics;

                    if (!dynamic_checkers->Install(install_diagnostics, exe_ctx))
                    {
                        if (install_diagnostics.Diagnostics().size())
                            err.SetErrorString("couldn't install checkers, unknown error");
                        else
                            err.SetErrorString(install_diagnostics.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.AsCString());

                llvm::Module *module = execution_unit_sp->GetModule();
                if (!module || !ir_dynamic_checks.runOnModule(*module))
                {
                    err.SetErrorToGenericError();
                    err.SetErrorString("Couldn't add dynamic checks to the expression");
                    return err;
                }

                if (custom_passes.LatePasses)
                {
                    if (log)
                        log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'",
                                    __FUNCTION__, m_expr.FunctionName());

                    custom_passes.LatePasses->run(*module);
                }
            }
        }

        if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel ||
            !can_interpret)
        {
            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
        }
    }
    else
    {
        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }

    return err;
}
size_t
UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
{
    m_cursors.clear();
    
    Frame *first_frame = exe_ctx.GetFramePtr();

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
        return 0;
    
    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;

    struct Frame_i386
    {
        uint32_t fp;
        uint32_t pc;
    };

    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
    assert (reg_ctx);

    Cursor cursor;
    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
    cursor.fp = reg_ctx->GetFP (0);
    
    Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };

    m_cursors.push_back(cursor);

    const size_t k_frame_size = sizeof(frame);
    Error error;
    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
    {
        // Read both the FP and PC (8 bytes)
        if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
            break;
        if (frame.pc >= 0x1000)
        {
            cursor.pc = frame.pc;
            cursor.fp = frame.fp;
            m_cursors.push_back (cursor);
        }
    }
    if (!m_cursors.empty())
    {
        lldb::addr_t first_frame_pc = m_cursors.front().pc;
        if (first_frame_pc != LLDB_INVALID_ADDRESS)
        {
            const uint32_t resolve_scope = eSymbolContextModule |
                                           eSymbolContextCompUnit |
                                           eSymbolContextFunction |
                                           eSymbolContextSymbol;

            SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
            const AddressRange *addr_range_ptr = NULL;
            AddressRange range;
            if (first_frame_sc.function)
                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
            else if (first_frame_sc.symbol)
            {
                range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
                range.SetByteSize (first_frame_sc.symbol->GetByteSize());
                addr_range_ptr = &range;
            }

            if (addr_range_ptr)
            {
                if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
                {
                    // We are at the first instruction, so we can recover the
                    // previous PC by dereferencing the SP
                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
                    // Read the real second frame return address into frame.pc
                    if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
                    {
                        cursor.fp = m_cursors.front().fp;
                        cursor.pc = frame.pc;           // Set the new second frame PC

                        // Insert the second frame
                        m_cursors.insert(m_cursors.begin()+1, cursor);
                        
                        m_cursors.front().fp = first_frame_sp;
                    }
                }
            }
        }
    }
//    uint32_t i=0;
//    printf("      PC                 FP\n");
//    printf("      ------------------ ------------------ \n");
//    for (i=0; i<m_cursors.size(); ++i)
//    {
//        printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
//    }
    return m_cursors.size();
}
Пример #18
0
lldb::ExpressionResults
ClangUserExpression::Execute (Stream &error_stream,
                              ExecutionContext &exe_ctx,
                              const EvaluateExpressionOptions& options,
                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                              lldb::ClangExpressionVariableSP &result)
{
    // The expression log is quite verbose, and if you're just tracking the execution of the
    // expression, it's quite convenient to have these logs come out with the STEP log as well.
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
    {
        lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;

        lldb::addr_t object_ptr = 0;
        lldb::addr_t cmd_ptr = 0;

        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
        {
            error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
            return lldb::eExpressionSetupError;
        }

        lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
        lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;

        if (m_can_interpret)
        {
            llvm::Module *module = m_execution_unit_sp->GetModule();
            llvm::Function *function = m_execution_unit_sp->GetFunction();

            if (!module || !function)
            {
                error_stream.Printf("Supposed to interpret, but nothing is there");
                return lldb::eExpressionSetupError;
            }

            Error interpreter_error;

            llvm::SmallVector <lldb::addr_t, 3> args;

            if (m_needs_object_ptr)
            {
                args.push_back(object_ptr);

                if (m_objectivec)
                    args.push_back(cmd_ptr);
            }

            args.push_back(struct_address);

            function_stack_bottom = m_stack_frame_bottom;
            function_stack_top = m_stack_frame_top;

            IRInterpreter::Interpret (*module,
                                      *function,
                                      args,
                                      *m_execution_unit_sp.get(),
                                      interpreter_error,
                                      function_stack_bottom,
                                      function_stack_top);

            if (!interpreter_error.Success())
            {
                error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
                return lldb::eExpressionDiscarded;
            }
        }
        else
        {
            if (!exe_ctx.HasThreadScope())
            {
                error_stream.Printf("ClangUserExpression::Execute called with no thread selected.");
                return lldb::eExpressionSetupError;
            }

            Address wrapper_address (m_jit_start_addr);

            llvm::SmallVector <lldb::addr_t, 3> args;

            if (m_needs_object_ptr) {
                args.push_back(object_ptr);
                if (m_objectivec)
                    args.push_back(cmd_ptr);
            }

            args.push_back(struct_address);
         
            ThreadPlanCallUserExpression *user_expression_plan = 
                    new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
                                                      wrapper_address, 
                                                      args,
                                                      options,
                                                      shared_ptr_to_me);
            lldb::ThreadPlanSP call_plan_sp(user_expression_plan);

            if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
                return lldb::eExpressionSetupError;

            lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();

            function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
            function_stack_top = function_stack_pointer;

            if (log)
                log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");

            if (exe_ctx.GetProcessPtr())
                exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);

            lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
                                                                                       call_plan_sp,
                                                                                       options,
                                                                                       error_stream);

            if (exe_ctx.GetProcessPtr())
                exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);

            if (log)
                log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");

            if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
            {
                const char *error_desc = NULL;

                if (call_plan_sp)
                {
                    lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
                    if (real_stop_info_sp)
                        error_desc = real_stop_info_sp->GetDescription();
                }
                if (error_desc)
                    error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
                else
                    error_stream.PutCString ("Execution was interrupted.");

                if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
                    || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
                    error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
                else
                {
                    if (execution_result == lldb::eExpressionHitBreakpoint)
                        user_expression_plan->TransferExpressionOwnership();
                    error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
                                             "use \"thread return -x\" to return to the state before expression evaluation.");
                }

                return execution_result;
            }
            else if (execution_result == lldb::eExpressionStoppedForDebug)
            {
                    error_stream.PutCString ("Execution was halted at the first instruction of the expression "
                                             "function because \"debug\" was requested.\n"
                                             "Use \"thread return -x\" to return to the state before expression evaluation.");
                    return execution_result;
            }
            else if (execution_result != lldb::eExpressionCompleted)
            {
                error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
                return execution_result;
            }
        }

        if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
        {
            return lldb::eExpressionCompleted;
        }
        else
        {
            return lldb::eExpressionResultUnavailable;
        }
    }
    else
    {
        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
        return lldb::eExpressionSetupError;
    }
}
Пример #19
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;
}
Пример #20
0
Error
ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    
    const char *name = m_expr.FunctionName();
    
    Error ret;
    
    ret.Clear();
    
    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos < end; pos++)
    {
        if (strstr(pos->m_name.c_str(), name))
        {
            func_local_addr = pos->m_local_addr;
            func_remote_addr = pos->m_remote_addr;
        }
    }
    
    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
        return ret;
    }
    
    if (log)
        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
    
    std::pair <lldb::addr_t, lldb::addr_t> func_range;
    
    func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr);
    
    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
        return ret;
    }
    
    if (log)
        log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second);
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
    }
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
    
    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
    
    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }
    
    ArchSpec arch(target->GetArchitecture());
    
    Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL);
    
    if (disassembler == NULL)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }
    
    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }
    
    DataExtractor extractor(buffer_sp, 
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());
    
    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log.get(),
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }
    
    disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
    
    InstructionList &instruction_list = disassembler->GetInstructionList();
    const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
         instruction_index < num_instructions; 
         ++instruction_index)
    {
        Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
        instruction->Dump (&stream,
                           max_opcode_byte_size,
                           true,
                           true,
                           &exe_ctx);
        stream.PutChar('\n');
    }
    
    return ret;
}
Пример #21
0
bool 
Disassembler::PrintInstructions
(
    Disassembler *disasm_ptr,
    Debugger &debugger,
    const ArchSpec &arch,
    const ExecutionContext &exe_ctx,
    uint32_t num_instructions,
    uint32_t num_mixed_context_lines,
    uint32_t options,
    Stream &strm
)
{
    // We got some things disassembled...
    size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
    
    if (num_instructions > 0 && num_instructions < num_instructions_found)
        num_instructions_found = num_instructions;
        
    const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
    uint32_t offset = 0;
    SymbolContext sc;
    SymbolContext prev_sc;
    AddressRange sc_range;
    const Address *pc_addr_ptr = NULL;
    ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
    Frame *frame = exe_ctx.GetFramePtr();

    TargetSP target_sp (exe_ctx.GetTargetSP());
    SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();

    if (frame)
        pc_addr_ptr = &frame->GetFrameCodeAddress();
    const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
    const bool use_inline_block_range = false;
    for (size_t i=0; i<num_instructions_found; ++i)
    {
        Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
        if (inst)
        {
            const Address &addr = inst->GetAddress();
            const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;

            prev_sc = sc;

            ModuleSP module_sp (addr.GetModule());
            if (module_sp)
            {
                uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
                if (resolved_mask)
                {
                    if (num_mixed_context_lines)
                    {
                        if (!sc_range.ContainsFileAddress (addr))
                        {
                            sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
                            
                            if (sc != prev_sc)
                            {
                                if (offset != 0)
                                    strm.EOL();
                                
                                sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
                                strm.EOL();
                                
                                if (sc.comp_unit && sc.line_entry.IsValid())
                                {
                                    source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
                                                                                      sc.line_entry.line,
                                                                                      num_mixed_context_lines,
                                                                                      num_mixed_context_lines,
                                                                                      ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
                                                                                      &strm);
                                }
                            }
                        }
                    }
                    else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol))
                    {
                        if (prev_sc.function || prev_sc.symbol)
                            strm.EOL();

                        bool show_fullpaths = false;
                        bool show_module = true;
                        bool show_inlined_frames = true;
                        sc.DumpStopContext (&strm, 
                                            exe_scope, 
                                            addr, 
                                            show_fullpaths,
                                            show_module,
                                            show_inlined_frames);
                        
                        strm << ":\n";
                    }
                }
                else
                {
                    sc.Clear(true);
                }
            }

            if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
            {
                strm.PutCString(inst_is_at_pc ? "-> " : "   ");
            }
            const bool show_bytes = (options & eOptionShowBytes) != 0;
            inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx);
            strm.EOL();            
        }
        else
        {
            break;
        }
    }
        
    return true;
}
Пример #22
0
lldb::ExpressionResults
ClangFunction::ExecuteFunction(
        ExecutionContext &exe_ctx, 
        lldb::addr_t *args_addr_ptr,
        const EvaluateExpressionOptions &options,
        Stream &errors, 
        Value &results)
{
    using namespace clang;
    lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
    
    // ClangFunction::ExecuteFunction execution is always just to get the result.  Do make sure we ignore
    // breakpoints, unwind on error, and don't try to debug it.
    EvaluateExpressionOptions real_options = options;
    real_options.SetDebug(false);
    real_options.SetUnwindOnError(true);
    real_options.SetIgnoreBreakpoints(true);
    
    lldb::addr_t args_addr;
    
    if (args_addr_ptr != NULL)
        args_addr = *args_addr_ptr;
    else
        args_addr = LLDB_INVALID_ADDRESS;
        
    if (CompileFunction(errors) != 0)
        return lldb::eExpressionSetupError;
    
    if (args_addr == LLDB_INVALID_ADDRESS)
    {
        if (!InsertFunction(exe_ctx, args_addr, errors))
            return lldb::eExpressionSetupError;
    }

    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    if (log)
        log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
    
    lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
                                                                   args_addr,
                                                                   real_options,
                                                                   errors);
    if (!call_plan_sp)
        return lldb::eExpressionSetupError;
        
    // We need to make sure we record the fact that we are running an expression here
    // otherwise this fact will fail to be recorded when fetching an Objective-C object description
    if (exe_ctx.GetProcessPtr())
        exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
    
    return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
                                                          call_plan_sp,
                                                          real_options,
                                                          errors);
    
    if (log)
    {
        if (return_value != lldb::eExpressionCompleted)
        {
            log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
        }
        else
        {
            log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
        }
    }
    
    if (exe_ctx.GetProcessPtr())
        exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
    
    if (args_addr_ptr != NULL)
        *args_addr_ptr = args_addr;
    
    if (return_value != lldb::eExpressionCompleted)
        return return_value;

    FetchFunctionResults(exe_ctx, args_addr, results);
    
    if (args_addr_ptr == NULL)
        DeallocateFunctionResults(exe_ctx, args_addr);
        
    return lldb::eExpressionCompleted;
}
Пример #23
0
bool
ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, 
                                       lldb::addr_t &args_addr_ref, 
                                       Address function_address, 
                                       ValueList &arg_values, 
                                       Stream &errors)
{
    // All the information to reconstruct the struct is provided by the
    // StructExtractor.
    if (!m_struct_valid)
    {
        errors.Printf("Argument information was not correctly parsed, so the function cannot be called.");
        return false;
    }
        
    Error error;
    using namespace clang;
    ExecutionResults return_value = eExecutionSetupError;

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL)
        return return_value;

    if (process != m_jit_process_sp.get())
        return false;
                
    if (args_addr_ref == LLDB_INVALID_ADDRESS)
    {
        args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
        if (args_addr_ref == LLDB_INVALID_ADDRESS)
            return false;
        m_wrapper_args_addrs.push_back (args_addr_ref);
    } 
    else 
    {
        // Make sure this is an address that we've already handed out.
        if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end())
        {
            return false;
        }
    }

    // TODO: verify fun_addr needs to be a callable address
    Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
    int first_offset = m_member_offsets[0];
    process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);

    // FIXME: We will need to extend this for Variadic functions.

    Error value_error;
    
    size_t num_args = arg_values.GetSize();
    if (num_args != m_arg_values.GetSize())
    {
        errors.Printf ("Wrong number of arguments - was: %lu should be: %lu", num_args, m_arg_values.GetSize());
        return false;
    }
    
    for (size_t i = 0; i < num_args; i++)
    {
        // FIXME: We should sanity check sizes.

        int offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
        Value *arg_value = arg_values.GetValueAtIndex(i);
        
        // FIXME: For now just do scalars:
        
        // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings)
        
        if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
            arg_value->GetContextType() == Value::eContextTypeClangType &&
            ClangASTContext::IsPointerType(arg_value->GetClangType()))
            continue;
        
        const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext());

        if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error))
            return false;
    }

    return true;
}
Пример #24
0
lldb::ExpressionResults
UserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error,
                               uint32_t line_offset,
                               lldb::ModuleSP *jit_module_sp_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        if (log)
            log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
        return lldb::eExpressionSetupError;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;

    const char *full_prefix = NULL;
    const char *option_prefix = options.GetPrefix();
    std::string full_prefix_storage;
    if (expr_prefix && option_prefix)
    {
        full_prefix_storage.assign(expr_prefix);
        full_prefix_storage.append(option_prefix);
        if (!full_prefix_storage.empty())
            full_prefix = full_prefix_storage.c_str();
    }
    else if (expr_prefix)
        full_prefix = expr_prefix;
    else
        full_prefix = option_prefix;
    
    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }


    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }

    lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
                                                                                    full_prefix,
                                                                                    language,
                                                                                    desired_type,
                                                                                    options,
                                                                                    error));
    if (error.Fail())
    {
        if (log)
            log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
        return lldb::eExpressionSetupError;
    }
 
    StreamString error_stream;

    if (log)
        log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    if (!user_expression_sp->Parse (error_stream,
                                    exe_ctx,
                                    execution_policy,
                                    keep_expression_in_memory,
                                    generate_debug_info,
                                    0))
    {
        execution_results = lldb::eExpressionParseError;
        if (error_stream.GetString().empty())
            error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
        else
            error.SetExpressionError (execution_results, error_stream.GetString().c_str());
    }
    else
    {
        // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
        if (jit_module_sp_ptr)
            *jit_module_sp_ptr = user_expression_sp->GetJITModule();

        lldb::ExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (error_stream.GetString().empty())
                error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            error_stream.GetString().clear();

            if (log)
                log->Printf("== [UserExpression::Evaluate] Executing expression ==");

            execution_results = user_expression_sp->Execute (error_stream,
                                                             exe_ctx,
                                                             options,
                                                             user_expression_sp,
                                                             expr_result);

            if (options.GetResultIsInternal() && expr_result && process)
            {
                process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
            }

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");

                if (error_stream.GetString().empty())
                    error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError (execution_results, error_stream.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}
Пример #25
0
bool
ClangUserExpression::Parse (Stream &error_stream,
                            ExecutionContext &exe_ctx,
                            lldb_private::ExecutionPolicy execution_policy,
                            bool keep_result_in_memory,
                            bool generate_debug_info)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    InstallContext(exe_ctx);

    ScanContext(exe_ctx, err);

    if (!err.Success())
    {
        error_stream.Printf("warning: %s\n", err.AsCString());
    }

    StreamString m_transformed_stream;

    ////////////////////////////////////
    // Generate the expression
    //

    ApplyObjcCastHack(m_expr_text);
    //ApplyUnicharHack(m_expr_text);

    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));

    lldb::LanguageType lang_type;

    if (m_cplusplus)
        lang_type = lldb::eLanguageTypeC_plus_plus;
    else if(m_objectivec)
        lang_type = lldb::eLanguageTypeObjC;
    else
        lang_type = lldb::eLanguageTypeC;

    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx))
    {
        error_stream.PutCString ("error: couldn't construct expression body");
        return false;
    }

    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    m_materializer_ap.reset(new Materializer());

    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));

    class OnExit
    {
    public:
        typedef std::function <void (void)> Callback;

        OnExit (Callback const &callback) :
            m_callback(callback)
        {
        }

        ~OnExit ()
        {
            m_callback();
        }
    private:
        Callback m_callback;
    };

    OnExit on_exit([this]() { m_expr_decl_map.reset(); });

    if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    Process *process = exe_ctx.GetProcessPtr();
    ExecutionContextScope *exe_scope = process;

    if (!exe_scope)
        exe_scope = exe_ctx.GetTargetPtr();

    ClangExpressionParser parser(exe_scope, *this, generate_debug_info);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    // Prepare the output of the parser for execution, evaluating it statically if possible
    //

    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
                                                  m_jit_end_addr,
                                                  m_execution_unit_sp,
                                                  exe_ctx,
                                                  m_can_interpret,
                                                  execution_policy);

    if (generate_debug_info)
    {
        lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());

        if (jit_module_sp)
        {
            ConstString const_func_name(FunctionName());
            FileSpec jit_file;
            jit_file.GetFilename() = const_func_name;
            jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
            m_jit_module_wp = jit_module_sp;
            target->GetImages().Append(jit_module_sp);
        }
//        lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
//        StreamFile strm (stdout, false);
//        if (jit_obj_file)
//        {
//            jit_obj_file->GetSectionList();
//            jit_obj_file->GetSymtab();
//            jit_obj_file->Dump(&strm);
//        }
//        lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
//        if (jit_sym_vendor)
//        {
//            lldb_private::SymbolContextList sc_list;
//            jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
//            sc_list.Dump(&strm, target);
//            jit_sym_vendor->Dump(&strm);
//        }
    }

    m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions.

    if (jit_error.Success())
    {
        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
Пример #26
0
//------------------------------------------------------------------
/// Install the utility function into a process
///
/// @param[in] error_stream
///     A stream to print parse errors and warnings to.
///
/// @param[in] exe_ctx
///     The execution context to install the utility function to.
///
/// @return
///     True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool
ClangUtilityFunction::Install (Stream &error_stream,
                               ExecutionContext &exe_ctx)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
    {
        error_stream.PutCString("error: already installed\n");
        return false;
    }

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (!process)
    {
        error_stream.PutCString ("error: invalid process\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    bool keep_result_in_memory = false;

    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));

    m_data_allocator.reset(new ProcessDataAllocator(*process));

    if (!m_expr_decl_map->WillParse(exe_ctx))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
        return false;
    }

    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);

        m_expr_decl_map.reset();

        return false;
    }

    //////////////////////////////////
    // JIT the output of the parser
    //

    lldb::ClangExpressionVariableSP const_result;

    bool evaluated_statically = false; // should stay that way

    Error jit_error = parser.PrepareForExecution (m_jit_alloc,
                      m_jit_start_addr,
                      m_jit_end_addr,
                      exe_ctx,
                      m_data_allocator.get(),
                      evaluated_statically,
                      const_result,
                      eExecutionPolicyAlways);

    if (log)
    {
        StreamString dump_string;
        m_data_allocator->Dump(dump_string);

        log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
    }

    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
        m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());

#if 0
    // jingham: look here
    StreamFile logfile ("/tmp/exprs.txt", "a");
    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
                    m_jit_start_addr,
                    m_function_name.c_str(),
                    m_function_text.c_str());
#endif

    m_expr_decl_map->DidParse();

    m_expr_decl_map.reset();

    if (jit_error.Success())
    {
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
Пример #27
0
lldb::ExpressionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    const lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;

    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));

    StreamString error_stream;

    if (log)
        log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    if (!user_expression_sp->Parse (error_stream,
                                    exe_ctx,
                                    execution_policy,
                                    keep_expression_in_memory,
                                    generate_debug_info))
    {
        if (error_stream.GetString().empty())
            error.SetExpressionError (lldb::eExpressionParseError, "expression failed to parse, unknown error");
        else
            error.SetExpressionError (lldb::eExpressionParseError, error_stream.GetString().c_str());
    }
    else
    {
        lldb::ClangExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (error_stream.GetString().empty())
                error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            error_stream.GetString().clear();

            if (log)
                log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");

            execution_results = user_expression_sp->Execute (error_stream,
                                                             exe_ctx,
                                                             options,
                                                             user_expression_sp,
                                                             expr_result);

            if (options.GetResultIsInternal())
            {
                process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
            }

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");

                if (error_stream.GetString().empty())
                    error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError (execution_results, error_stream.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}
Пример #28
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));

    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());
        
        if (!ir_for_target.runOnModule(*module))
        {
            err.SetErrorToGenericError();
            err.SetErrorString("Couldn't prepare the expression for execution in the target");
            return err;
        }
        
        if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess())
        {
            evaluated_statically = true;
            err.Clear();
            return err;
        }
        
        Process *process = exe_ctx.GetProcessPtr();

        if (!process || execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorToGenericError();
            err.SetErrorString("Execution needed to run in the target, but the target can't be run");
            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());
    }
    
#if defined (USE_STANDARD_JIT)
    m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, 
                                                               &error_string, 
                                                               jit_memory_manager,
                                                               CodeGenOpt::Less,
                                                               true,
                                                               Reloc::Default,
                                                               CodeModel::Small));
#else
    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);
    m_execution_engine.reset(builder.create());
#endif
        
    if (!m_execution_engine.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return err;
    }
    
    m_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 = m_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;
    }
    
    // Look over the regions allocated for the function compiled.  The JIT
    // tries to allocate the functions & stubs close together, so we should try to
    // write them that way too...
    // For now I only write functions with no stubs, globals, exception tables,
    // etc.  So I only need to write the functions.
    
    size_t alloc_size = 0;
    
    std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin();
    std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end();

    for (; fun_pos != fun_end; ++fun_pos)
    {
        size_t mem_size = fun_pos->second - fun_pos->first;
        if (log)
            log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size);
        alloc_size += mem_size;
    }
    
    Error alloc_error;
    func_allocation_addr = process->AllocateMemory (alloc_size, 
                                                                lldb::ePermissionsReadable|lldb::ePermissionsExecutable, 
                                                                alloc_error);
    
    if (func_allocation_addr == LLDB_INVALID_ADDRESS)
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
        return err;
    }
    
    lldb::addr_t cursor = func_allocation_addr;
        
    for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++)
    {
        lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
        lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
        size_t size = lend - lstart;
        
        Error write_error;
        
        if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
        {
            err.SetErrorToGenericError();
            err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error"));
            return err;
        }
            
        jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor);
        cursor += size;
    }
    
    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()))
        {
            func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).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());
        }
    }
    
    err.Clear();
    return err;
}
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
                                            lldb::addr_t &func_end,
                                            std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
                                            ExecutionContext &exe_ctx,
                                            bool &can_interpret,
                                            ExecutionPolicy execution_policy)
{
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());

    if (!llvm_module_ap.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }

    // Find the actual name of the function (it's often mangled somehow)

    ConstString function_name;

    if (!FindFunctionInModule(function_name, llvm_module_ap.get(), 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.AsCString(), m_expr.FunctionName());
    }

    execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
                                                 llvm_module_ap, // handed off here
                                                 function_name,
                                                 exe_ctx.GetTargetSP(),
                                                 m_compiler->getTargetOpts().Features));

    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().GetErrorFile().get();

        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  *execution_unit_sp,
                                  error_stream,
                                  function_name.AsCString());

        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

        Error interpret_error;

        can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);

        Process *process = exe_ctx.GetProcessPtr();

        if (!ir_can_run)
        {
            err.SetErrorString("The expression could not be prepared to run in the target");
            return err;
        }

        if (!can_interpret && execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyAlways)
        {
            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
            return err;
        }

        if (execution_policy == eExecutionPolicyAlways || !can_interpret)
        {
            if (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.AsCString());

                if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
                {
                    err.SetErrorToGenericError();
                    err.SetErrorString("Couldn't add dynamic checks to the expression");
                    return err;
                }
            }

            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
        }
    }
    else
    {
        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }

    return err;
}
Пример #30
0
lldb::ExpressionResults
UserExpression::Evaluate (ExecutionContext &exe_ctx,
                               const EvaluateExpressionOptions& options,
                               const char *expr_cstr,
                               const char *expr_prefix,
                               lldb::ValueObjectSP &result_valobj_sp,
                               Error &error,
                               uint32_t line_offset,
                               std::string *fixed_expression,
                               lldb::ModuleSP *jit_module_sp_ptr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
    lldb::LanguageType language = options.GetLanguage();
    const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        if (log)
            log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
        return lldb::eExpressionSetupError;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (process == NULL || process->GetState() != lldb::eStateStopped)
    {
        if (execution_policy == eExecutionPolicyAlways)
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            error.SetErrorString ("expression needed to run but couldn't");

            return execution_results;
        }
    }

    if (process == NULL || !process->CanJIT())
        execution_policy = eExecutionPolicyNever;
    
    // We need to set the expression execution thread here, turns out parse can call functions in the process of
    // looking up symbols, which will escape the context set by exe_ctx passed to Execute.
    lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
    ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp);

    const char *full_prefix = NULL;
    const char *option_prefix = options.GetPrefix();
    std::string full_prefix_storage;
    if (expr_prefix && option_prefix)
    {
        full_prefix_storage.assign(expr_prefix);
        full_prefix_storage.append(option_prefix);
        if (!full_prefix_storage.empty())
            full_prefix = full_prefix_storage.c_str();
    }
    else if (expr_prefix)
        full_prefix = expr_prefix;
    else
        full_prefix = option_prefix;

    // If the language was not specified in the expression command,
    // set it to the language in the target's properties if
    // specified, else default to the langage for the frame.
    if (language == lldb::eLanguageTypeUnknown)
    {
        if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
            language = target->GetLanguage();
        else if (StackFrame *frame = exe_ctx.GetFramePtr())
            language = frame->GetLanguage();
    }

    lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
                                                                                    full_prefix,
                                                                                    language,
                                                                                    desired_type,
                                                                                    options,
                                                                                    error));
    if (error.Fail())
    {
        if (log)
            log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
        return lldb::eExpressionSetupError;
    }

    if (log)
        log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);

    const bool keep_expression_in_memory = true;
    const bool generate_debug_info = options.GetGenerateDebugInfo();

    if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
    {
        error.SetErrorString ("expression interrupted by callback before parse");
        result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
    }

    DiagnosticManager diagnostic_manager;

    bool parse_success = user_expression_sp->Parse(diagnostic_manager,
                                                   exe_ctx,
                                                   execution_policy,
                                                   keep_expression_in_memory,
                                                   generate_debug_info);
    
    // Calculate the fixed expression always, since we need it for errors.
    std::string tmp_fixed_expression;
    if (fixed_expression == nullptr)
        fixed_expression = &tmp_fixed_expression;

    const char *fixed_text = user_expression_sp->GetFixedText();
    if (fixed_text != nullptr)
            fixed_expression->append(fixed_text);
    
    // If there is a fixed expression, try to parse it:
    if (!parse_success)
    {
        execution_results = lldb::eExpressionParseError;
        if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts())
        {
            lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(),
                                                                                             full_prefix,
                                                                                             language,
                                                                                             desired_type,
                                                                                             options,
                                                                                             error));
            DiagnosticManager fixed_diagnostic_manager;
            parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager,
                                                       exe_ctx,
                                                       execution_policy,
                                                       keep_expression_in_memory,
                                                       generate_debug_info);
            if (parse_success)
            {
                diagnostic_manager.Clear();
                user_expression_sp = fixed_expression_sp;
            }
            else
            {
                // If the fixed expression failed to parse, don't tell the user about, that won't help.
                fixed_expression->clear();
            }
        }
        
        if (!parse_success)
        {
            if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts())
            {
                error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n  %s",
                                                   fixed_expression->c_str());
            }
            else
            {
                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
        }
    }
    
    if (parse_success)
    {
        // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
        if (jit_module_sp_ptr)
            *jit_module_sp_ptr = user_expression_sp->GetJITModule();

        lldb::ExpressionVariableSP expr_result;

        if (execution_policy == eExecutionPolicyNever &&
            !user_expression_sp->CanInterpret())
        {
            if (log)
                log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");

            if (!diagnostic_manager.Diagnostics().size())
                error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't");
        }
        else if (execution_policy == eExecutionPolicyTopLevel)
        {
            error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
            return lldb::eExpressionCompleted;
        }
        else
        {
            if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
            {
                error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
                result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
                return lldb::eExpressionInterrupted;
            }

            diagnostic_manager.Clear();

            if (log)
                log->Printf("== [UserExpression::Evaluate] Executing expression ==");

            execution_results =
                user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result);

            if (execution_results != lldb::eExpressionCompleted)
            {
                if (log)
                    log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");

                if (!diagnostic_manager.Diagnostics().size())
                    error.SetExpressionError(execution_results, "expression failed to execute, unknown error");
                else
                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
            }
            else
            {
                if (expr_result)
                {
                    result_valobj_sp = expr_result->GetValueObject();

                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
                                    result_valobj_sp->GetValueAsCString());
                }
                else
                {
                    if (log)
                        log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");

                    error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
                }
            }
        }
    }

    if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
    {
        error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
        return lldb::eExpressionInterrupted;
    }

    if (result_valobj_sp.get() == NULL)
    {
        result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
    }

    return execution_results;
}