486 lines · cpp
1//===-- ThreadPlanCallFunction.cpp ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/ThreadPlanCallFunction.h"10#include "lldb/Breakpoint/Breakpoint.h"11#include "lldb/Breakpoint/BreakpointLocation.h"12#include "lldb/Core/Address.h"13#include "lldb/Core/DumpRegisterValue.h"14#include "lldb/Core/Module.h"15#include "lldb/Symbol/ObjectFile.h"16#include "lldb/Target/ABI.h"17#include "lldb/Target/LanguageRuntime.h"18#include "lldb/Target/Process.h"19#include "lldb/Target/RegisterContext.h"20#include "lldb/Target/StopInfo.h"21#include "lldb/Target/Target.h"22#include "lldb/Target/Thread.h"23#include "lldb/Target/ThreadPlanRunToAddress.h"24#include "lldb/Utility/LLDBLog.h"25#include "lldb/Utility/Log.h"26#include "lldb/Utility/Stream.h"27 28#include <memory>29 30using namespace lldb;31using namespace lldb_private;32 33// ThreadPlanCallFunction: Plan to call a single function34bool ThreadPlanCallFunction::ConstructorSetup(35 Thread &thread, ABI *&abi, lldb::addr_t &start_load_addr,36 lldb::addr_t &function_load_addr) {37 SetIsControllingPlan(true);38 SetOkayToDiscard(false);39 SetPrivate(true);40 41 ProcessSP process_sp(thread.GetProcess());42 if (!process_sp)43 return false;44 45 abi = process_sp->GetABI().get();46 47 if (!abi)48 return false;49 50 Log *log = GetLog(LLDBLog::Step);51 52 SetBreakpoints();53 54 m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();55 // If we can't read memory at the point of the process where we are planning56 // to put our function, we're not going to get any further...57 Status error;58 process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);59 if (!error.Success()) {60 m_constructor_errors.Printf(61 "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".",62 m_function_sp);63 LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),64 m_constructor_errors.GetData());65 return false;66 }67 68 llvm::Expected<Address> start_address = GetTarget().GetEntryPointAddress();69 if (!start_address) {70 m_constructor_errors.Printf(71 "%s", llvm::toString(start_address.takeError()).c_str());72 LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),73 m_constructor_errors.GetData());74 return false;75 }76 77 m_start_addr = *start_address;78 start_load_addr = m_start_addr.GetLoadAddress(&GetTarget());79 80 // Checkpoint the thread state so we can restore it later.81 if (log && log->GetVerbose())82 ReportRegisterState("About to checkpoint thread before function call. "83 "Original register state was:");84 85 if (!thread.CheckpointThreadState(m_stored_thread_state)) {86 m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to "87 "checkpoint thread state.");88 LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),89 m_constructor_errors.GetData());90 return false;91 }92 function_load_addr = m_function_addr.GetLoadAddress(&GetTarget());93 94 return true;95}96 97ThreadPlanCallFunction::ThreadPlanCallFunction(98 Thread &thread, const Address &function, const CompilerType &return_type,99 llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options)100 : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,101 eVoteNoOpinion, eVoteNoOpinion),102 m_valid(false), m_stop_other_threads(options.GetStopOthers()),103 m_unwind_on_error(options.DoesUnwindOnError()),104 m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),105 m_debug_execution(options.GetDebug()),106 m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),107 m_start_addr(), m_function_sp(0), m_subplan_sp(),108 m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr),109 m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(),110 m_return_valobj_sp(), m_takedown_done(false),111 m_should_clear_objc_exception_bp(false),112 m_should_clear_cxx_exception_bp(false),113 m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) {114 lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;115 lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;116 ABI *abi = nullptr;117 118 if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))119 return;120 121 if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr,122 start_load_addr, args))123 return;124 125 ReportRegisterState("Function call was set up. Register state was:");126 127 m_valid = true;128}129 130ThreadPlanCallFunction::ThreadPlanCallFunction(131 Thread &thread, const Address &function,132 const EvaluateExpressionOptions &options)133 : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,134 eVoteNoOpinion, eVoteNoOpinion),135 m_valid(false), m_stop_other_threads(options.GetStopOthers()),136 m_unwind_on_error(options.DoesUnwindOnError()),137 m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),138 m_debug_execution(options.GetDebug()),139 m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),140 m_start_addr(), m_function_sp(0), m_subplan_sp(),141 m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr),142 m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(),143 m_return_valobj_sp(), m_takedown_done(false),144 m_should_clear_objc_exception_bp(false),145 m_should_clear_cxx_exception_bp(false),146 m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {}147 148ThreadPlanCallFunction::~ThreadPlanCallFunction() {149 DoTakedown(PlanSucceeded());150}151 152void ThreadPlanCallFunction::ReportRegisterState(const char *message) {153 Log *log = GetLog(LLDBLog::Step);154 if (log && log->GetVerbose()) {155 StreamString strm;156 RegisterContext *reg_ctx = GetThread().GetRegisterContext().get();157 158 log->PutCString(message);159 160 RegisterValue reg_value;161 162 for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();163 reg_idx < num_registers; ++reg_idx) {164 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);165 if (reg_ctx->ReadRegister(reg_info, reg_value)) {166 DumpRegisterValue(reg_value, strm, *reg_info, true, false,167 eFormatDefault);168 strm.EOL();169 }170 }171 log->PutString(strm.GetString());172 }173}174 175void ThreadPlanCallFunction::DoTakedown(bool success) {176 Log *log = GetLog(LLDBLog::Step);177 Thread &thread = GetThread();178 179 if (!m_valid) {180 // If ConstructorSetup was succesfull but PrepareTrivialCall was not,181 // we will have a saved register state and potentially modified registers.182 // Restore those.183 if (m_stored_thread_state.register_backup_sp)184 if (!thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state))185 LLDB_LOGF(186 log,187 "ThreadPlanCallFunction(%p): Failed to restore register state from "188 "invalid plan that contained a saved register state.",189 static_cast<void *>(this));190 191 // Don't call DoTakedown if we were never valid to begin with.192 LLDB_LOGF(log,193 "ThreadPlanCallFunction(%p): Log called on "194 "ThreadPlanCallFunction that was never valid.",195 static_cast<void *>(this));196 return;197 }198 199 if (!m_takedown_done) {200 if (success) {201 SetReturnValue();202 }203 LLDB_LOGF(log,204 "ThreadPlanCallFunction(%p): DoTakedown called for thread "205 "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",206 static_cast<void *>(this), m_tid, m_valid, IsPlanComplete());207 m_takedown_done = true;208 m_stop_address =209 thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();210 m_real_stop_info_sp = GetPrivateStopInfo();211 if (!thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) {212 LLDB_LOGF(log,213 "ThreadPlanCallFunction(%p): DoTakedown failed to restore "214 "register state",215 static_cast<void *>(this));216 }217 SetPlanComplete(success);218 ClearBreakpoints();219 if (log && log->GetVerbose())220 ReportRegisterState("Restoring thread state after function call. "221 "Restored register state:");222 } else {223 LLDB_LOGF(log,224 "ThreadPlanCallFunction(%p): DoTakedown called as no-op for "225 "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",226 static_cast<void *>(this), m_tid, m_valid, IsPlanComplete());227 }228}229 230void ThreadPlanCallFunction::DidPop() { DoTakedown(PlanSucceeded()); }231 232void ThreadPlanCallFunction::GetDescription(Stream *s, DescriptionLevel level) {233 if (level == eDescriptionLevelBrief) {234 s->Printf("Function call thread plan");235 } else {236 s->Printf("Thread plan to call 0x%" PRIx64,237 m_function_addr.GetLoadAddress(&GetTarget()));238 }239}240 241bool ThreadPlanCallFunction::ValidatePlan(Stream *error) {242 if (!m_valid) {243 if (error) {244 if (m_constructor_errors.GetSize() > 0)245 error->PutCString(m_constructor_errors.GetString());246 else247 error->PutCString("Unknown error");248 }249 return false;250 }251 252 return true;253}254 255Vote ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) {256 if (m_takedown_done || IsPlanComplete())257 return eVoteYes;258 else259 return ThreadPlan::ShouldReportStop(event_ptr);260}261 262bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {263 Log *log(GetLog(LLDBLog::Step | LLDBLog::Process));264 m_real_stop_info_sp = GetPrivateStopInfo();265 266 // If our subplan knows why we stopped, even if it's done (which would267 // forward the question to us) we answer yes.268 if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) {269 SetPlanComplete();270 return true;271 }272 273 // Check if the breakpoint is one of ours.274 275 StopReason stop_reason;276 if (!m_real_stop_info_sp)277 stop_reason = eStopReasonNone;278 else279 stop_reason = m_real_stop_info_sp->GetStopReason();280 LLDB_LOG(log,281 "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - {0}.",282 Thread::StopReasonAsString(stop_reason));283 284 if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())285 return true;286 287 // One more quirk here. If this event was from Halt interrupting the target,288 // then we should not consider ourselves complete. Return true to289 // acknowledge the stop.290 if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {291 LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: The event is an "292 "Interrupt, returning true.");293 return true;294 }295 // We control breakpoints separately from other "stop reasons." So first,296 // check the case where we stopped for an internal breakpoint, in that case,297 // continue on. If it is not an internal breakpoint, consult298 // m_ignore_breakpoints.299 300 if (stop_reason == eStopReasonBreakpoint) {301 uint64_t break_site_id = m_real_stop_info_sp->GetValue();302 BreakpointSiteSP bp_site_sp;303 bp_site_sp = m_process.GetBreakpointSiteList().FindByID(break_site_id);304 if (bp_site_sp) {305 uint32_t num_owners = bp_site_sp->GetNumberOfConstituents();306 bool is_internal = true;307 for (uint32_t i = 0; i < num_owners; i++) {308 Breakpoint &bp = bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();309 LLDB_LOGF(log,310 "ThreadPlanCallFunction::PlanExplainsStop: hit "311 "breakpoint %d while calling function",312 bp.GetID());313 314 if (!bp.IsInternal()) {315 is_internal = false;316 break;317 }318 }319 if (is_internal) {320 LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop hit an "321 "internal breakpoint, not stopping.");322 return false;323 }324 }325 326 if (m_ignore_breakpoints) {327 LLDB_LOGF(log,328 "ThreadPlanCallFunction::PlanExplainsStop: we are ignoring "329 "breakpoints, overriding breakpoint stop info ShouldStop, "330 "returning true");331 m_real_stop_info_sp->OverrideShouldStop(false);332 return true;333 } else {334 LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: we are not "335 "ignoring breakpoints, overriding breakpoint stop info "336 "ShouldStop, returning true");337 m_real_stop_info_sp->OverrideShouldStop(true);338 return false;339 }340 } else if (!m_unwind_on_error) {341 // If we don't want to discard this plan, than any stop we don't understand342 // should be propagated up the stack.343 return false;344 } else {345 // If the subplan is running, any crashes are attributable to us. If we346 // want to discard the plan, then we say we explain the stop but if we are347 // going to be discarded, let whoever is above us explain the stop. But348 // don't discard the plan if the stop would restart itself (for instance if349 // it is a signal that is set not to stop. Check that here first. We just350 // say we explain the stop but aren't done and everything will continue on351 // from there.352 353 if (m_real_stop_info_sp &&354 m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) {355 SetPlanComplete(false);356 return m_subplan_sp ? m_unwind_on_error : false;357 } else358 return true;359 }360}361 362bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) {363 // We do some computation in DoPlanExplainsStop that may or may not set the364 // plan as complete. We need to do that here to make sure our state is365 // correct.366 DoPlanExplainsStop(event_ptr);367 368 if (IsPlanComplete()) {369 ReportRegisterState("Function completed. Register state was:");370 return true;371 } else {372 return false;373 }374}375 376bool ThreadPlanCallFunction::StopOthers() { return m_stop_other_threads; }377 378StateType ThreadPlanCallFunction::GetPlanRunState() { return eStateRunning; }379 380void ThreadPlanCallFunction::DidPush() {381 //#define SINGLE_STEP_EXPRESSIONS382 383 // Now set the thread state to "no reason" so we don't run with whatever384 // signal was outstanding... Wait till the plan is pushed so we aren't385 // changing the stop info till we're about to run.386 387 GetThread().SetStopInfoToNothing();388 389#ifndef SINGLE_STEP_EXPRESSIONS390 Thread &thread = GetThread();391 m_subplan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, m_start_addr, 392 m_stop_other_threads);393 394 thread.QueueThreadPlan(m_subplan_sp, false);395 m_subplan_sp->SetPrivate(true);396#endif397}398 399bool ThreadPlanCallFunction::WillStop() { return true; }400 401bool ThreadPlanCallFunction::MischiefManaged() {402 Log *log = GetLog(LLDBLog::Step);403 404 if (IsPlanComplete()) {405 LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.",406 static_cast<void *>(this));407 408 ThreadPlan::MischiefManaged();409 return true;410 } else {411 return false;412 }413}414 415void ThreadPlanCallFunction::SetBreakpoints() {416 if (m_trap_exceptions) {417 m_cxx_language_runtime =418 m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);419 m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);420 421 if (m_cxx_language_runtime) {422 m_should_clear_cxx_exception_bp =423 !m_cxx_language_runtime->ExceptionBreakpointsAreSet();424 m_cxx_language_runtime->SetExceptionBreakpoints();425 }426 if (m_objc_language_runtime) {427 m_should_clear_objc_exception_bp =428 !m_objc_language_runtime->ExceptionBreakpointsAreSet();429 m_objc_language_runtime->SetExceptionBreakpoints();430 }431 }432}433 434void ThreadPlanCallFunction::ClearBreakpoints() {435 if (m_trap_exceptions) {436 if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)437 m_cxx_language_runtime->ClearExceptionBreakpoints();438 if (m_objc_language_runtime && m_should_clear_objc_exception_bp)439 m_objc_language_runtime->ClearExceptionBreakpoints();440 }441}442 443bool ThreadPlanCallFunction::BreakpointsExplainStop() {444 StopInfoSP stop_info_sp = GetPrivateStopInfo();445 446 if (m_trap_exceptions) {447 if ((m_cxx_language_runtime &&448 m_cxx_language_runtime->ExceptionBreakpointsExplainStop(449 stop_info_sp)) ||450 (m_objc_language_runtime &&451 m_objc_language_runtime->ExceptionBreakpointsExplainStop(452 stop_info_sp))) {453 Log *log = GetLog(LLDBLog::Step);454 LLDB_LOGF(log, "ThreadPlanCallFunction::BreakpointsExplainStop - Hit an "455 "exception breakpoint, setting plan complete.");456 457 SetPlanComplete(false);458 459 // If the user has set the ObjC language breakpoint, it would normally460 // get priority over our internal catcher breakpoint, but in this case we461 // can't let that happen, so force the ShouldStop here.462 stop_info_sp->OverrideShouldStop(true);463 return true;464 }465 }466 467 return false;468}469 470void ThreadPlanCallFunction::SetStopOthers(bool new_value) {471 m_subplan_sp->SetStopOthers(new_value);472}473 474void ThreadPlanCallFunction::RestoreThreadState() {475 GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);476}477 478void ThreadPlanCallFunction::SetReturnValue() {479 const ABI *abi = m_process.GetABI().get();480 if (abi && m_return_type.IsValid()) {481 const bool persistent = false;482 m_return_valobj_sp =483 abi->GetReturnValueObject(GetThread(), m_return_type, persistent);484 }485}486