130fdc8d8SChris Lattner //===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanCallFunction.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
156db73ca5SSean Callanan #include "llvm/Support/MachO.h"
1630fdc8d8SChris Lattner // Project includes
1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h"
1840d871faSJim Ingham #include "lldb/Breakpoint/Breakpoint.h"
1940d871faSJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h"
2030fdc8d8SChris Lattner #include "lldb/Core/Address.h"
2130fdc8d8SChris Lattner #include "lldb/Core/Log.h"
221f746071SGreg Clayton #include "lldb/Core/Module.h"
2330fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
241f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h"
25f211510fSSean Callanan #include "lldb/Target/LanguageRuntime.h"
2630fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2730fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
2840d871faSJim Ingham #include "lldb/Target/StopInfo.h"
2930fdc8d8SChris Lattner #include "lldb/Target/Target.h"
3030fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
3130fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h"
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner using namespace lldb;
3430fdc8d8SChris Lattner using namespace lldb_private;
3530fdc8d8SChris Lattner 
3630fdc8d8SChris Lattner //----------------------------------------------------------------------
3730fdc8d8SChris Lattner // ThreadPlanCallFunction: Plan to call a single function
3830fdc8d8SChris Lattner //----------------------------------------------------------------------
390092c8ebSJim Ingham bool
400092c8ebSJim Ingham ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
410092c8ebSJim Ingham                                           ABI *& abi,
420092c8ebSJim Ingham                                           lldb::addr_t &start_load_addr,
430092c8ebSJim Ingham                                           lldb::addr_t &function_load_addr)
440092c8ebSJim Ingham {
450092c8ebSJim Ingham     SetIsMasterPlan (true);
46923886ceSJim Ingham     SetOkayToDiscard (false);
47327c267aSAndrew Kaylor     SetPrivate (true);
480092c8ebSJim Ingham 
490092c8ebSJim Ingham     ProcessSP process_sp (thread.GetProcess());
500092c8ebSJim Ingham     if (!process_sp)
510092c8ebSJim Ingham         return false;
520092c8ebSJim Ingham 
530092c8ebSJim Ingham     abi = process_sp->GetABI().get();
540092c8ebSJim Ingham 
550092c8ebSJim Ingham     if (!abi)
560092c8ebSJim Ingham         return false;
570092c8ebSJim Ingham 
580092c8ebSJim Ingham     TargetSP target_sp (thread.CalculateTarget());
590092c8ebSJim Ingham 
605160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
610092c8ebSJim Ingham 
620092c8ebSJim Ingham     SetBreakpoints();
630092c8ebSJim Ingham 
640092c8ebSJim Ingham     m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
650092c8ebSJim Ingham     // If we can't read memory at the point of the process where we are planning to put our function, we're
660092c8ebSJim Ingham     // not going to get any further...
670092c8ebSJim Ingham     Error error;
680092c8ebSJim Ingham     process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
690092c8ebSJim Ingham     if (!error.Success())
700092c8ebSJim Ingham     {
71*ea06f3bfSJim Ingham         m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp);
720092c8ebSJim Ingham         if (log)
73*ea06f3bfSJim Ingham             log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
740092c8ebSJim Ingham         return false;
750092c8ebSJim Ingham     }
760092c8ebSJim Ingham 
770092c8ebSJim Ingham     Module *exe_module = target_sp->GetExecutableModulePointer();
780092c8ebSJim Ingham 
790092c8ebSJim Ingham     if (exe_module == NULL)
800092c8ebSJim Ingham     {
81*ea06f3bfSJim Ingham         m_constructor_errors.Printf ("Can't execute code without an executable module.");
820092c8ebSJim Ingham         if (log)
83*ea06f3bfSJim Ingham             log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
840092c8ebSJim Ingham         return false;
850092c8ebSJim Ingham     }
860092c8ebSJim Ingham     else
870092c8ebSJim Ingham     {
880092c8ebSJim Ingham         ObjectFile *objectFile = exe_module->GetObjectFile();
890092c8ebSJim Ingham         if (!objectFile)
900092c8ebSJim Ingham         {
91*ea06f3bfSJim Ingham             m_constructor_errors.Printf ("Could not find object file for module \"%s\".",
92*ea06f3bfSJim Ingham                                          exe_module->GetFileSpec().GetFilename().AsCString());
93*ea06f3bfSJim Ingham 
940092c8ebSJim Ingham             if (log)
95*ea06f3bfSJim Ingham                 log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
960092c8ebSJim Ingham             return false;
970092c8ebSJim Ingham         }
98*ea06f3bfSJim Ingham 
990092c8ebSJim Ingham         m_start_addr = objectFile->GetEntryPointAddress();
1000092c8ebSJim Ingham         if (!m_start_addr.IsValid())
1010092c8ebSJim Ingham         {
102*ea06f3bfSJim Ingham             m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".",
103*ea06f3bfSJim Ingham                                          exe_module->GetFileSpec().GetFilename().AsCString());
1040092c8ebSJim Ingham             if (log)
105*ea06f3bfSJim Ingham                 log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
1060092c8ebSJim Ingham             return false;
1070092c8ebSJim Ingham         }
1080092c8ebSJim Ingham     }
1090092c8ebSJim Ingham 
1100092c8ebSJim Ingham     start_load_addr = m_start_addr.GetLoadAddress (target_sp.get());
1110092c8ebSJim Ingham 
1120092c8ebSJim Ingham     // Checkpoint the thread state so we can restore it later.
1130092c8ebSJim Ingham     if (log && log->GetVerbose())
1140092c8ebSJim Ingham         ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
1150092c8ebSJim Ingham 
1160092c8ebSJim Ingham     if (!thread.CheckpointThreadState (m_stored_thread_state))
1170092c8ebSJim Ingham     {
118*ea06f3bfSJim Ingham         m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
1190092c8ebSJim Ingham         if (log)
120*ea06f3bfSJim Ingham             log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
1210092c8ebSJim Ingham         return false;
1220092c8ebSJim Ingham     }
1230092c8ebSJim Ingham     function_load_addr = m_function_addr.GetLoadAddress (target_sp.get());
1240092c8ebSJim Ingham 
1250092c8ebSJim Ingham     return true;
1260092c8ebSJim Ingham }
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
12900049b8bSMatt Kopec                                                 const Address &function,
130ef651600SJim Ingham                                                 const ClangASTType &return_type,
1312a48f525SGreg Clayton                                                 addr_t arg,
13230fdc8d8SChris Lattner                                                 bool stop_other_threads,
133184e9811SJim Ingham                                                 bool unwind_on_error,
134184e9811SJim Ingham                                                 bool ignore_breakpoints,
1352a48f525SGreg Clayton                                                 addr_t *this_arg,
1362a48f525SGreg Clayton                                                 addr_t *cmd_arg) :
137b01e742aSJim Ingham     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
13830fdc8d8SChris Lattner     m_valid (false),
1391ee0d4f7SBenjamin Kramer     m_stop_other_threads (stop_other_threads),
14016e0c686SJim Ingham     m_function_addr (function),
141b4cb0be3SFilipe Cabecinhas     m_function_sp (0),
142ef651600SJim Ingham     m_return_type (return_type),
143ce553d88SJim Ingham     m_takedown_done (false),
144923886ceSJim Ingham     m_stop_address (LLDB_INVALID_ADDRESS),
145184e9811SJim Ingham     m_unwind_on_error (unwind_on_error),
146184e9811SJim Ingham     m_ignore_breakpoints (ignore_breakpoints)
14730fdc8d8SChris Lattner {
1480092c8ebSJim Ingham     lldb::addr_t start_load_addr;
1490092c8ebSJim Ingham     ABI *abi;
1500092c8ebSJim Ingham     lldb::addr_t function_load_addr;
151923886ceSJim Ingham     if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
1521ac04c30SGreg Clayton         return;
1531ac04c30SGreg Clayton 
154fdeb1563SGreg Clayton     if (this_arg && cmd_arg)
155fdeb1563SGreg Clayton     {
15630fdc8d8SChris Lattner         if (!abi->PrepareTrivialCall (thread,
157e359d9b7SSean Callanan                                       m_function_sp,
1580092c8ebSJim Ingham                                       function_load_addr,
1592a48f525SGreg Clayton                                       start_load_addr,
16017827830SSean Callanan                                       this_arg,
161fdeb1563SGreg Clayton                                       cmd_arg,
1622a48f525SGreg Clayton                                       &arg))
16330fdc8d8SChris Lattner             return;
164fdeb1563SGreg Clayton     }
165fdeb1563SGreg Clayton     else if (this_arg)
166fdeb1563SGreg Clayton     {
167fdeb1563SGreg Clayton         if (!abi->PrepareTrivialCall (thread,
168fdeb1563SGreg Clayton                                       m_function_sp,
1690092c8ebSJim Ingham                                       function_load_addr,
1702a48f525SGreg Clayton                                       start_load_addr,
171fdeb1563SGreg Clayton                                       this_arg,
1722a48f525SGreg Clayton                                       &arg))
173fdeb1563SGreg Clayton             return;
174fdeb1563SGreg Clayton     }
175fdeb1563SGreg Clayton     else
176fdeb1563SGreg Clayton     {
177fdeb1563SGreg Clayton         if (!abi->PrepareTrivialCall (thread,
178fdeb1563SGreg Clayton                                       m_function_sp,
1790092c8ebSJim Ingham                                       function_load_addr,
1802a48f525SGreg Clayton                                       start_load_addr,
1812a48f525SGreg Clayton                                       &arg))
1822a48f525SGreg Clayton             return;
1832a48f525SGreg Clayton     }
1842a48f525SGreg Clayton 
1852a48f525SGreg Clayton     ReportRegisterState ("Function call was set up.  Register state was:");
1862a48f525SGreg Clayton 
1872a48f525SGreg Clayton     m_valid = true;
1882a48f525SGreg Clayton }
1892a48f525SGreg Clayton 
1902a48f525SGreg Clayton 
1912a48f525SGreg Clayton ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
19200049b8bSMatt Kopec                                                 const Address &function,
193ef651600SJim Ingham                                                 const ClangASTType &return_type,
1942a48f525SGreg Clayton                                                 bool stop_other_threads,
195184e9811SJim Ingham                                                 bool unwind_on_error,
196184e9811SJim Ingham                                                 bool ignore_breakpoints,
1972a48f525SGreg Clayton                                                 addr_t *arg1_ptr,
1982a48f525SGreg Clayton                                                 addr_t *arg2_ptr,
1992a48f525SGreg Clayton                                                 addr_t *arg3_ptr,
2002a48f525SGreg Clayton                                                 addr_t *arg4_ptr,
2012a48f525SGreg Clayton                                                 addr_t *arg5_ptr,
2022a48f525SGreg Clayton                                                 addr_t *arg6_ptr) :
2032a48f525SGreg Clayton     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
2042a48f525SGreg Clayton     m_valid (false),
2052a48f525SGreg Clayton     m_stop_other_threads (stop_other_threads),
20616e0c686SJim Ingham     m_function_addr (function),
207b4cb0be3SFilipe Cabecinhas     m_function_sp (0),
208ef651600SJim Ingham     m_return_type (return_type),
2090092c8ebSJim Ingham     m_takedown_done (false),
2108559a355SJim Ingham     m_stop_address (LLDB_INVALID_ADDRESS),
211184e9811SJim Ingham     m_unwind_on_error (unwind_on_error),
212184e9811SJim Ingham     m_ignore_breakpoints (ignore_breakpoints)
2132a48f525SGreg Clayton {
2140092c8ebSJim Ingham     lldb::addr_t start_load_addr;
2150092c8ebSJim Ingham     ABI *abi;
2160092c8ebSJim Ingham     lldb::addr_t function_load_addr;
217923886ceSJim Ingham     if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
2181ac04c30SGreg Clayton         return;
2191ac04c30SGreg Clayton 
2202a48f525SGreg Clayton     if (!abi->PrepareTrivialCall (thread,
2212a48f525SGreg Clayton                                   m_function_sp,
2220092c8ebSJim Ingham                                   function_load_addr,
2232a48f525SGreg Clayton                                   start_load_addr,
2242a48f525SGreg Clayton                                   arg1_ptr,
2252a48f525SGreg Clayton                                   arg2_ptr,
2262a48f525SGreg Clayton                                   arg3_ptr,
2272a48f525SGreg Clayton                                   arg4_ptr,
2282a48f525SGreg Clayton                                   arg5_ptr,
2292a48f525SGreg Clayton                                   arg6_ptr))
2302a48f525SGreg Clayton     {
231fdeb1563SGreg Clayton             return;
232fdeb1563SGreg Clayton     }
23330fdc8d8SChris Lattner 
2349da3683cSJim Ingham     ReportRegisterState ("Function call was set up.  Register state was:");
2359da3683cSJim Ingham 
2369da3683cSJim Ingham     m_valid = true;
2379da3683cSJim Ingham }
2389da3683cSJim Ingham 
2399da3683cSJim Ingham ThreadPlanCallFunction::~ThreadPlanCallFunction ()
2409da3683cSJim Ingham {
2410161b49cSJim Ingham     DoTakedown(PlanSucceeded());
2429da3683cSJim Ingham }
2439da3683cSJim Ingham 
2449da3683cSJim Ingham void
2459da3683cSJim Ingham ThreadPlanCallFunction::ReportRegisterState (const char *message)
2469da3683cSJim Ingham {
2475160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE));
248ece96492SSean Callanan     if (log)
249ece96492SSean Callanan     {
250af247d7bSGreg Clayton         StreamString strm;
2515ccbd294SGreg Clayton         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
252ece96492SSean Callanan 
2539da3683cSJim Ingham         log->PutCString(message);
254ece96492SSean Callanan 
255af247d7bSGreg Clayton         RegisterValue reg_value;
256ece96492SSean Callanan 
257af247d7bSGreg Clayton         for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
258af247d7bSGreg Clayton              reg_idx < num_registers;
259af247d7bSGreg Clayton              ++reg_idx)
260af247d7bSGreg Clayton         {
261af247d7bSGreg Clayton             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx);
262af247d7bSGreg Clayton             if (reg_ctx->ReadRegister(reg_info, reg_value))
263af247d7bSGreg Clayton             {
264af247d7bSGreg Clayton                 reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
265af247d7bSGreg Clayton                 strm.EOL();
266ece96492SSean Callanan             }
267ece96492SSean Callanan         }
268af247d7bSGreg Clayton         log->PutCString(strm.GetData());
269af247d7bSGreg Clayton     }
27010af7c43SSean Callanan }
27110af7c43SSean Callanan 
27210af7c43SSean Callanan void
27318de2fdcSJim Ingham ThreadPlanCallFunction::DoTakedown (bool success)
27410af7c43SSean Callanan {
2755160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
27687d0e618SJim Ingham 
27787d0e618SJim Ingham     if (!m_valid)
27887d0e618SJim Ingham     {
27987d0e618SJim Ingham         //Don't call DoTakedown if we were never valid to begin with.
28087d0e618SJim Ingham         if (log)
28187d0e618SJim Ingham             log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.", this);
28287d0e618SJim Ingham         return;
28387d0e618SJim Ingham     }
28487d0e618SJim Ingham 
2859da3683cSJim Ingham     if (!m_takedown_done)
28677787033SJim Ingham     {
28718de2fdcSJim Ingham         if (success)
28818de2fdcSJim Ingham         {
2891ac04c30SGreg Clayton             ProcessSP process_sp (m_thread.GetProcess());
2901ac04c30SGreg Clayton             const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
291ef651600SJim Ingham             if (abi && m_return_type.IsValid())
292ef651600SJim Ingham             {
2936153c518SSean Callanan                 const bool persistent = false;
2946153c518SSean Callanan                 m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent);
29570b57657SGreg Clayton             }
29618de2fdcSJim Ingham         }
2979da3683cSJim Ingham         if (log)
298d01b2953SDaniel Malea             log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
2999da3683cSJim Ingham         m_takedown_done = true;
300ce553d88SJim Ingham         m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
301160f78c5SJim Ingham         m_real_stop_info_sp = GetPrivateStopReason();
3028559a355SJim Ingham         m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state);
30318de2fdcSJim Ingham         SetPlanComplete(success);
30410af7c43SSean Callanan         ClearBreakpoints();
3059da3683cSJim Ingham         if (log && log->GetVerbose())
3069da3683cSJim Ingham             ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
3072c36439cSJim Ingham 
3089da3683cSJim Ingham     }
3099da3683cSJim Ingham     else
3109da3683cSJim Ingham     {
3119da3683cSJim Ingham         if (log)
312d01b2953SDaniel Malea             log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
31330fdc8d8SChris Lattner     }
31477787033SJim Ingham }
31530fdc8d8SChris Lattner 
31630fdc8d8SChris Lattner void
317bda4e5ebSJim Ingham ThreadPlanCallFunction::WillPop ()
318bda4e5ebSJim Ingham {
3190161b49cSJim Ingham     DoTakedown(PlanSucceeded());
320bda4e5ebSJim Ingham }
321bda4e5ebSJim Ingham 
322bda4e5ebSJim Ingham void
3232a48f525SGreg Clayton ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level)
32430fdc8d8SChris Lattner {
3252a48f525SGreg Clayton     if (level == eDescriptionLevelBrief)
32630fdc8d8SChris Lattner     {
32730fdc8d8SChris Lattner         s->Printf("Function call thread plan");
32830fdc8d8SChris Lattner     }
32930fdc8d8SChris Lattner     else
33030fdc8d8SChris Lattner     {
3311ac04c30SGreg Clayton         TargetSP target_sp (m_thread.CalculateTarget());
332d01b2953SDaniel Malea         s->Printf("Thread plan to call 0x%" PRIx64, m_function_addr.GetLoadAddress(target_sp.get()));
33330fdc8d8SChris Lattner     }
33430fdc8d8SChris Lattner }
33530fdc8d8SChris Lattner 
33630fdc8d8SChris Lattner bool
33730fdc8d8SChris Lattner ThreadPlanCallFunction::ValidatePlan (Stream *error)
33830fdc8d8SChris Lattner {
33930fdc8d8SChris Lattner     if (!m_valid)
340*ea06f3bfSJim Ingham     {
341*ea06f3bfSJim Ingham         if (error)
342*ea06f3bfSJim Ingham         {
343*ea06f3bfSJim Ingham             if (m_constructor_errors.GetSize() > 0)
344*ea06f3bfSJim Ingham                 error->PutCString (m_constructor_errors.GetData());
345*ea06f3bfSJim Ingham             else
346*ea06f3bfSJim Ingham                 error->PutCString ("Unknown error");
347*ea06f3bfSJim Ingham         }
34830fdc8d8SChris Lattner         return false;
349*ea06f3bfSJim Ingham     }
35030fdc8d8SChris Lattner 
35130fdc8d8SChris Lattner     return true;
35230fdc8d8SChris Lattner }
35330fdc8d8SChris Lattner 
3540161b49cSJim Ingham 
3550161b49cSJim Ingham Vote
3560161b49cSJim Ingham ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
35730fdc8d8SChris Lattner {
3580161b49cSJim Ingham     if (m_takedown_done || IsPlanComplete())
3590161b49cSJim Ingham         return eVoteYes;
3600161b49cSJim Ingham     else
3610161b49cSJim Ingham         return ThreadPlan::ShouldReportStop(event_ptr);
3620161b49cSJim Ingham }
3630161b49cSJim Ingham 
3640161b49cSJim Ingham bool
3650161b49cSJim Ingham ThreadPlanCallFunction::PlanExplainsStop (Event *event_ptr)
3660161b49cSJim Ingham {
3675160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
368160f78c5SJim Ingham     m_real_stop_info_sp = GetPrivateStopReason();
369160f78c5SJim Ingham 
37040d871faSJim Ingham     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
37140d871faSJim Ingham     // we answer yes.
3720161b49cSJim Ingham     if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr))
373184e9811SJim Ingham     {
374184e9811SJim Ingham         SetPlanComplete();
37540d871faSJim Ingham         return true;
376184e9811SJim Ingham     }
3773e6fedcaSSean Callanan 
378c98aca60SSean Callanan     // Check if the breakpoint is one of ours.
379c98aca60SSean Callanan 
38018de2fdcSJim Ingham     StopReason stop_reason;
38118de2fdcSJim Ingham     if (!m_real_stop_info_sp)
38218de2fdcSJim Ingham         stop_reason = eStopReasonNone;
38318de2fdcSJim Ingham     else
38418de2fdcSJim Ingham         stop_reason = m_real_stop_info_sp->GetStopReason();
3850161b49cSJim Ingham     if (log)
3860161b49cSJim Ingham         log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", Thread::StopReasonAsCString(stop_reason));
38718de2fdcSJim Ingham 
38818de2fdcSJim Ingham     if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
389c98aca60SSean Callanan         return true;
390c98aca60SSean Callanan 
3910161b49cSJim Ingham     // We control breakpoints separately from other "stop reasons."  So first,
3920161b49cSJim Ingham     // check the case where we stopped for an internal breakpoint, in that case, continue on.
3930161b49cSJim Ingham     // If it is not an internal breakpoint, consult m_ignore_breakpoints.
3946db73ca5SSean Callanan 
39518de2fdcSJim Ingham 
39618de2fdcSJim Ingham     if (stop_reason == eStopReasonBreakpoint)
39740d871faSJim Ingham     {
3981ac04c30SGreg Clayton         ProcessSP process_sp (m_thread.CalculateProcess());
399160f78c5SJim Ingham         uint64_t break_site_id = m_real_stop_info_sp->GetValue();
4001ac04c30SGreg Clayton         BreakpointSiteSP bp_site_sp;
4011ac04c30SGreg Clayton         if (process_sp)
4021ac04c30SGreg Clayton             bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id);
40340d871faSJim Ingham         if (bp_site_sp)
40440d871faSJim Ingham         {
40540d871faSJim Ingham             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
40640d871faSJim Ingham             bool is_internal = true;
40740d871faSJim Ingham             for (uint32_t i = 0; i < num_owners; i++)
40840d871faSJim Ingham             {
4096db73ca5SSean Callanan                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
4100161b49cSJim Ingham                 if (log)
4110161b49cSJim Ingham                     log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: hit breakpoint %d while calling function", bp.GetID());
4126db73ca5SSean Callanan 
4136db73ca5SSean Callanan                 if (!bp.IsInternal())
41440d871faSJim Ingham                 {
41540d871faSJim Ingham                     is_internal = false;
41640d871faSJim Ingham                     break;
41740d871faSJim Ingham                 }
41840d871faSJim Ingham             }
41940d871faSJim Ingham             if (is_internal)
4200161b49cSJim Ingham             {
4210161b49cSJim Ingham                 if (log)
4220161b49cSJim Ingham                     log->Printf ("ThreadPlanCallFunction::PlanExplainsStop hit an internal breakpoint, not stopping.");
42340d871faSJim Ingham                 return false;
42440d871faSJim Ingham             }
4250161b49cSJim Ingham         }
42640d871faSJim Ingham 
427184e9811SJim Ingham         if (m_ignore_breakpoints)
428923886ceSJim Ingham         {
4290161b49cSJim Ingham             if (log)
4300161b49cSJim Ingham                 log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
4310161b49cSJim Ingham             m_real_stop_info_sp->OverrideShouldStop(false);
432923886ceSJim Ingham             return true;
433923886ceSJim Ingham         }
434923886ceSJim Ingham         else
4350161b49cSJim Ingham         {
4360161b49cSJim Ingham             if (log)
4370161b49cSJim Ingham                 log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
4380161b49cSJim Ingham             m_real_stop_info_sp->OverrideShouldStop(true);
4390161b49cSJim Ingham             return false;
4400161b49cSJim Ingham         }
4410161b49cSJim Ingham     }
4420161b49cSJim Ingham     else if (!m_unwind_on_error)
4430161b49cSJim Ingham     {
4440161b49cSJim Ingham         // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
445923886ceSJim Ingham         return false;
44640d871faSJim Ingham     }
44740d871faSJim Ingham     else
44840d871faSJim Ingham     {
44940d871faSJim Ingham         // If the subplan is running, any crashes are attributable to us.
4502c36439cSJim Ingham         // If we want to discard the plan, then we say we explain the stop
4512c36439cSJim Ingham         // but if we are going to be discarded, let whoever is above us
4522c36439cSJim Ingham         // explain the stop.
4530161b49cSJim Ingham         // But don't discard the plan if the stop would restart itself (for instance if it is a
4540161b49cSJim Ingham         // signal that is set not to stop.  Check that here first.  We just say we explain the stop
4550161b49cSJim Ingham         // but aren't done and everything will continue on from there.
4560161b49cSJim Ingham 
4570161b49cSJim Ingham         if (m_real_stop_info_sp->ShouldStopSynchronous(event_ptr))
4580161b49cSJim Ingham         {
459184e9811SJim Ingham             SetPlanComplete(false);
4609a028519SSean Callanan             if (m_subplan_sp)
46118de2fdcSJim Ingham             {
462184e9811SJim Ingham                 if (m_unwind_on_error)
46318de2fdcSJim Ingham                     return true;
46418de2fdcSJim Ingham                 else
46518de2fdcSJim Ingham                     return false;
46618de2fdcSJim Ingham             }
46718de2fdcSJim Ingham             else
46818de2fdcSJim Ingham                 return false;
46930fdc8d8SChris Lattner         }
4700161b49cSJim Ingham         else
4710161b49cSJim Ingham             return true;
4720161b49cSJim Ingham     }
47340d871faSJim Ingham }
47430fdc8d8SChris Lattner 
47530fdc8d8SChris Lattner bool
47630fdc8d8SChris Lattner ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
47730fdc8d8SChris Lattner {
478184e9811SJim Ingham     // We do some computation in PlanExplainsStop that may or may not set the plan as complete.
479184e9811SJim Ingham     // We need to do that here to make sure our state is correct.
4800161b49cSJim Ingham     PlanExplainsStop(event_ptr);
481184e9811SJim Ingham 
482184e9811SJim Ingham     if (IsPlanComplete())
48330fdc8d8SChris Lattner     {
4849da3683cSJim Ingham         ReportRegisterState ("Function completed.  Register state was:");
48530fdc8d8SChris Lattner         return true;
48630fdc8d8SChris Lattner     }
48730fdc8d8SChris Lattner     else
48830fdc8d8SChris Lattner     {
48930fdc8d8SChris Lattner         return false;
49030fdc8d8SChris Lattner     }
49130fdc8d8SChris Lattner }
49230fdc8d8SChris Lattner 
49330fdc8d8SChris Lattner bool
49430fdc8d8SChris Lattner ThreadPlanCallFunction::StopOthers ()
49530fdc8d8SChris Lattner {
49630fdc8d8SChris Lattner     return m_stop_other_threads;
49730fdc8d8SChris Lattner }
49830fdc8d8SChris Lattner 
49930fdc8d8SChris Lattner void
50030fdc8d8SChris Lattner ThreadPlanCallFunction::SetStopOthers (bool new_value)
50130fdc8d8SChris Lattner {
50230fdc8d8SChris Lattner     if (m_subplan_sp)
50330fdc8d8SChris Lattner     {
50430fdc8d8SChris Lattner         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
50530fdc8d8SChris Lattner         address_plan->SetStopOthers(new_value);
50630fdc8d8SChris Lattner     }
50730fdc8d8SChris Lattner     m_stop_other_threads = new_value;
50830fdc8d8SChris Lattner }
50930fdc8d8SChris Lattner 
51030fdc8d8SChris Lattner StateType
51106e827ccSJim Ingham ThreadPlanCallFunction::GetPlanRunState ()
51230fdc8d8SChris Lattner {
51330fdc8d8SChris Lattner     return eStateRunning;
51430fdc8d8SChris Lattner }
51530fdc8d8SChris Lattner 
51630fdc8d8SChris Lattner void
51730fdc8d8SChris Lattner ThreadPlanCallFunction::DidPush ()
51830fdc8d8SChris Lattner {
519be3a1b14SSean Callanan //#define SINGLE_STEP_EXPRESSIONS
520be3a1b14SSean Callanan 
5218559a355SJim Ingham     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
5228559a355SJim Ingham     // Wait till the plan is pushed so we aren't changing the stop info till we're about to run.
5238559a355SJim Ingham 
5248559a355SJim Ingham     GetThread().SetStopInfoToNothing();
5258559a355SJim Ingham 
526be3a1b14SSean Callanan #ifndef SINGLE_STEP_EXPRESSIONS
52730fdc8d8SChris Lattner     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
52830fdc8d8SChris Lattner 
52930fdc8d8SChris Lattner     m_thread.QueueThreadPlan(m_subplan_sp, false);
53077787033SJim Ingham     m_subplan_sp->SetPrivate (true);
531be3a1b14SSean Callanan #endif
53230fdc8d8SChris Lattner }
53330fdc8d8SChris Lattner 
53430fdc8d8SChris Lattner bool
53530fdc8d8SChris Lattner ThreadPlanCallFunction::WillStop ()
53630fdc8d8SChris Lattner {
53730fdc8d8SChris Lattner     return true;
53830fdc8d8SChris Lattner }
53930fdc8d8SChris Lattner 
54030fdc8d8SChris Lattner bool
54130fdc8d8SChris Lattner ThreadPlanCallFunction::MischiefManaged ()
54230fdc8d8SChris Lattner {
5435160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
54430fdc8d8SChris Lattner 
545184e9811SJim Ingham     if (IsPlanComplete())
546184e9811SJim Ingham     {
54730fdc8d8SChris Lattner         if (log)
54887d0e618SJim Ingham             log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this);
54930fdc8d8SChris Lattner 
55030fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
55130fdc8d8SChris Lattner         return true;
55230fdc8d8SChris Lattner     }
55330fdc8d8SChris Lattner     else
55430fdc8d8SChris Lattner     {
55530fdc8d8SChris Lattner         return false;
55630fdc8d8SChris Lattner     }
55730fdc8d8SChris Lattner }
5586db73ca5SSean Callanan 
5596db73ca5SSean Callanan void
5606db73ca5SSean Callanan ThreadPlanCallFunction::SetBreakpoints ()
5616db73ca5SSean Callanan {
5621ac04c30SGreg Clayton     ProcessSP process_sp (m_thread.CalculateProcess());
5631ac04c30SGreg Clayton     if (process_sp)
5641ac04c30SGreg Clayton     {
5651ac04c30SGreg Clayton         m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
5661ac04c30SGreg Clayton         m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
5676db73ca5SSean Callanan 
568f211510fSSean Callanan         if (m_cxx_language_runtime)
569f211510fSSean Callanan             m_cxx_language_runtime->SetExceptionBreakpoints();
570f211510fSSean Callanan         if (m_objc_language_runtime)
571f211510fSSean Callanan             m_objc_language_runtime->SetExceptionBreakpoints();
5726db73ca5SSean Callanan     }
5731ac04c30SGreg Clayton }
5746db73ca5SSean Callanan 
5756db73ca5SSean Callanan void
5766db73ca5SSean Callanan ThreadPlanCallFunction::ClearBreakpoints ()
5776db73ca5SSean Callanan {
578f211510fSSean Callanan     if (m_cxx_language_runtime)
579f211510fSSean Callanan         m_cxx_language_runtime->ClearExceptionBreakpoints();
580f211510fSSean Callanan     if (m_objc_language_runtime)
581f211510fSSean Callanan         m_objc_language_runtime->ClearExceptionBreakpoints();
5826db73ca5SSean Callanan }
583c98aca60SSean Callanan 
584c98aca60SSean Callanan bool
585c98aca60SSean Callanan ThreadPlanCallFunction::BreakpointsExplainStop()
586c98aca60SSean Callanan {
5872a48f525SGreg Clayton     StopInfoSP stop_info_sp = GetPrivateStopReason();
588c98aca60SSean Callanan 
589184e9811SJim Ingham     if ((m_cxx_language_runtime &&
590f211510fSSean Callanan             m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
591184e9811SJim Ingham        ||(m_objc_language_runtime &&
592184e9811SJim Ingham             m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
593184e9811SJim Ingham     {
594184e9811SJim Ingham         SetPlanComplete(false);
595c98aca60SSean Callanan         return true;
596184e9811SJim Ingham     }
597f211510fSSean Callanan 
598c98aca60SSean Callanan     return false;
599c98aca60SSean Callanan }
6008559a355SJim Ingham 
6018559a355SJim Ingham bool
6028559a355SJim Ingham ThreadPlanCallFunction::RestoreThreadState()
6038559a355SJim Ingham {
6048559a355SJim Ingham     return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
6058559a355SJim Ingham }
6068559a355SJim Ingham 
607