Beispiel #1
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;
}
ClangUserExpression::ClangUserExpression(
    ExecutionContextScope &exe_scope, llvm::StringRef expr,
    llvm::StringRef prefix, lldb::LanguageType language,
    ResultType desired_type, const EvaluateExpressionOptions &options)
    : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
                         options),
      m_type_system_helper(*m_target_wp.lock().get(),
                           options.GetExecutionPolicy() ==
                               eExecutionPolicyTopLevel),
      m_result_delegate(exe_scope.CalculateTarget()) {
  switch (m_language) {
  case lldb::eLanguageTypeC_plus_plus:
    m_allow_cxx = true;
    break;
  case lldb::eLanguageTypeObjC:
    m_allow_objc = true;
    break;
  case lldb::eLanguageTypeObjC_plus_plus:
  default:
    m_allow_cxx = true;
    m_allow_objc = true;
    break;
  }
}
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;
}
Beispiel #4
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;
}
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;
}