1 //===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/ThreadPlanCallFunction.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "llvm/Support/MachO.h"
16 // Project includes
17 #include "lldb/lldb-private-log.h"
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Core/Address.h"
21 #include "lldb/Core/Log.h"
22 #include "lldb/Core/Stream.h"
23 #include "lldb/Target/LanguageRuntime.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StopInfo.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Thread.h"
29 #include "lldb/Target/ThreadPlanRunToAddress.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 //----------------------------------------------------------------------
35 // ThreadPlanCallFunction: Plan to call a single function
36 //----------------------------------------------------------------------
37 
38 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
39                                                 Address &function,
40                                                 lldb::addr_t arg,
41                                                 bool stop_other_threads,
42                                                 bool discard_on_error,
43                                                 lldb::addr_t *this_arg,
44                                                 lldb::addr_t *cmd_arg) :
45     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
46     m_valid (false),
47     m_stop_other_threads (stop_other_threads),
48     m_arg_addr (arg),
49     m_args (NULL),
50     m_process (thread.GetProcess()),
51     m_thread (thread)
52 {
53     SetOkayToDiscard (discard_on_error);
54 
55     Process& process = thread.GetProcess();
56     Target& target = process.GetTarget();
57     const ABI *abi = process.GetABI();
58 
59     if (!abi)
60         return;
61 
62     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
63 
64     SetBreakpoints();
65 
66     lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
67 
68     SymbolContextList contexts;
69     SymbolContext context;
70     ModuleSP executableModuleSP (target.GetExecutableModule());
71 
72     if (!executableModuleSP ||
73         !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
74         return;
75 
76     contexts.GetContextAtIndex(0, context);
77 
78     m_start_addr = context.symbol->GetValue();
79     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
80 
81     // Checkpoint the thread state so we can restore it later.
82     if (!thread.CheckpointThreadState (m_stored_thread_state))
83     {
84         if (log)
85             log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
86         return;
87     }
88     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
89     thread.SetStopInfoToNothing();
90 
91     m_function_addr = function;
92     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
93 
94     if (!abi->PrepareTrivialCall(thread,
95                                  spBelowRedZone,
96                                  FunctionLoadAddr,
97                                  StartLoadAddr,
98                                  m_arg_addr,
99                                  this_arg,
100                                  cmd_arg))
101         return;
102 
103     if (log)
104     {
105         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
106 
107         log->PutCString("Function call was set up.  Register state was:");
108 
109         for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
110              register_index < num_registers;
111              ++register_index)
112         {
113             const char *register_name = reg_ctx->GetRegisterName(register_index);
114             uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
115 
116             log->Printf("  %s = 0x%llx", register_name, register_value);
117         }
118     }
119 
120     m_valid = true;
121 }
122 
123 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
124 {
125         DoTakedown();
126 }
127 
128 void
129 ThreadPlanCallFunction::DoTakedown ()
130 {
131     if (m_valid && !IsPlanComplete())
132     {
133         m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
134         SetPlanComplete();
135         ClearBreakpoints();
136     }
137 }
138 
139 void
140 ThreadPlanCallFunction::WillPop ()
141 {
142     DoTakedown();
143 }
144 
145 void
146 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
147 {
148     if (level == lldb::eDescriptionLevelBrief)
149     {
150         s->Printf("Function call thread plan");
151     }
152     else
153     {
154         if (m_args)
155             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
156         else
157             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
158     }
159 }
160 
161 bool
162 ThreadPlanCallFunction::ValidatePlan (Stream *error)
163 {
164     if (!m_valid)
165         return false;
166 
167     return true;
168 }
169 
170 bool
171 ThreadPlanCallFunction::PlanExplainsStop ()
172 {
173     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
174     // we answer yes.
175     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
176         return true;
177 
178     // Check if the breakpoint is one of ours.
179 
180     if (BreakpointsExplainStop())
181         return true;
182 
183     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
184     if (!OkayToDiscard())
185         return false;
186 
187     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
188     // If it is not an internal breakpoint, consult OkayToDiscard.
189     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
190 
191     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
192     {
193         uint64_t break_site_id = stop_info_sp->GetValue();
194         lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
195         if (bp_site_sp)
196         {
197             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
198             bool is_internal = true;
199             for (uint32_t i = 0; i < num_owners; i++)
200             {
201                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
202 
203                 if (!bp.IsInternal())
204                 {
205                     is_internal = false;
206                     break;
207                 }
208             }
209             if (is_internal)
210                 return false;
211         }
212 
213         return OkayToDiscard();
214     }
215     else
216     {
217         // If the subplan is running, any crashes are attributable to us.
218         return (m_subplan_sp.get() != NULL);
219     }
220 }
221 
222 bool
223 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
224 {
225     if (PlanExplainsStop())
226     {
227         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
228 
229         if (log)
230         {
231             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
232 
233             log->PutCString("Function completed.  Register state was:");
234 
235             for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
236                  register_index < num_registers;
237                  ++register_index)
238             {
239                 const char *register_name = reg_ctx->GetRegisterName(register_index);
240                 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
241 
242                 log->Printf("  %s = 0x%llx", register_name, register_value);
243             }
244         }
245 
246         DoTakedown();
247 
248         return true;
249     }
250     else
251     {
252         return false;
253     }
254 }
255 
256 bool
257 ThreadPlanCallFunction::StopOthers ()
258 {
259     return m_stop_other_threads;
260 }
261 
262 void
263 ThreadPlanCallFunction::SetStopOthers (bool new_value)
264 {
265     if (m_subplan_sp)
266     {
267         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
268         address_plan->SetStopOthers(new_value);
269     }
270     m_stop_other_threads = new_value;
271 }
272 
273 StateType
274 ThreadPlanCallFunction::GetPlanRunState ()
275 {
276     return eStateRunning;
277 }
278 
279 void
280 ThreadPlanCallFunction::DidPush ()
281 {
282 //#define SINGLE_STEP_EXPRESSIONS
283 
284 #ifndef SINGLE_STEP_EXPRESSIONS
285     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
286 
287     m_thread.QueueThreadPlan(m_subplan_sp, false);
288     m_subplan_sp->SetPrivate (true);
289 #endif
290 }
291 
292 bool
293 ThreadPlanCallFunction::WillStop ()
294 {
295     return true;
296 }
297 
298 bool
299 ThreadPlanCallFunction::MischiefManaged ()
300 {
301     if (IsPlanComplete())
302     {
303         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
304 
305         if (log)
306             log->Printf("Completed call function plan.");
307 
308         ThreadPlan::MischiefManaged ();
309         return true;
310     }
311     else
312     {
313         return false;
314     }
315 }
316 
317 void
318 ThreadPlanCallFunction::SetBreakpoints ()
319 {
320     m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
321     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
322 
323     if (m_cxx_language_runtime)
324         m_cxx_language_runtime->SetExceptionBreakpoints();
325     if (m_objc_language_runtime)
326         m_objc_language_runtime->SetExceptionBreakpoints();
327 }
328 
329 void
330 ThreadPlanCallFunction::ClearBreakpoints ()
331 {
332     if (m_cxx_language_runtime)
333         m_cxx_language_runtime->ClearExceptionBreakpoints();
334     if (m_objc_language_runtime)
335         m_objc_language_runtime->ClearExceptionBreakpoints();
336 }
337 
338 bool
339 ThreadPlanCallFunction::BreakpointsExplainStop()
340 {
341     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
342 
343     if (m_cxx_language_runtime &&
344         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
345         return true;
346 
347     if (m_objc_language_runtime &&
348         m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
349         return true;
350 
351     return false;
352 }
353