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"
2230fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
23f211510fSSean Callanan #include "lldb/Target/LanguageRuntime.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2530fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
2640d871faSJim Ingham #include "lldb/Target/StopInfo.h"
2730fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2830fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2930fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h"
3030fdc8d8SChris Lattner 
3130fdc8d8SChris Lattner using namespace lldb;
3230fdc8d8SChris Lattner using namespace lldb_private;
3330fdc8d8SChris Lattner 
3430fdc8d8SChris Lattner //----------------------------------------------------------------------
3530fdc8d8SChris Lattner // ThreadPlanCallFunction: Plan to call a single function
3630fdc8d8SChris Lattner //----------------------------------------------------------------------
3730fdc8d8SChris Lattner 
3830fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
3930fdc8d8SChris Lattner                                                 Address &function,
4030fdc8d8SChris Lattner                                                 lldb::addr_t arg,
4130fdc8d8SChris Lattner                                                 bool stop_other_threads,
42fc55f5d1SSean Callanan                                                 bool discard_on_error,
4317827830SSean Callanan                                                 lldb::addr_t *this_arg,
4417827830SSean Callanan                                                 lldb::addr_t *cmd_arg) :
45b01e742aSJim Ingham     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
4630fdc8d8SChris Lattner     m_valid (false),
471ee0d4f7SBenjamin Kramer     m_stop_other_threads (stop_other_threads),
4830fdc8d8SChris Lattner     m_arg_addr (arg),
4930fdc8d8SChris Lattner     m_args (NULL),
501ee0d4f7SBenjamin Kramer     m_process (thread.GetProcess()),
519da3683cSJim Ingham     m_thread (thread),
52*e359d9b7SSean Callanan     m_takedown_done (false),
53*e359d9b7SSean Callanan     m_function_sp(NULL)
5430fdc8d8SChris Lattner {
5530fdc8d8SChris Lattner     SetOkayToDiscard (discard_on_error);
5630fdc8d8SChris Lattner 
5730fdc8d8SChris Lattner     Process& process = thread.GetProcess();
5830fdc8d8SChris Lattner     Target& target = process.GetTarget();
5930fdc8d8SChris Lattner     const ABI *abi = process.GetABI();
6030fdc8d8SChris Lattner 
6130fdc8d8SChris Lattner     if (!abi)
6230fdc8d8SChris Lattner         return;
6330fdc8d8SChris Lattner 
6477787033SJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
6577787033SJim Ingham 
666db73ca5SSean Callanan     SetBreakpoints();
676db73ca5SSean Callanan 
68*e359d9b7SSean Callanan     m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
6930fdc8d8SChris Lattner 
7030fdc8d8SChris Lattner     ModuleSP executableModuleSP (target.GetExecutableModule());
7130fdc8d8SChris Lattner 
72672e6f59SJim Ingham     if (!executableModuleSP)
73672e6f59SJim Ingham     {
74672e6f59SJim Ingham         log->Printf ("Can't execute code without an executable module.");
7530fdc8d8SChris Lattner         return;
76672e6f59SJim Ingham     }
77672e6f59SJim Ingham     else
78672e6f59SJim Ingham     {
79672e6f59SJim Ingham         ObjectFile *objectFile = executableModuleSP->GetObjectFile();
80672e6f59SJim Ingham         if (!objectFile)
81672e6f59SJim Ingham         {
82672e6f59SJim Ingham             log->Printf ("Could not find object file for module \"%s\".",
83672e6f59SJim Ingham                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
84672e6f59SJim Ingham             return;
85672e6f59SJim Ingham         }
86672e6f59SJim Ingham         m_start_addr = objectFile->GetEntryPointAddress();
87672e6f59SJim Ingham         if (!m_start_addr.IsValid())
88672e6f59SJim Ingham         {
89672e6f59SJim Ingham             log->Printf ("Could not find entry point address for executable module \"%s\".",
90672e6f59SJim Ingham                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
91672e6f59SJim Ingham             return;
92672e6f59SJim Ingham         }
93672e6f59SJim Ingham     }
9430fdc8d8SChris Lattner 
95f5e56de0SGreg Clayton     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
9630fdc8d8SChris Lattner 
9777787033SJim Ingham     // Checkpoint the thread state so we can restore it later.
989da3683cSJim Ingham     if (log && log->GetVerbose())
999da3683cSJim Ingham         ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
1009da3683cSJim Ingham 
10177787033SJim Ingham     if (!thread.CheckpointThreadState (m_stored_thread_state))
10277787033SJim Ingham     {
10377787033SJim Ingham         if (log)
10477787033SJim Ingham             log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
10530fdc8d8SChris Lattner         return;
10677787033SJim Ingham     }
10777787033SJim Ingham     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
10877787033SJim Ingham     thread.SetStopInfoToNothing();
10930fdc8d8SChris Lattner 
11030fdc8d8SChris Lattner     m_function_addr = function;
111f5e56de0SGreg Clayton     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
11230fdc8d8SChris Lattner 
11330fdc8d8SChris Lattner     if (!abi->PrepareTrivialCall(thread,
114*e359d9b7SSean Callanan                                  m_function_sp,
11530fdc8d8SChris Lattner                                  FunctionLoadAddr,
11630fdc8d8SChris Lattner                                  StartLoadAddr,
117fc55f5d1SSean Callanan                                  m_arg_addr,
11817827830SSean Callanan                                  this_arg,
11917827830SSean Callanan                                  cmd_arg))
12030fdc8d8SChris Lattner         return;
12130fdc8d8SChris Lattner 
1229da3683cSJim Ingham     ReportRegisterState ("Function call was set up.  Register state was:");
1239da3683cSJim Ingham 
1249da3683cSJim Ingham     m_valid = true;
1259da3683cSJim Ingham }
1269da3683cSJim Ingham 
1279da3683cSJim Ingham ThreadPlanCallFunction::~ThreadPlanCallFunction ()
1289da3683cSJim Ingham {
1299da3683cSJim Ingham }
1309da3683cSJim Ingham 
1319da3683cSJim Ingham void
1329da3683cSJim Ingham ThreadPlanCallFunction::ReportRegisterState (const char *message)
1339da3683cSJim Ingham {
1349da3683cSJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
135ece96492SSean Callanan     if (log)
136ece96492SSean Callanan     {
1375ccbd294SGreg Clayton         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
138ece96492SSean Callanan 
1399da3683cSJim Ingham         log->PutCString(message);
140ece96492SSean Callanan 
141ece96492SSean Callanan         for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
142ece96492SSean Callanan              register_index < num_registers;
143ece96492SSean Callanan              ++register_index)
144ece96492SSean Callanan         {
145ece96492SSean Callanan             const char *register_name = reg_ctx->GetRegisterName(register_index);
146ece96492SSean Callanan             uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
147ece96492SSean Callanan 
148ece96492SSean Callanan             log->Printf("  %s = 0x%llx", register_name, register_value);
149ece96492SSean Callanan         }
150ece96492SSean Callanan     }
15110af7c43SSean Callanan }
15210af7c43SSean Callanan 
15310af7c43SSean Callanan void
15410af7c43SSean Callanan ThreadPlanCallFunction::DoTakedown ()
15510af7c43SSean Callanan {
1569da3683cSJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1579da3683cSJim Ingham     if (!m_takedown_done)
15877787033SJim Ingham     {
1599da3683cSJim Ingham         if (log)
1609da3683cSJim Ingham             log->Printf ("DoTakedown called for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
1619da3683cSJim Ingham         m_takedown_done = true;
16277787033SJim Ingham         m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
16310af7c43SSean Callanan         SetPlanComplete();
16410af7c43SSean Callanan         ClearBreakpoints();
1659da3683cSJim Ingham         if (log && log->GetVerbose())
1669da3683cSJim Ingham             ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
1672c36439cSJim Ingham 
1689da3683cSJim Ingham     }
1699da3683cSJim Ingham     else
1709da3683cSJim Ingham     {
1719da3683cSJim Ingham         if (log)
1729da3683cSJim Ingham             log->Printf ("DoTakedown called as no-op for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
17330fdc8d8SChris Lattner     }
17477787033SJim Ingham }
17530fdc8d8SChris Lattner 
17630fdc8d8SChris Lattner void
177bda4e5ebSJim Ingham ThreadPlanCallFunction::WillPop ()
178bda4e5ebSJim Ingham {
179bda4e5ebSJim Ingham     DoTakedown();
180bda4e5ebSJim Ingham }
181bda4e5ebSJim Ingham 
182bda4e5ebSJim Ingham void
18330fdc8d8SChris Lattner ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
18430fdc8d8SChris Lattner {
18530fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
18630fdc8d8SChris Lattner     {
18730fdc8d8SChris Lattner         s->Printf("Function call thread plan");
18830fdc8d8SChris Lattner     }
18930fdc8d8SChris Lattner     else
19030fdc8d8SChris Lattner     {
19130fdc8d8SChris Lattner         if (m_args)
192f5e56de0SGreg Clayton             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
19330fdc8d8SChris Lattner         else
194f5e56de0SGreg Clayton             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
19530fdc8d8SChris Lattner     }
19630fdc8d8SChris Lattner }
19730fdc8d8SChris Lattner 
19830fdc8d8SChris Lattner bool
19930fdc8d8SChris Lattner ThreadPlanCallFunction::ValidatePlan (Stream *error)
20030fdc8d8SChris Lattner {
20130fdc8d8SChris Lattner     if (!m_valid)
20230fdc8d8SChris Lattner         return false;
20330fdc8d8SChris Lattner 
20430fdc8d8SChris Lattner     return true;
20530fdc8d8SChris Lattner }
20630fdc8d8SChris Lattner 
20730fdc8d8SChris Lattner bool
20830fdc8d8SChris Lattner ThreadPlanCallFunction::PlanExplainsStop ()
20930fdc8d8SChris Lattner {
21040d871faSJim Ingham     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
21140d871faSJim Ingham     // we answer yes.
21240d871faSJim Ingham     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
21340d871faSJim Ingham         return true;
2143e6fedcaSSean Callanan 
215c98aca60SSean Callanan     // Check if the breakpoint is one of ours.
216c98aca60SSean Callanan 
217c98aca60SSean Callanan     if (BreakpointsExplainStop())
218c98aca60SSean Callanan         return true;
219c98aca60SSean Callanan 
22040d871faSJim Ingham     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
22140d871faSJim Ingham     if (!OkayToDiscard())
22240d871faSJim Ingham         return false;
22340d871faSJim Ingham 
22440d871faSJim Ingham     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
22540d871faSJim Ingham     // If it is not an internal breakpoint, consult OkayToDiscard.
22640d871faSJim Ingham     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
2276db73ca5SSean Callanan 
22840d871faSJim Ingham     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
22940d871faSJim Ingham     {
23040d871faSJim Ingham         uint64_t break_site_id = stop_info_sp->GetValue();
23140d871faSJim Ingham         lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
23240d871faSJim Ingham         if (bp_site_sp)
23340d871faSJim Ingham         {
23440d871faSJim Ingham             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
23540d871faSJim Ingham             bool is_internal = true;
23640d871faSJim Ingham             for (uint32_t i = 0; i < num_owners; i++)
23740d871faSJim Ingham             {
2386db73ca5SSean Callanan                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
2396db73ca5SSean Callanan 
2406db73ca5SSean Callanan                 if (!bp.IsInternal())
24140d871faSJim Ingham                 {
24240d871faSJim Ingham                     is_internal = false;
24340d871faSJim Ingham                     break;
24440d871faSJim Ingham                 }
24540d871faSJim Ingham             }
24640d871faSJim Ingham             if (is_internal)
24740d871faSJim Ingham                 return false;
24840d871faSJim Ingham         }
24940d871faSJim Ingham 
25040d871faSJim Ingham         return OkayToDiscard();
25140d871faSJim Ingham     }
25240d871faSJim Ingham     else
25340d871faSJim Ingham     {
25440d871faSJim Ingham         // If the subplan is running, any crashes are attributable to us.
2552c36439cSJim Ingham         // If we want to discard the plan, then we say we explain the stop
2562c36439cSJim Ingham         // but if we are going to be discarded, let whoever is above us
2572c36439cSJim Ingham         // explain the stop.
2582c36439cSJim Ingham         return ((m_subplan_sp.get() != NULL) && !OkayToDiscard());
25930fdc8d8SChris Lattner     }
26040d871faSJim Ingham }
26130fdc8d8SChris Lattner 
26230fdc8d8SChris Lattner bool
26330fdc8d8SChris Lattner ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
26430fdc8d8SChris Lattner {
26530fdc8d8SChris Lattner     if (PlanExplainsStop())
26630fdc8d8SChris Lattner     {
2679da3683cSJim Ingham         ReportRegisterState ("Function completed.  Register state was:");
2685300d37aSSean Callanan 
26910af7c43SSean Callanan         DoTakedown();
2706db73ca5SSean Callanan 
27130fdc8d8SChris Lattner         return true;
27230fdc8d8SChris Lattner     }
27330fdc8d8SChris Lattner     else
27430fdc8d8SChris Lattner     {
27530fdc8d8SChris Lattner         return false;
27630fdc8d8SChris Lattner     }
27730fdc8d8SChris Lattner }
27830fdc8d8SChris Lattner 
27930fdc8d8SChris Lattner bool
28030fdc8d8SChris Lattner ThreadPlanCallFunction::StopOthers ()
28130fdc8d8SChris Lattner {
28230fdc8d8SChris Lattner     return m_stop_other_threads;
28330fdc8d8SChris Lattner }
28430fdc8d8SChris Lattner 
28530fdc8d8SChris Lattner void
28630fdc8d8SChris Lattner ThreadPlanCallFunction::SetStopOthers (bool new_value)
28730fdc8d8SChris Lattner {
28830fdc8d8SChris Lattner     if (m_subplan_sp)
28930fdc8d8SChris Lattner     {
29030fdc8d8SChris Lattner         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
29130fdc8d8SChris Lattner         address_plan->SetStopOthers(new_value);
29230fdc8d8SChris Lattner     }
29330fdc8d8SChris Lattner     m_stop_other_threads = new_value;
29430fdc8d8SChris Lattner }
29530fdc8d8SChris Lattner 
29630fdc8d8SChris Lattner StateType
29706e827ccSJim Ingham ThreadPlanCallFunction::GetPlanRunState ()
29830fdc8d8SChris Lattner {
29930fdc8d8SChris Lattner     return eStateRunning;
30030fdc8d8SChris Lattner }
30130fdc8d8SChris Lattner 
30230fdc8d8SChris Lattner void
30330fdc8d8SChris Lattner ThreadPlanCallFunction::DidPush ()
30430fdc8d8SChris Lattner {
305be3a1b14SSean Callanan //#define SINGLE_STEP_EXPRESSIONS
306be3a1b14SSean Callanan 
307be3a1b14SSean Callanan #ifndef SINGLE_STEP_EXPRESSIONS
30830fdc8d8SChris Lattner     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
30930fdc8d8SChris Lattner 
31030fdc8d8SChris Lattner     m_thread.QueueThreadPlan(m_subplan_sp, false);
31177787033SJim Ingham     m_subplan_sp->SetPrivate (true);
312be3a1b14SSean Callanan #endif
31330fdc8d8SChris Lattner }
31430fdc8d8SChris Lattner 
31530fdc8d8SChris Lattner bool
31630fdc8d8SChris Lattner ThreadPlanCallFunction::WillStop ()
31730fdc8d8SChris Lattner {
31830fdc8d8SChris Lattner     return true;
31930fdc8d8SChris Lattner }
32030fdc8d8SChris Lattner 
32130fdc8d8SChris Lattner bool
32230fdc8d8SChris Lattner ThreadPlanCallFunction::MischiefManaged ()
32330fdc8d8SChris Lattner {
32430fdc8d8SChris Lattner     if (IsPlanComplete())
32530fdc8d8SChris Lattner     {
3262d4edfbcSGreg Clayton         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
32730fdc8d8SChris Lattner 
32830fdc8d8SChris Lattner         if (log)
32930fdc8d8SChris Lattner             log->Printf("Completed call function plan.");
33030fdc8d8SChris Lattner 
33130fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
33230fdc8d8SChris Lattner         return true;
33330fdc8d8SChris Lattner     }
33430fdc8d8SChris Lattner     else
33530fdc8d8SChris Lattner     {
33630fdc8d8SChris Lattner         return false;
33730fdc8d8SChris Lattner     }
33830fdc8d8SChris Lattner }
3396db73ca5SSean Callanan 
3406db73ca5SSean Callanan void
3416db73ca5SSean Callanan ThreadPlanCallFunction::SetBreakpoints ()
3426db73ca5SSean Callanan {
343f211510fSSean Callanan     m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
344f211510fSSean Callanan     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
3456db73ca5SSean Callanan 
346f211510fSSean Callanan     if (m_cxx_language_runtime)
347f211510fSSean Callanan         m_cxx_language_runtime->SetExceptionBreakpoints();
348f211510fSSean Callanan     if (m_objc_language_runtime)
349f211510fSSean Callanan         m_objc_language_runtime->SetExceptionBreakpoints();
3506db73ca5SSean Callanan }
3516db73ca5SSean Callanan 
3526db73ca5SSean Callanan void
3536db73ca5SSean Callanan ThreadPlanCallFunction::ClearBreakpoints ()
3546db73ca5SSean Callanan {
355f211510fSSean Callanan     if (m_cxx_language_runtime)
356f211510fSSean Callanan         m_cxx_language_runtime->ClearExceptionBreakpoints();
357f211510fSSean Callanan     if (m_objc_language_runtime)
358f211510fSSean Callanan         m_objc_language_runtime->ClearExceptionBreakpoints();
3596db73ca5SSean Callanan }
360c98aca60SSean Callanan 
361c98aca60SSean Callanan bool
362c98aca60SSean Callanan ThreadPlanCallFunction::BreakpointsExplainStop()
363c98aca60SSean Callanan {
364c98aca60SSean Callanan     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
365c98aca60SSean Callanan 
366f211510fSSean Callanan     if (m_cxx_language_runtime &&
367f211510fSSean Callanan         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
368c98aca60SSean Callanan         return true;
369f211510fSSean Callanan 
370f211510fSSean Callanan     if (m_objc_language_runtime &&
371f211510fSSean Callanan         m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
372f211510fSSean Callanan         return true;
373c98aca60SSean Callanan 
374c98aca60SSean Callanan     return false;
375c98aca60SSean Callanan }
376