blob: 2f5f7cca1cd755a494b159aacdfb668945af591f [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"
Jim Ingham40d871f2010-10-26 00:27:4517#include "lldb/Breakpoint/Breakpoint.h"
18#include "lldb/Breakpoint/BreakpointLocation.h"
Chris Lattner30fdc8d2010-06-08 16:52:2419#include "lldb/Core/Address.h"
20#include "lldb/Core/Log.h"
21#include "lldb/Core/Stream.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
Jim Ingham40d871f2010-10-26 00:27:4524#include "lldb/Target/StopInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:2425#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadPlanRunToAddress.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32//----------------------------------------------------------------------
33// ThreadPlanCallFunction: Plan to call a single function
34//----------------------------------------------------------------------
35
36ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
37 Address &function,
38 lldb::addr_t arg,
39 bool stop_other_threads,
Sean Callananfc55f5d2010-09-21 00:44:1240 bool discard_on_error,
41 lldb::addr_t *this_arg) :
Jim Inghamb01e742a2010-06-19 04:45:3242 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3343 m_valid (false),
44 m_stop_other_threads (stop_other_threads),
Chris Lattner30fdc8d2010-06-08 16:52:2445 m_arg_addr (arg),
46 m_args (NULL),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3347 m_process (thread.GetProcess()),
48 m_thread (thread)
Chris Lattner30fdc8d2010-06-08 16:52:2449{
Chris Lattner30fdc8d2010-06-08 16:52:2450 SetOkayToDiscard (discard_on_error);
51
52 Process& process = thread.GetProcess();
53 Target& target = process.GetTarget();
54 const ABI *abi = process.GetABI();
55
56 if (!abi)
57 return;
58
59 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
60
61 SymbolContextList contexts;
62 SymbolContext context;
63 ModuleSP executableModuleSP (target.GetExecutableModule());
64
65 if (!executableModuleSP ||
66 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
67 return;
68
69 contexts.GetContextAtIndex(0, context);
70
71 m_start_addr = context.symbol->GetValue();
Greg Claytonf5e56de2010-09-14 23:36:4072 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:2473
74 if (!thread.SaveFrameZeroState(m_register_backup))
75 return;
76
77 m_function_addr = function;
Greg Claytonf5e56de2010-09-14 23:36:4078 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:2479
80 if (!abi->PrepareTrivialCall(thread,
81 spBelowRedZone,
82 FunctionLoadAddr,
83 StartLoadAddr,
Sean Callananfc55f5d2010-09-21 00:44:1284 m_arg_addr,
85 this_arg))
Chris Lattner30fdc8d2010-06-08 16:52:2486 return;
87
88 m_valid = true;
89}
90
91ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
92 Address &function,
93 ValueList &args,
94 bool stop_other_threads,
95 bool discard_on_error) :
Jim Inghamb01e742a2010-06-19 04:45:3296 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
Benjamin Kramer1ee0d4f2010-07-16 12:32:3397 m_valid (false),
98 m_stop_other_threads (stop_other_threads),
Chris Lattner30fdc8d2010-06-08 16:52:2499 m_arg_addr (0),
100 m_args (&args),
Benjamin Kramer1ee0d4f2010-07-16 12:32:33101 m_process (thread.GetProcess()),
102 m_thread (thread)
Chris Lattner30fdc8d2010-06-08 16:52:24103{
104
105 SetOkayToDiscard (discard_on_error);
106
107 Process& process = thread.GetProcess();
108 Target& target = process.GetTarget();
109 const ABI *abi = process.GetABI();
110
111 if(!abi)
112 return;
113
114 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
115
116 SymbolContextList contexts;
117 SymbolContext context;
118 ModuleSP executableModuleSP (target.GetExecutableModule());
119
120 if (!executableModuleSP ||
121 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
122 return;
123
124 contexts.GetContextAtIndex(0, context);
125
126 m_start_addr = context.symbol->GetValue();
Greg Claytonf5e56de2010-09-14 23:36:40127 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:24128
129 if(!thread.SaveFrameZeroState(m_register_backup))
130 return;
131
132 m_function_addr = function;
Greg Claytonf5e56de2010-09-14 23:36:40133 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
Chris Lattner30fdc8d2010-06-08 16:52:24134
135 if (!abi->PrepareNormalCall(thread,
136 spBelowRedZone,
137 FunctionLoadAddr,
138 StartLoadAddr,
139 *m_args))
140 return;
141
142 m_valid = true;
143}
144
145ThreadPlanCallFunction::~ThreadPlanCallFunction ()
146{
147}
148
149void
150ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
151{
152 if (level == lldb::eDescriptionLevelBrief)
153 {
154 s->Printf("Function call thread plan");
155 }
156 else
157 {
158 if (m_args)
Greg Claytonf5e56de2010-09-14 23:36:40159 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:24160 else
Greg Claytonf5e56de2010-09-14 23:36:40161 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:24162 }
163}
164
165bool
166ThreadPlanCallFunction::ValidatePlan (Stream *error)
167{
168 if (!m_valid)
169 return false;
170
171 return true;
172}
173
174bool
175ThreadPlanCallFunction::PlanExplainsStop ()
176{
Jim Ingham40d871f2010-10-26 00:27:45177 // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
178 // we answer yes.
179 if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
180 return true;
Sean Callanan3e6fedc2010-10-19 22:24:06181
Jim Ingham40d871f2010-10-26 00:27:45182 // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
183 if (!OkayToDiscard())
184 return false;
185
186 // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
187 // If it is not an internal breakpoint, consult OkayToDiscard.
188 lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
189 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
190 {
191 uint64_t break_site_id = stop_info_sp->GetValue();
192 lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
193 if (bp_site_sp)
194 {
195 uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
196 bool is_internal = true;
197 for (uint32_t i = 0; i < num_owners; i++)
198 {
199 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
200 {
201 is_internal = false;
202 break;
203 }
204 }
205 if (is_internal)
206 return false;
207 }
208
209 return OkayToDiscard();
210 }
211 else
212 {
213 // If the subplan is running, any crashes are attributable to us.
214 return (m_subplan_sp.get() != NULL);
215 }
Chris Lattner30fdc8d2010-06-08 16:52:24216}
217
218bool
219ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
220{
221 if (PlanExplainsStop())
222 {
Sean Callanan5300d372010-07-31 01:32:05223 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
224
225 if (log)
226 {
227 RegisterContext *reg_ctx = m_thread.GetRegisterContext();
228
229 log->PutCString("Function completed. Register state was:");
230
231 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
232 register_index < num_registers;
233 ++register_index)
234 {
235 const char *register_name = reg_ctx->GetRegisterName(register_index);
236 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
237
238 log->Printf(" %s = 0x%llx", register_name, register_value);
239 }
240 }
241
Chris Lattner30fdc8d2010-06-08 16:52:24242 m_thread.RestoreSaveFrameZero(m_register_backup);
243 m_thread.ClearStackFrames();
244 SetPlanComplete();
245 return true;
246 }
247 else
248 {
249 return false;
250 }
251}
252
253bool
254ThreadPlanCallFunction::StopOthers ()
255{
256 return m_stop_other_threads;
257}
258
259void
260ThreadPlanCallFunction::SetStopOthers (bool new_value)
261{
262 if (m_subplan_sp)
263 {
264 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
265 address_plan->SetStopOthers(new_value);
266 }
267 m_stop_other_threads = new_value;
268}
269
270StateType
271ThreadPlanCallFunction::RunState ()
272{
273 return eStateRunning;
274}
275
276void
277ThreadPlanCallFunction::DidPush ()
278{
279 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
280
281 m_thread.QueueThreadPlan(m_subplan_sp, false);
282
283}
284
285bool
286ThreadPlanCallFunction::WillStop ()
287{
288 return true;
289}
290
291bool
292ThreadPlanCallFunction::MischiefManaged ()
293{
294 if (IsPlanComplete())
295 {
296 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
297
298 if (log)
299 log->Printf("Completed call function plan.");
300
301 ThreadPlan::MischiefManaged ();
302 return true;
303 }
304 else
305 {
306 return false;
307 }
308}