blob: 3935a1340ec6e934ed4e081cdc21c2045a118e4d [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,
Sean Callananfc55f5d2010-09-21 00:44:1237 bool discard_on_error,
38 lldb::addr_t *this_arg) :
Jim Inghamb01e742a2010-06-19 04:45:3239 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3340 m_valid (false),
41 m_stop_other_threads (stop_other_threads),
Chris Lattner30fdc8d2010-06-08 16:52:2442 m_arg_addr (arg),
43 m_args (NULL),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3344 m_process (thread.GetProcess()),
45 m_thread (thread)
Chris Lattner30fdc8d2010-06-08 16:52:2446{
Chris Lattner30fdc8d2010-06-08 16:52:2447 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();
Greg Claytonf5e56de2010-09-14 23:36:4069 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:2470
71 if (!thread.SaveFrameZeroState(m_register_backup))
72 return;
73
74 m_function_addr = function;
Greg Claytonf5e56de2010-09-14 23:36:4075 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:2476
77 if (!abi->PrepareTrivialCall(thread,
78 spBelowRedZone,
79 FunctionLoadAddr,
80 StartLoadAddr,
Sean Callananfc55f5d2010-09-21 00:44:1281 m_arg_addr,
82 this_arg))
Chris Lattner30fdc8d2010-06-08 16:52:2483 return;
84
85 m_valid = true;
86}
87
88ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
89 Address &function,
90 ValueList &args,
91 bool stop_other_threads,
92 bool discard_on_error) :
Jim Inghamb01e742a2010-06-19 04:45:3293 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3394 m_valid (false),
95 m_stop_other_threads (stop_other_threads),
Chris Lattner30fdc8d2010-06-08 16:52:2496 m_arg_addr (0),
97 m_args (&args),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3398 m_process (thread.GetProcess()),
99 m_thread (thread)
Chris Lattner30fdc8d2010-06-08 16:52:24100{
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();
Greg Claytonf5e56de2010-09-14 23:36:40124 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:24125
126 if(!thread.SaveFrameZeroState(m_register_backup))
127 return;
128
129 m_function_addr = function;
Greg Claytonf5e56de2010-09-14 23:36:40130 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:24131
132 if (!abi->PrepareNormalCall(thread,
133 spBelowRedZone,
134 FunctionLoadAddr,
135 StartLoadAddr,
136 *m_args))
137 return;
138
139 m_valid = true;
140}
141
142ThreadPlanCallFunction::~ThreadPlanCallFunction ()
143{
144}
145
146void
147ThreadPlanCallFunction::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)
Greg Claytonf5e56de2010-09-14 23:36:40156 s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24157 else
Greg Claytonf5e56de2010-09-14 23:36:40158 s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24159 }
160}
161
162bool
163ThreadPlanCallFunction::ValidatePlan (Stream *error)
164{
165 if (!m_valid)
166 return false;
167
168 return true;
169}
170
171bool
172ThreadPlanCallFunction::PlanExplainsStop ()
173{
174 if (!m_subplan_sp)
175 return false;
176 else
177 return m_subplan_sp->PlanExplainsStop();
178}
179
180bool
181ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
182{
183 if (PlanExplainsStop())
184 {
Sean Callanan5300d372010-07-31 01:32:05185 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
186
187 if (log)
188 {
189 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
190
191 log->PutCString("Function completed. Register state was:");
192
193 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
194 register_index < num_registers;
195 ++register_index)
196 {
197 const char *register_name = reg_ctx->GetRegisterName(register_index);
198 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
199
200 log->Printf(" %s = 0x%llx", register_name, register_value);
201 }
202 }
203
Chris Lattner30fdc8d2010-06-08 16:52:24204 m_thread.RestoreSaveFrameZero(m_register_backup);
205 m_thread.ClearStackFrames();
206 SetPlanComplete();
207 return true;
208 }
209 else
210 {
211 return false;
212 }
213}
214
215bool
216ThreadPlanCallFunction::StopOthers ()
217{
218 return m_stop_other_threads;
219}
220
221void
222ThreadPlanCallFunction::SetStopOthers (bool new_value)
223{
224 if (m_subplan_sp)
225 {
226 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
227 address_plan->SetStopOthers(new_value);
228 }
229 m_stop_other_threads = new_value;
230}
231
232StateType
233ThreadPlanCallFunction::RunState ()
234{
235 return eStateRunning;
236}
237
238void
239ThreadPlanCallFunction::DidPush ()
240{
241 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
242
243 m_thread.QueueThreadPlan(m_subplan_sp, false);
244
245}
246
247bool
248ThreadPlanCallFunction::WillStop ()
249{
250 return true;
251}
252
253bool
254ThreadPlanCallFunction::MischiefManaged ()
255{
256 if (IsPlanComplete())
257 {
258 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
259
260 if (log)
261 log->Printf("Completed call function plan.");
262
263 ThreadPlan::MischiefManaged ();
264 return true;
265 }
266 else
267 {
268 return false;
269 }
270}