xref: /src/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- ThreadPlanCallFunction.cpp ----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9e81d9d49SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h"
10f034231aSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
11f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
12f034231aSEd Maste #include "lldb/Core/Address.h"
13f73363f1SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
14f034231aSEd Maste #include "lldb/Core/Module.h"
15f034231aSEd Maste #include "lldb/Symbol/ObjectFile.h"
165e95aa85SEd Maste #include "lldb/Target/ABI.h"
17f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
18f034231aSEd Maste #include "lldb/Target/Process.h"
19f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
20f034231aSEd Maste #include "lldb/Target/StopInfo.h"
21f034231aSEd Maste #include "lldb/Target/Target.h"
22f034231aSEd Maste #include "lldb/Target/Thread.h"
23f034231aSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
24145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
2574a628f7SDimitry Andric #include "lldb/Utility/Log.h"
2674a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
27f034231aSEd Maste 
285f29bb8aSDimitry Andric #include <memory>
295f29bb8aSDimitry Andric 
30f034231aSEd Maste using namespace lldb;
31f034231aSEd Maste using namespace lldb_private;
32f034231aSEd Maste 
33f034231aSEd Maste // ThreadPlanCallFunction: Plan to call a single function
ConstructorSetup(Thread & thread,ABI * & abi,lldb::addr_t & start_load_addr,lldb::addr_t & function_load_addr)3414f1b3e8SDimitry Andric bool ThreadPlanCallFunction::ConstructorSetup(
3514f1b3e8SDimitry Andric     Thread &thread, ABI *&abi, lldb::addr_t &start_load_addr,
3614f1b3e8SDimitry Andric     lldb::addr_t &function_load_addr) {
37c0981da4SDimitry Andric   SetIsControllingPlan(true);
38f034231aSEd Maste   SetOkayToDiscard(false);
39f034231aSEd Maste   SetPrivate(true);
40f034231aSEd Maste 
41f034231aSEd Maste   ProcessSP process_sp(thread.GetProcess());
42f034231aSEd Maste   if (!process_sp)
43f034231aSEd Maste     return false;
44f034231aSEd Maste 
45f034231aSEd Maste   abi = process_sp->GetABI().get();
46f034231aSEd Maste 
47f034231aSEd Maste   if (!abi)
48f034231aSEd Maste     return false;
49f034231aSEd Maste 
50145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
51f034231aSEd Maste 
52f034231aSEd Maste   SetBreakpoints();
53f034231aSEd Maste 
54f034231aSEd Maste   m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
5514f1b3e8SDimitry Andric   // If we can't read memory at the point of the process where we are planning
56f73363f1SDimitry Andric   // to put our function, we're not going to get any further...
57b76161e4SDimitry Andric   Status error;
58f034231aSEd Maste   process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
5914f1b3e8SDimitry Andric   if (!error.Success()) {
6014f1b3e8SDimitry Andric     m_constructor_errors.Printf(
6114f1b3e8SDimitry Andric         "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".",
6214f1b3e8SDimitry Andric         m_function_sp);
63ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
640cac4ca3SEd Maste               m_constructor_errors.GetData());
65f034231aSEd Maste     return false;
66f034231aSEd Maste   }
67f034231aSEd Maste 
68ead24645SDimitry Andric   llvm::Expected<Address> start_address = GetTarget().GetEntryPointAddress();
69ead24645SDimitry Andric   if (!start_address) {
7014f1b3e8SDimitry Andric     m_constructor_errors.Printf(
71ead24645SDimitry Andric         "%s", llvm::toString(start_address.takeError()).c_str());
72ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
730cac4ca3SEd Maste               m_constructor_errors.GetData());
74f034231aSEd Maste     return false;
75f034231aSEd Maste   }
76f034231aSEd Maste 
77ead24645SDimitry Andric   m_start_addr = *start_address;
7886758c71SEd Maste   start_load_addr = m_start_addr.GetLoadAddress(&GetTarget());
79f034231aSEd Maste 
80f034231aSEd Maste   // Checkpoint the thread state so we can restore it later.
81f034231aSEd Maste   if (log && log->GetVerbose())
8214f1b3e8SDimitry Andric     ReportRegisterState("About to checkpoint thread before function call.  "
8314f1b3e8SDimitry Andric                         "Original register state was:");
84f034231aSEd Maste 
8514f1b3e8SDimitry Andric   if (!thread.CheckpointThreadState(m_stored_thread_state)) {
8614f1b3e8SDimitry Andric     m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to "
8714f1b3e8SDimitry Andric                                 "checkpoint thread state.");
88ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
890cac4ca3SEd Maste               m_constructor_errors.GetData());
90f034231aSEd Maste     return false;
91f034231aSEd Maste   }
9286758c71SEd Maste   function_load_addr = m_function_addr.GetLoadAddress(&GetTarget());
93f034231aSEd Maste 
94f034231aSEd Maste   return true;
95f034231aSEd Maste }
96f034231aSEd Maste 
ThreadPlanCallFunction(Thread & thread,const Address & function,const CompilerType & return_type,llvm::ArrayRef<addr_t> args,const EvaluateExpressionOptions & options)9714f1b3e8SDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction(
9814f1b3e8SDimitry Andric     Thread &thread, const Address &function, const CompilerType &return_type,
9914f1b3e8SDimitry Andric     llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options)
10014f1b3e8SDimitry Andric     : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,
10114f1b3e8SDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
10214f1b3e8SDimitry Andric       m_valid(false), m_stop_other_threads(options.GetStopOthers()),
10386758c71SEd Maste       m_unwind_on_error(options.DoesUnwindOnError()),
10486758c71SEd Maste       m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),
10586758c71SEd Maste       m_debug_execution(options.GetDebug()),
10614f1b3e8SDimitry Andric       m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),
10708e8dd7bSDimitry Andric       m_start_addr(), m_function_sp(0), m_subplan_sp(),
10808e8dd7bSDimitry Andric       m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr),
10908e8dd7bSDimitry Andric       m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(),
11008e8dd7bSDimitry Andric       m_return_valobj_sp(), m_takedown_done(false),
11186758c71SEd Maste       m_should_clear_objc_exception_bp(false),
11286758c71SEd Maste       m_should_clear_cxx_exception_bp(false),
11314f1b3e8SDimitry Andric       m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) {
114027f1c96SDimitry Andric   lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
115027f1c96SDimitry Andric   lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
116027f1c96SDimitry Andric   ABI *abi = nullptr;
117027f1c96SDimitry Andric 
118f034231aSEd Maste   if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
119f034231aSEd Maste     return;
120f034231aSEd Maste 
12114f1b3e8SDimitry Andric   if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr,
12214f1b3e8SDimitry Andric                                start_load_addr, args))
123f034231aSEd Maste     return;
124f034231aSEd Maste 
125f034231aSEd Maste   ReportRegisterState("Function call was set up.  Register state was:");
126f034231aSEd Maste 
127f034231aSEd Maste   m_valid = true;
128f034231aSEd Maste }
129f034231aSEd Maste 
ThreadPlanCallFunction(Thread & thread,const Address & function,const EvaluateExpressionOptions & options)13014f1b3e8SDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction(
13114f1b3e8SDimitry Andric     Thread &thread, const Address &function,
13214f1b3e8SDimitry Andric     const EvaluateExpressionOptions &options)
13314f1b3e8SDimitry Andric     : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread,
13414f1b3e8SDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
13514f1b3e8SDimitry Andric       m_valid(false), m_stop_other_threads(options.GetStopOthers()),
136027f1c96SDimitry Andric       m_unwind_on_error(options.DoesUnwindOnError()),
137027f1c96SDimitry Andric       m_ignore_breakpoints(options.DoesIgnoreBreakpoints()),
138027f1c96SDimitry Andric       m_debug_execution(options.GetDebug()),
13914f1b3e8SDimitry Andric       m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function),
14008e8dd7bSDimitry Andric       m_start_addr(), m_function_sp(0), m_subplan_sp(),
14108e8dd7bSDimitry Andric       m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr),
14208e8dd7bSDimitry Andric       m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(),
14308e8dd7bSDimitry Andric       m_return_valobj_sp(), m_takedown_done(false),
144027f1c96SDimitry Andric       m_should_clear_objc_exception_bp(false),
145027f1c96SDimitry Andric       m_should_clear_cxx_exception_bp(false),
14614f1b3e8SDimitry Andric       m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {}
147027f1c96SDimitry Andric 
~ThreadPlanCallFunction()14814f1b3e8SDimitry Andric ThreadPlanCallFunction::~ThreadPlanCallFunction() {
149f034231aSEd Maste   DoTakedown(PlanSucceeded());
150f034231aSEd Maste }
151f034231aSEd Maste 
ReportRegisterState(const char * message)15214f1b3e8SDimitry Andric void ThreadPlanCallFunction::ReportRegisterState(const char *message) {
153145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
15474a628f7SDimitry Andric   if (log && log->GetVerbose()) {
155f034231aSEd Maste     StreamString strm;
156cfca06d7SDimitry Andric     RegisterContext *reg_ctx = GetThread().GetRegisterContext().get();
157f034231aSEd Maste 
158f034231aSEd Maste     log->PutCString(message);
159f034231aSEd Maste 
160f034231aSEd Maste     RegisterValue reg_value;
161f034231aSEd Maste 
162f034231aSEd Maste     for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
16314f1b3e8SDimitry Andric          reg_idx < num_registers; ++reg_idx) {
164f034231aSEd Maste       const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
16514f1b3e8SDimitry Andric       if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1667fa27ce4SDimitry Andric         DumpRegisterValue(reg_value, strm, *reg_info, true, false,
167f73363f1SDimitry Andric                           eFormatDefault);
168f034231aSEd Maste         strm.EOL();
169f034231aSEd Maste       }
170f034231aSEd Maste     }
17114f1b3e8SDimitry Andric     log->PutString(strm.GetString());
172f034231aSEd Maste   }
173f034231aSEd Maste }
174f034231aSEd Maste 
DoTakedown(bool success)17514f1b3e8SDimitry Andric void ThreadPlanCallFunction::DoTakedown(bool success) {
176145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
177f034231aSEd Maste 
17814f1b3e8SDimitry Andric   if (!m_valid) {
179f034231aSEd Maste     // Don't call DoTakedown if we were never valid to begin with.
180ead24645SDimitry Andric     LLDB_LOGF(log,
181ead24645SDimitry Andric               "ThreadPlanCallFunction(%p): Log called on "
18214f1b3e8SDimitry Andric               "ThreadPlanCallFunction that was never valid.",
1830cac4ca3SEd Maste               static_cast<void *>(this));
184f034231aSEd Maste     return;
185f034231aSEd Maste   }
186f034231aSEd Maste 
18714f1b3e8SDimitry Andric   if (!m_takedown_done) {
188cfca06d7SDimitry Andric     Thread &thread = GetThread();
18914f1b3e8SDimitry Andric     if (success) {
190027f1c96SDimitry Andric       SetReturnValue();
191f034231aSEd Maste     }
192ead24645SDimitry Andric     LLDB_LOGF(log,
193ead24645SDimitry Andric               "ThreadPlanCallFunction(%p): DoTakedown called for thread "
19414f1b3e8SDimitry Andric               "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
195cfca06d7SDimitry Andric               static_cast<void *>(this), m_tid, m_valid, IsPlanComplete());
196f034231aSEd Maste     m_takedown_done = true;
19714f1b3e8SDimitry Andric     m_stop_address =
198cfca06d7SDimitry Andric         thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
199f034231aSEd Maste     m_real_stop_info_sp = GetPrivateStopInfo();
200cfca06d7SDimitry Andric     if (!thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) {
201ead24645SDimitry Andric       LLDB_LOGF(log,
202ead24645SDimitry Andric                 "ThreadPlanCallFunction(%p): DoTakedown failed to restore "
20314f1b3e8SDimitry Andric                 "register state",
2040cac4ca3SEd Maste                 static_cast<void *>(this));
20586758c71SEd Maste     }
206f034231aSEd Maste     SetPlanComplete(success);
207f034231aSEd Maste     ClearBreakpoints();
208f034231aSEd Maste     if (log && log->GetVerbose())
20914f1b3e8SDimitry Andric       ReportRegisterState("Restoring thread state after function call.  "
21014f1b3e8SDimitry Andric                           "Restored register state:");
21114f1b3e8SDimitry Andric   } else {
212ead24645SDimitry Andric     LLDB_LOGF(log,
213ead24645SDimitry Andric               "ThreadPlanCallFunction(%p): DoTakedown called as no-op for "
21414f1b3e8SDimitry Andric               "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
215cfca06d7SDimitry Andric               static_cast<void *>(this), m_tid, m_valid, IsPlanComplete());
216f034231aSEd Maste   }
217f034231aSEd Maste }
218f034231aSEd Maste 
DidPop()219c0981da4SDimitry Andric void ThreadPlanCallFunction::DidPop() { DoTakedown(PlanSucceeded()); }
220f034231aSEd Maste 
GetDescription(Stream * s,DescriptionLevel level)22114f1b3e8SDimitry Andric void ThreadPlanCallFunction::GetDescription(Stream *s, DescriptionLevel level) {
22214f1b3e8SDimitry Andric   if (level == eDescriptionLevelBrief) {
223f034231aSEd Maste     s->Printf("Function call thread plan");
22414f1b3e8SDimitry Andric   } else {
22514f1b3e8SDimitry Andric     s->Printf("Thread plan to call 0x%" PRIx64,
226cfca06d7SDimitry Andric               m_function_addr.GetLoadAddress(&GetTarget()));
227f034231aSEd Maste   }
228f034231aSEd Maste }
229f034231aSEd Maste 
ValidatePlan(Stream * error)23014f1b3e8SDimitry Andric bool ThreadPlanCallFunction::ValidatePlan(Stream *error) {
23114f1b3e8SDimitry Andric   if (!m_valid) {
23214f1b3e8SDimitry Andric     if (error) {
233f034231aSEd Maste       if (m_constructor_errors.GetSize() > 0)
23414f1b3e8SDimitry Andric         error->PutCString(m_constructor_errors.GetString());
235f034231aSEd Maste       else
236f034231aSEd Maste         error->PutCString("Unknown error");
237f034231aSEd Maste     }
238f034231aSEd Maste     return false;
239f034231aSEd Maste   }
240f034231aSEd Maste 
241f034231aSEd Maste   return true;
242f034231aSEd Maste }
243f034231aSEd Maste 
ShouldReportStop(Event * event_ptr)24414f1b3e8SDimitry Andric Vote ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) {
245f034231aSEd Maste   if (m_takedown_done || IsPlanComplete())
246f034231aSEd Maste     return eVoteYes;
247f034231aSEd Maste   else
248f034231aSEd Maste     return ThreadPlan::ShouldReportStop(event_ptr);
249f034231aSEd Maste }
250f034231aSEd Maste 
DoPlanExplainsStop(Event * event_ptr)25114f1b3e8SDimitry Andric bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) {
252145449b1SDimitry Andric   Log *log(GetLog(LLDBLog::Step | LLDBLog::Process));
253f034231aSEd Maste   m_real_stop_info_sp = GetPrivateStopInfo();
254f034231aSEd Maste 
255f73363f1SDimitry Andric   // If our subplan knows why we stopped, even if it's done (which would
256f73363f1SDimitry Andric   // forward the question to us) we answer yes.
25714f1b3e8SDimitry Andric   if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) {
258f034231aSEd Maste     SetPlanComplete();
259f034231aSEd Maste     return true;
260f034231aSEd Maste   }
261f034231aSEd Maste 
262f034231aSEd Maste   // Check if the breakpoint is one of ours.
263f034231aSEd Maste 
264f034231aSEd Maste   StopReason stop_reason;
265f034231aSEd Maste   if (!m_real_stop_info_sp)
266f034231aSEd Maste     stop_reason = eStopReasonNone;
267f034231aSEd Maste   else
268f034231aSEd Maste     stop_reason = m_real_stop_info_sp->GetStopReason();
269b60736ecSDimitry Andric   LLDB_LOG(log,
270b60736ecSDimitry Andric            "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - {0}.",
271b60736ecSDimitry Andric            Thread::StopReasonAsString(stop_reason));
272f034231aSEd Maste 
273f034231aSEd Maste   if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
274f034231aSEd Maste     return true;
275f034231aSEd Maste 
27614f1b3e8SDimitry Andric   // One more quirk here.  If this event was from Halt interrupting the target,
277f73363f1SDimitry Andric   // then we should not consider ourselves complete.  Return true to
278f73363f1SDimitry Andric   // acknowledge the stop.
27914f1b3e8SDimitry Andric   if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
280ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: The event is an "
28114f1b3e8SDimitry Andric                    "Interrupt, returning true.");
2820cac4ca3SEd Maste     return true;
2830cac4ca3SEd Maste   }
284f034231aSEd Maste   // We control breakpoints separately from other "stop reasons."  So first,
28514f1b3e8SDimitry Andric   // check the case where we stopped for an internal breakpoint, in that case,
286f73363f1SDimitry Andric   // continue on. If it is not an internal breakpoint, consult
287f73363f1SDimitry Andric   // m_ignore_breakpoints.
288f034231aSEd Maste 
28914f1b3e8SDimitry Andric   if (stop_reason == eStopReasonBreakpoint) {
290f034231aSEd Maste     uint64_t break_site_id = m_real_stop_info_sp->GetValue();
291f034231aSEd Maste     BreakpointSiteSP bp_site_sp;
292cfca06d7SDimitry Andric     bp_site_sp = m_process.GetBreakpointSiteList().FindByID(break_site_id);
29314f1b3e8SDimitry Andric     if (bp_site_sp) {
294b1c73532SDimitry Andric       uint32_t num_owners = bp_site_sp->GetNumberOfConstituents();
295f034231aSEd Maste       bool is_internal = true;
29614f1b3e8SDimitry Andric       for (uint32_t i = 0; i < num_owners; i++) {
297b1c73532SDimitry Andric         Breakpoint &bp = bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();
298ead24645SDimitry Andric         LLDB_LOGF(log,
299ead24645SDimitry Andric                   "ThreadPlanCallFunction::PlanExplainsStop: hit "
30014f1b3e8SDimitry Andric                   "breakpoint %d while calling function",
30114f1b3e8SDimitry Andric                   bp.GetID());
302f034231aSEd Maste 
30314f1b3e8SDimitry Andric         if (!bp.IsInternal()) {
304f034231aSEd Maste           is_internal = false;
305f034231aSEd Maste           break;
306f034231aSEd Maste         }
307f034231aSEd Maste       }
30814f1b3e8SDimitry Andric       if (is_internal) {
309ead24645SDimitry Andric         LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop hit an "
31014f1b3e8SDimitry Andric                        "internal breakpoint, not stopping.");
311f034231aSEd Maste         return false;
312f034231aSEd Maste       }
313f034231aSEd Maste     }
314f034231aSEd Maste 
31514f1b3e8SDimitry Andric     if (m_ignore_breakpoints) {
316ead24645SDimitry Andric       LLDB_LOGF(log,
317ead24645SDimitry Andric                 "ThreadPlanCallFunction::PlanExplainsStop: we are ignoring "
31814f1b3e8SDimitry Andric                 "breakpoints, overriding breakpoint stop info ShouldStop, "
31914f1b3e8SDimitry Andric                 "returning true");
320f034231aSEd Maste       m_real_stop_info_sp->OverrideShouldStop(false);
321f034231aSEd Maste       return true;
32214f1b3e8SDimitry Andric     } else {
323ead24645SDimitry Andric       LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: we are not "
32414f1b3e8SDimitry Andric                      "ignoring breakpoints, overriding breakpoint stop info "
32514f1b3e8SDimitry Andric                      "ShouldStop, returning true");
326f034231aSEd Maste       m_real_stop_info_sp->OverrideShouldStop(true);
327f034231aSEd Maste       return false;
328f034231aSEd Maste     }
32914f1b3e8SDimitry Andric   } else if (!m_unwind_on_error) {
33014f1b3e8SDimitry Andric     // If we don't want to discard this plan, than any stop we don't understand
33114f1b3e8SDimitry Andric     // should be propagated up the stack.
332f034231aSEd Maste     return false;
33314f1b3e8SDimitry Andric   } else {
334f73363f1SDimitry Andric     // If the subplan is running, any crashes are attributable to us. If we
335f73363f1SDimitry Andric     // want to discard the plan, then we say we explain the stop but if we are
336f73363f1SDimitry Andric     // going to be discarded, let whoever is above us explain the stop. But
337f73363f1SDimitry Andric     // don't discard the plan if the stop would restart itself (for instance if
338f73363f1SDimitry Andric     // it is a signal that is set not to stop.  Check that here first.  We just
339f73363f1SDimitry Andric     // say we explain the stop but aren't done and everything will continue on
340f73363f1SDimitry Andric     // from there.
341f034231aSEd Maste 
34214f1b3e8SDimitry Andric     if (m_real_stop_info_sp &&
34314f1b3e8SDimitry Andric         m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) {
344f034231aSEd Maste       SetPlanComplete(false);
345e81d9d49SDimitry Andric       return m_subplan_sp ? m_unwind_on_error : false;
34614f1b3e8SDimitry Andric     } else
347f034231aSEd Maste       return true;
348f034231aSEd Maste   }
349f034231aSEd Maste }
350f034231aSEd Maste 
ShouldStop(Event * event_ptr)35114f1b3e8SDimitry Andric bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) {
35214f1b3e8SDimitry Andric   // We do some computation in DoPlanExplainsStop that may or may not set the
353f73363f1SDimitry Andric   // plan as complete. We need to do that here to make sure our state is
354f73363f1SDimitry Andric   // correct.
355f034231aSEd Maste   DoPlanExplainsStop(event_ptr);
356f034231aSEd Maste 
35714f1b3e8SDimitry Andric   if (IsPlanComplete()) {
358f034231aSEd Maste     ReportRegisterState("Function completed.  Register state was:");
359f034231aSEd Maste     return true;
36014f1b3e8SDimitry Andric   } else {
361f034231aSEd Maste     return false;
362f034231aSEd Maste   }
363f034231aSEd Maste }
364f034231aSEd Maste 
StopOthers()36514f1b3e8SDimitry Andric bool ThreadPlanCallFunction::StopOthers() { return m_stop_other_threads; }
366f034231aSEd Maste 
GetPlanRunState()36714f1b3e8SDimitry Andric StateType ThreadPlanCallFunction::GetPlanRunState() { return eStateRunning; }
368f034231aSEd Maste 
DidPush()36914f1b3e8SDimitry Andric void ThreadPlanCallFunction::DidPush() {
370f034231aSEd Maste   //#define SINGLE_STEP_EXPRESSIONS
371f034231aSEd Maste 
37214f1b3e8SDimitry Andric   // Now set the thread state to "no reason" so we don't run with whatever
373f73363f1SDimitry Andric   // signal was outstanding... Wait till the plan is pushed so we aren't
374f73363f1SDimitry Andric   // changing the stop info till we're about to run.
375f034231aSEd Maste 
376f034231aSEd Maste   GetThread().SetStopInfoToNothing();
377f034231aSEd Maste 
378f034231aSEd Maste #ifndef SINGLE_STEP_EXPRESSIONS
379cfca06d7SDimitry Andric   Thread &thread = GetThread();
380cfca06d7SDimitry Andric   m_subplan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, m_start_addr,
381cfca06d7SDimitry Andric                                                           m_stop_other_threads);
382f034231aSEd Maste 
383cfca06d7SDimitry Andric   thread.QueueThreadPlan(m_subplan_sp, false);
384f034231aSEd Maste   m_subplan_sp->SetPrivate(true);
385f034231aSEd Maste #endif
386f034231aSEd Maste }
387f034231aSEd Maste 
WillStop()38814f1b3e8SDimitry Andric bool ThreadPlanCallFunction::WillStop() { return true; }
389f034231aSEd Maste 
MischiefManaged()39014f1b3e8SDimitry Andric bool ThreadPlanCallFunction::MischiefManaged() {
391145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
392f034231aSEd Maste 
39314f1b3e8SDimitry Andric   if (IsPlanComplete()) {
394ead24645SDimitry Andric     LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.",
3950cac4ca3SEd Maste               static_cast<void *>(this));
396f034231aSEd Maste 
397f034231aSEd Maste     ThreadPlan::MischiefManaged();
398f034231aSEd Maste     return true;
39914f1b3e8SDimitry Andric   } else {
400f034231aSEd Maste     return false;
401f034231aSEd Maste   }
402f034231aSEd Maste }
403f034231aSEd Maste 
SetBreakpoints()40414f1b3e8SDimitry Andric void ThreadPlanCallFunction::SetBreakpoints() {
405cfca06d7SDimitry Andric   if (m_trap_exceptions) {
40614f1b3e8SDimitry Andric     m_cxx_language_runtime =
407cfca06d7SDimitry Andric         m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
408cfca06d7SDimitry Andric     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
409f034231aSEd Maste 
41014f1b3e8SDimitry Andric     if (m_cxx_language_runtime) {
41114f1b3e8SDimitry Andric       m_should_clear_cxx_exception_bp =
41214f1b3e8SDimitry Andric           !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
413f034231aSEd Maste       m_cxx_language_runtime->SetExceptionBreakpoints();
41486758c71SEd Maste     }
41514f1b3e8SDimitry Andric     if (m_objc_language_runtime) {
41614f1b3e8SDimitry Andric       m_should_clear_objc_exception_bp =
41714f1b3e8SDimitry Andric           !m_objc_language_runtime->ExceptionBreakpointsAreSet();
418f034231aSEd Maste       m_objc_language_runtime->SetExceptionBreakpoints();
419f034231aSEd Maste     }
420f034231aSEd Maste   }
42186758c71SEd Maste }
422f034231aSEd Maste 
ClearBreakpoints()42314f1b3e8SDimitry Andric void ThreadPlanCallFunction::ClearBreakpoints() {
42414f1b3e8SDimitry Andric   if (m_trap_exceptions) {
42586758c71SEd Maste     if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
426f034231aSEd Maste       m_cxx_language_runtime->ClearExceptionBreakpoints();
42786758c71SEd Maste     if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
428f034231aSEd Maste       m_objc_language_runtime->ClearExceptionBreakpoints();
429f034231aSEd Maste   }
43086758c71SEd Maste }
431f034231aSEd Maste 
BreakpointsExplainStop()43214f1b3e8SDimitry Andric bool ThreadPlanCallFunction::BreakpointsExplainStop() {
433f034231aSEd Maste   StopInfoSP stop_info_sp = GetPrivateStopInfo();
434f034231aSEd Maste 
43514f1b3e8SDimitry Andric   if (m_trap_exceptions) {
436f034231aSEd Maste     if ((m_cxx_language_runtime &&
43714f1b3e8SDimitry Andric          m_cxx_language_runtime->ExceptionBreakpointsExplainStop(
43814f1b3e8SDimitry Andric              stop_info_sp)) ||
43914f1b3e8SDimitry Andric         (m_objc_language_runtime &&
44014f1b3e8SDimitry Andric          m_objc_language_runtime->ExceptionBreakpointsExplainStop(
44114f1b3e8SDimitry Andric              stop_info_sp))) {
442145449b1SDimitry Andric       Log *log = GetLog(LLDBLog::Step);
443ead24645SDimitry Andric       LLDB_LOGF(log, "ThreadPlanCallFunction::BreakpointsExplainStop - Hit an "
44414f1b3e8SDimitry Andric                      "exception breakpoint, setting plan complete.");
445f034231aSEd Maste 
446f034231aSEd Maste       SetPlanComplete(false);
447f034231aSEd Maste 
448f73363f1SDimitry Andric       // If the user has set the ObjC language breakpoint, it would normally
449f73363f1SDimitry Andric       // get priority over our internal catcher breakpoint, but in this case we
450f73363f1SDimitry Andric       // can't let that happen, so force the ShouldStop here.
451f034231aSEd Maste       stop_info_sp->OverrideShouldStop(true);
452f034231aSEd Maste       return true;
453f034231aSEd Maste     }
45486758c71SEd Maste   }
455f034231aSEd Maste 
456f034231aSEd Maste   return false;
457f034231aSEd Maste }
458f034231aSEd Maste 
SetStopOthers(bool new_value)45914f1b3e8SDimitry Andric void ThreadPlanCallFunction::SetStopOthers(bool new_value) {
4600cac4ca3SEd Maste   m_subplan_sp->SetStopOthers(new_value);
4610cac4ca3SEd Maste }
4620cac4ca3SEd Maste 
RestoreThreadState()463344a3780SDimitry Andric void ThreadPlanCallFunction::RestoreThreadState() {
464344a3780SDimitry Andric   GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
465f034231aSEd Maste }
466f034231aSEd Maste 
SetReturnValue()46714f1b3e8SDimitry Andric void ThreadPlanCallFunction::SetReturnValue() {
468cfca06d7SDimitry Andric   const ABI *abi = m_process.GetABI().get();
46914f1b3e8SDimitry Andric   if (abi && m_return_type.IsValid()) {
470027f1c96SDimitry Andric     const bool persistent = false;
47114f1b3e8SDimitry Andric     m_return_valobj_sp =
472cfca06d7SDimitry Andric         abi->GetReturnValueObject(GetThread(), m_return_type, persistent);
473027f1c96SDimitry Andric   }
474027f1c96SDimitry Andric }
475