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