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