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     if (!m_subplan_sp)
179         return false;
180     else
181         return m_subplan_sp->PlanExplainsStop();
182 }
183 
184 bool
185 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
186 {
187     if (PlanExplainsStop())
188     {
189         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
190 
191         if (log)
192         {
193             RegisterContext *reg_ctx = m_thread.GetRegisterContext();
194 
195             log->PutCString("Function completed.  Register state was:");
196 
197             for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
198                  register_index < num_registers;
199                  ++register_index)
200             {
201                 const char *register_name = reg_ctx->GetRegisterName(register_index);
202                 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
203 
204                 log->Printf("  %s = 0x%llx", register_name, register_value);
205             }
206         }
207 
208         m_thread.RestoreSaveFrameZero(m_register_backup);
209         m_thread.ClearStackFrames();
210         SetPlanComplete();
211         return true;
212     }
213     else
214     {
215         return false;
216     }
217 }
218 
219 bool
220 ThreadPlanCallFunction::StopOthers ()
221 {
222     return m_stop_other_threads;
223 }
224 
225 void
226 ThreadPlanCallFunction::SetStopOthers (bool new_value)
227 {
228     if (m_subplan_sp)
229     {
230         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
231         address_plan->SetStopOthers(new_value);
232     }
233     m_stop_other_threads = new_value;
234 }
235 
236 StateType
237 ThreadPlanCallFunction::RunState ()
238 {
239     return eStateRunning;
240 }
241 
242 void
243 ThreadPlanCallFunction::DidPush ()
244 {
245     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
246 
247     m_thread.QueueThreadPlan(m_subplan_sp, false);
248 
249 }
250 
251 bool
252 ThreadPlanCallFunction::WillStop ()
253 {
254     return true;
255 }
256 
257 bool
258 ThreadPlanCallFunction::MischiefManaged ()
259 {
260     if (IsPlanComplete())
261     {
262         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
263 
264         if (log)
265             log->Printf("Completed call function plan.");
266 
267         ThreadPlan::MischiefManaged ();
268         return true;
269     }
270     else
271     {
272         return false;
273     }
274 }
275