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 // Project includes
16 #include "lldb/lldb-private-log.h"
17 #include "lldb/Core/Address.h"
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Target/ThreadPlanRunToAddress.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // ThreadPlanCallFunction: Plan to call a single function
31 //----------------------------------------------------------------------
32 
33 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
34                                                 Address &function,
35                                                 lldb::addr_t arg,
36                                                 bool stop_other_threads,
37                                                 bool discard_on_error,
38                                                 lldb::addr_t *this_arg) :
39     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
40     m_valid (false),
41     m_stop_other_threads (stop_other_threads),
42     m_arg_addr (arg),
43     m_args (NULL),
44     m_process (thread.GetProcess()),
45     m_thread (thread)
46 {
47     SetOkayToDiscard (discard_on_error);
48 
49     Process& process = thread.GetProcess();
50     Target& target = process.GetTarget();
51     const ABI *abi = process.GetABI();
52 
53     if (!abi)
54         return;
55 
56     lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
57 
58     SymbolContextList contexts;
59     SymbolContext context;
60     ModuleSP executableModuleSP (target.GetExecutableModule());
61 
62     if (!executableModuleSP ||
63         !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
64         return;
65 
66     contexts.GetContextAtIndex(0, context);
67 
68     m_start_addr = context.symbol->GetValue();
69     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
70 
71     if (!thread.SaveFrameZeroState(m_register_backup))
72         return;
73 
74     m_function_addr = function;
75     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
76 
77     if (!abi->PrepareTrivialCall(thread,
78                                  spBelowRedZone,
79                                  FunctionLoadAddr,
80                                  StartLoadAddr,
81                                  m_arg_addr,
82                                  this_arg))
83         return;
84 
85     m_valid = true;
86 }
87 
88 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
89                                                 Address &function,
90                                                 ValueList &args,
91                                                 bool stop_other_threads,
92                                                 bool discard_on_error) :
93     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
94     m_valid (false),
95     m_stop_other_threads (stop_other_threads),
96     m_arg_addr (0),
97     m_args (&args),
98     m_process (thread.GetProcess()),
99     m_thread (thread)
100 {
101 
102     SetOkayToDiscard (discard_on_error);
103 
104     Process& process = thread.GetProcess();
105     Target& target = process.GetTarget();
106     const ABI *abi = process.GetABI();
107 
108     if(!abi)
109         return;
110 
111     lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
112 
113     SymbolContextList contexts;
114     SymbolContext context;
115     ModuleSP executableModuleSP (target.GetExecutableModule());
116 
117     if (!executableModuleSP ||
118         !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
119         return;
120 
121     contexts.GetContextAtIndex(0, context);
122 
123     m_start_addr = context.symbol->GetValue();
124     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
125 
126     if(!thread.SaveFrameZeroState(m_register_backup))
127         return;
128 
129     m_function_addr = function;
130     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
131 
132     if (!abi->PrepareNormalCall(thread,
133                                 spBelowRedZone,
134                                 FunctionLoadAddr,
135                                 StartLoadAddr,
136                                 *m_args))
137         return;
138 
139     m_valid = true;
140 }
141 
142 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
143 {
144 }
145 
146 void
147 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
148 {
149     if (level == lldb::eDescriptionLevelBrief)
150     {
151         s->Printf("Function call thread plan");
152     }
153     else
154     {
155         if (m_args)
156             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
157         else
158             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
159     }
160 }
161 
162 bool
163 ThreadPlanCallFunction::ValidatePlan (Stream *error)
164 {
165     if (!m_valid)
166         return false;
167 
168     return true;
169 }
170 
171 bool
172 ThreadPlanCallFunction::PlanExplainsStop ()
173 {
174     // If the subplan is running, any crashes are attributable to us.
175 
176     return (m_subplan_sp.get() != NULL);
177 }
178 
179 bool
180 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
181 {
182     if (PlanExplainsStop())
183     {
184         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
185 
186         if (log)
187         {
188             RegisterContext *reg_ctx = m_thread.GetRegisterContext();
189 
190             log->PutCString("Function completed.  Register state was:");
191 
192             for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
193                  register_index < num_registers;
194                  ++register_index)
195             {
196                 const char *register_name = reg_ctx->GetRegisterName(register_index);
197                 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
198 
199                 log->Printf("  %s = 0x%llx", register_name, register_value);
200             }
201         }
202 
203         m_thread.RestoreSaveFrameZero(m_register_backup);
204         m_thread.ClearStackFrames();
205         SetPlanComplete();
206         return true;
207     }
208     else
209     {
210         return false;
211     }
212 }
213 
214 bool
215 ThreadPlanCallFunction::StopOthers ()
216 {
217     return m_stop_other_threads;
218 }
219 
220 void
221 ThreadPlanCallFunction::SetStopOthers (bool new_value)
222 {
223     if (m_subplan_sp)
224     {
225         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
226         address_plan->SetStopOthers(new_value);
227     }
228     m_stop_other_threads = new_value;
229 }
230 
231 StateType
232 ThreadPlanCallFunction::RunState ()
233 {
234     return eStateRunning;
235 }
236 
237 void
238 ThreadPlanCallFunction::DidPush ()
239 {
240     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
241 
242     m_thread.QueueThreadPlan(m_subplan_sp, false);
243 
244 }
245 
246 bool
247 ThreadPlanCallFunction::WillStop ()
248 {
249     return true;
250 }
251 
252 bool
253 ThreadPlanCallFunction::MischiefManaged ()
254 {
255     if (IsPlanComplete())
256     {
257         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
258 
259         if (log)
260             log->Printf("Completed call function plan.");
261 
262         ThreadPlan::MischiefManaged ();
263         return true;
264     }
265     else
266     {
267         return false;
268     }
269 }
270