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; }
ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size() || !m_first) return ValueObjectSP(); if (m_elements[idx]) return m_elements[idx]; ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); CompilerType type; ValueObjectSP chunk; // For small bitsets __first_ is not an array, but a plain size_t. if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) { llvm::Optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; chunk = m_first->GetChildAtIndex(idx / *bit_size, true); } else { type = m_first->GetCompilerType(); chunk = m_first; } if (!type || !chunk) return {}; llvm::Optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; size_t chunk_idx = idx % *bit_size; uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data, ctx, m_bool_type); return m_elements[idx]; }
bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) { ConstString watch_name("$__lldb__watch_value"); m_old_value_sp = m_new_value_sp; Address watch_address(GetLoadAddress()); if (!m_type.IsValid()) { // Don't know how to report new & old values, since we couldn't make a // scalar type for this watchpoint. This works around an assert in // ValueObjectMemory::Create. // FIXME: This should not happen, but if it does in some case we care about, // we can go grab the value raw and print it as unsigned. return false; } m_new_value_sp = ValueObjectMemory::Create( exe_ctx.GetBestExecutionContextScope(), watch_name.GetStringRef(), watch_address, m_type); m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name); return (m_new_value_sp && m_new_value_sp->GetError().Success()); }
bool LLVMUserExpression::FinalizeJITExecution( DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, lldb::addr_t function_stack_top) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing " "after execution --"); if (!m_dematerializer_sp) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : no " "dematerializer is present"); return false; } Error dematerialize_error; m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top); if (!dematerialize_error.Success()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : %s", dematerialize_error.AsCString("unknown error")); return false; } result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope()); if (result) result->TransferAddress(); m_dematerializer_sp.reset(); 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) { 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; } }
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; }
//------------------------------------------------------------------ /// 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; } }
//------------------------------------------------------------------ /// 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; } }
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; }
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; }