blob: 4b3533a3446b4e242253ff12dfd3cf77b545fd60 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:241//===-- 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
26using namespace lldb;
27using namespace lldb_private;
28
29//----------------------------------------------------------------------
30// ThreadPlanCallFunction: Plan to call a single function
31//----------------------------------------------------------------------
32
33ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
34 Address &function,
35 lldb::addr_t arg,
36 bool stop_other_threads,
37 bool discard_on_error) :
38 ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
39 m_valid(false),
40 m_process(thread.GetProcess()),
41 m_arg_addr (arg),
42 m_args (NULL),
43 m_thread(thread),
44 m_stop_other_threads(stop_other_threads)
45{
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(&process);
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(&process);
76
77 if (!abi->PrepareTrivialCall(thread,
78 spBelowRedZone,
79 FunctionLoadAddr,
80 StartLoadAddr,
81 m_arg_addr))
82 return;
83
84 m_valid = true;
85}
86
87ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
88 Address &function,
89 ValueList &args,
90 bool stop_other_threads,
91 bool discard_on_error) :
92 ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
93 m_valid(false),
94 m_process(thread.GetProcess()),
95 m_arg_addr (0),
96 m_args (&args),
97 m_thread(thread),
98 m_stop_other_threads(stop_other_threads)
99{
100
101 SetOkayToDiscard (discard_on_error);
102
103 Process& process = thread.GetProcess();
104 Target& target = process.GetTarget();
105 const ABI *abi = process.GetABI();
106
107 if(!abi)
108 return;
109
110 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
111
112 SymbolContextList contexts;
113 SymbolContext context;
114 ModuleSP executableModuleSP (target.GetExecutableModule());
115
116 if (!executableModuleSP ||
117 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
118 return;
119
120 contexts.GetContextAtIndex(0, context);
121
122 m_start_addr = context.symbol->GetValue();
123 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process);
124
125 if(!thread.SaveFrameZeroState(m_register_backup))
126 return;
127
128 m_function_addr = function;
129 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process);
130
131 if (!abi->PrepareNormalCall(thread,
132 spBelowRedZone,
133 FunctionLoadAddr,
134 StartLoadAddr,
135 *m_args))
136 return;
137
138 m_valid = true;
139}
140
141ThreadPlanCallFunction::~ThreadPlanCallFunction ()
142{
143}
144
145void
146ThreadPlanCallFunction::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), 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), m_arg_addr);
158 }
159}
160
161bool
162ThreadPlanCallFunction::ValidatePlan (Stream *error)
163{
164 if (!m_valid)
165 return false;
166
167 return true;
168}
169
170bool
171ThreadPlanCallFunction::PlanExplainsStop ()
172{
173 if (!m_subplan_sp)
174 return false;
175 else
176 return m_subplan_sp->PlanExplainsStop();
177}
178
179bool
180ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
181{
182 if (PlanExplainsStop())
183 {
184 m_thread.RestoreSaveFrameZero(m_register_backup);
185 m_thread.ClearStackFrames();
186 SetPlanComplete();
187 return true;
188 }
189 else
190 {
191 return false;
192 }
193}
194
195bool
196ThreadPlanCallFunction::StopOthers ()
197{
198 return m_stop_other_threads;
199}
200
201void
202ThreadPlanCallFunction::SetStopOthers (bool new_value)
203{
204 if (m_subplan_sp)
205 {
206 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
207 address_plan->SetStopOthers(new_value);
208 }
209 m_stop_other_threads = new_value;
210}
211
212StateType
213ThreadPlanCallFunction::RunState ()
214{
215 return eStateRunning;
216}
217
218void
219ThreadPlanCallFunction::DidPush ()
220{
221 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
222
223 m_thread.QueueThreadPlan(m_subplan_sp, false);
224
225}
226
227bool
228ThreadPlanCallFunction::WillStop ()
229{
230 return true;
231}
232
233bool
234ThreadPlanCallFunction::MischiefManaged ()
235{
236 if (IsPlanComplete())
237 {
238 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
239
240 if (log)
241 log->Printf("Completed call function plan.");
242
243 ThreadPlan::MischiefManaged ();
244 return true;
245 }
246 else
247 {
248 return false;
249 }
250}