blob: f87e8468640f3af0aa1e8aad946b66598df8728a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- BreakpointOptions.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/Breakpoint/BreakpointOptions.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Stream.h"
17#include "lldb/Core/StringList.h"
Jim Inghamd1686902010-10-14 23:45:03 +000018#include "lldb/Core/Value.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Breakpoint/StoppointCallbackContext.h"
Jim Inghamd1686902010-10-14 23:45:03 +000020#include "lldb/Target/Process.h"
Sean Callanana91dd992010-11-19 02:52:21 +000021#include "lldb/Target/Target.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000022#include "lldb/Target/ThreadSpec.h"
Jim Inghamd1686902010-10-14 23:45:03 +000023#include "lldb/Target/ThreadPlanTestCondition.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024
25using namespace lldb;
26using namespace lldb_private;
27
28bool
29BreakpointOptions::NullCallback (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
30{
31 return true;
32}
33
34//----------------------------------------------------------------------
35// BreakpointOptions constructor
36//----------------------------------------------------------------------
37BreakpointOptions::BreakpointOptions() :
38 m_callback (BreakpointOptions::NullCallback),
Chris Lattner24943d22010-06-08 16:52:24 +000039 m_callback_baton_sp (),
Greg Clayton54e7afa2010-07-09 20:39:50 +000040 m_callback_is_synchronous (false),
Chris Lattner24943d22010-06-08 16:52:24 +000041 m_enabled (true),
42 m_ignore_count (0),
Jim Inghamd1686902010-10-14 23:45:03 +000043 m_thread_spec_ap (NULL),
44 m_condition_ap()
Chris Lattner24943d22010-06-08 16:52:24 +000045{
46}
47
48//----------------------------------------------------------------------
49// BreakpointOptions copy constructor
50//----------------------------------------------------------------------
51BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
52 m_callback (rhs.m_callback),
53 m_callback_baton_sp (rhs.m_callback_baton_sp),
54 m_callback_is_synchronous (rhs.m_callback_is_synchronous),
55 m_enabled (rhs.m_enabled),
56 m_ignore_count (rhs.m_ignore_count),
Jim Inghamd1686902010-10-14 23:45:03 +000057 m_thread_spec_ap (NULL),
58 m_condition_ap (NULL)
Chris Lattner24943d22010-06-08 16:52:24 +000059{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000060 if (rhs.m_thread_spec_ap.get() != NULL)
61 m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
Jim Inghamd1686902010-10-14 23:45:03 +000062 if (rhs.m_condition_ap.get())
Sean Callanan77e93942010-10-29 00:29:03 +000063 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL));
Chris Lattner24943d22010-06-08 16:52:24 +000064}
65
66//----------------------------------------------------------------------
67// BreakpointOptions assignment operator
68//----------------------------------------------------------------------
69const BreakpointOptions&
70BreakpointOptions::operator=(const BreakpointOptions& rhs)
71{
72 m_callback = rhs.m_callback;
73 m_callback_baton_sp = rhs.m_callback_baton_sp;
74 m_callback_is_synchronous = rhs.m_callback_is_synchronous;
75 m_enabled = rhs.m_enabled;
76 m_ignore_count = rhs.m_ignore_count;
Jim Ingham3c7b5b92010-06-16 02:00:15 +000077 if (rhs.m_thread_spec_ap.get() != NULL)
78 m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
Jim Inghamd1686902010-10-14 23:45:03 +000079 if (rhs.m_condition_ap.get())
Sean Callanan77e93942010-10-29 00:29:03 +000080 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL));
Chris Lattner24943d22010-06-08 16:52:24 +000081 return *this;
82}
83
Jim Ingham649492b2010-06-18 01:00:58 +000084BreakpointOptions *
85BreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig)
86{
87 BreakpointHitCallback orig_callback = orig.m_callback;
88 lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
89 bool orig_is_sync = orig.m_callback_is_synchronous;
90
91 orig.ClearCallback();
92 BreakpointOptions *ret_val = new BreakpointOptions(orig);
93
94 orig.SetCallback (orig_callback, orig_callback_baton_sp, orig_is_sync);
95
96 return ret_val;
97}
98
Chris Lattner24943d22010-06-08 16:52:24 +000099//----------------------------------------------------------------------
100// Destructor
101//----------------------------------------------------------------------
102BreakpointOptions::~BreakpointOptions()
103{
104}
105
106//------------------------------------------------------------------
107// Callbacks
108//------------------------------------------------------------------
109void
110BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
111{
112 m_callback_is_synchronous = callback_is_synchronous;
113 m_callback = callback;
114 m_callback_baton_sp = callback_baton_sp;
115}
116
117void
118BreakpointOptions::ClearCallback ()
119{
Jim Inghamd1686902010-10-14 23:45:03 +0000120 m_callback = BreakpointOptions::NullCallback;
121 m_callback_is_synchronous = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000122 m_callback_baton_sp.reset();
123}
124
125Baton *
126BreakpointOptions::GetBaton ()
127{
128 return m_callback_baton_sp.get();
129}
130
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000131const Baton *
132BreakpointOptions::GetBaton () const
133{
134 return m_callback_baton_sp.get();
135}
136
Chris Lattner24943d22010-06-08 16:52:24 +0000137bool
138BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
139 lldb::user_id_t break_id,
140 lldb::user_id_t break_loc_id)
141{
142 if (m_callback && context->is_synchronous == IsCallbackSynchronous())
143 {
144 return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
145 context,
146 break_id,
147 break_loc_id);
148 }
149 else
150 return true;
151}
152
Jim Ingham649492b2010-06-18 01:00:58 +0000153bool
154BreakpointOptions::HasCallback ()
155{
156 return m_callback != BreakpointOptions::NullCallback;
157}
158
Jim Inghamd1686902010-10-14 23:45:03 +0000159void
160BreakpointOptions::SetCondition (const char *condition)
161{
162 if (condition == NULL || condition[0] == '\0')
163 {
164 if (m_condition_ap.get())
165 m_condition_ap.reset();
166 }
167 else
168 {
Sean Callanan77e93942010-10-29 00:29:03 +0000169 m_condition_ap.reset(new ClangUserExpression (condition, NULL));
Jim Inghamd1686902010-10-14 23:45:03 +0000170 }
171}
172
173ThreadPlan *
174BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
175 lldb::BreakpointLocationSP break_loc_sp,
176 Stream &error_stream)
177{
178 // No condition means we should stop, so return NULL.
179 if (!m_condition_ap.get())
180 return NULL;
181
182 // FIXME: I shouldn't have to do this, the process should handle it for me:
183 if (!exe_ctx.process->GetDynamicCheckers())
184 {
185 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
186
187 StreamString install_errors;
188
189 if (!dynamic_checkers->Install(install_errors, exe_ctx))
190 {
191 error_stream.Printf("Couldn't install dynamic checkers into the execution context: %s\n", install_errors.GetData());
192 return NULL;
193 }
194
195 exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
196 }
Sean Callanana91dd992010-11-19 02:52:21 +0000197
198 // Get the boolean type from the process's scratch AST context
199 ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
200 TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
Jim Inghamd1686902010-10-14 23:45:03 +0000201
Sean Callanan6a925532011-01-13 08:53:35 +0000202 if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, false /* keep_in_memory */))
Jim Inghamd1686902010-10-14 23:45:03 +0000203 {
204 // Errors mean we should stop.
205 return NULL;
206 }
207 // FIXME: When we can execute static expressions without running the target, we should check that here,
208 // and return something to indicate we should stop or just continue.
209
210 ThreadPlan *new_plan = new ThreadPlanTestCondition (*exe_ctx.thread,
211 exe_ctx,
212 m_condition_ap.get(),
213 break_loc_sp,
214 true);
215
216 return new_plan;
217}
218
219const char *
220BreakpointOptions::GetConditionText ()
221{
222 if (m_condition_ap.get())
223 return m_condition_ap->GetUserText();
224 else
225 return "<No Condition>";
226}
227
Chris Lattner24943d22010-06-08 16:52:24 +0000228//------------------------------------------------------------------
229// Enabled/Ignore Count
230//------------------------------------------------------------------
231bool
232BreakpointOptions::IsEnabled () const
233{
234 return m_enabled;
235}
236
237void
238BreakpointOptions::SetEnabled (bool enabled)
239{
240 m_enabled = enabled;
241}
242
Greg Clayton54e7afa2010-07-09 20:39:50 +0000243uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000244BreakpointOptions::GetIgnoreCount () const
245{
246 return m_ignore_count;
247}
248
249void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000250BreakpointOptions::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000251{
252 m_ignore_count = n;
253}
254
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000255const ThreadSpec *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000256BreakpointOptions::GetThreadSpecNoCreate () const
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000257{
258 return m_thread_spec_ap.get();
259}
260
261ThreadSpec *
262BreakpointOptions::GetThreadSpec ()
263{
264 if (m_thread_spec_ap.get() == NULL)
265 m_thread_spec_ap.reset (new ThreadSpec());
266
267 return m_thread_spec_ap.get();
268}
269
Chris Lattner24943d22010-06-08 16:52:24 +0000270void
271BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
272{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000273 GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000274}
275
Chris Lattner24943d22010-06-08 16:52:24 +0000276void
Jim Ingham649492b2010-06-18 01:00:58 +0000277BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
278{
279
280 // Figure out if there are any options not at their default value, and only print
281 // anything if there are:
282
Jim Ingham9c6898b2010-06-22 21:12:54 +0000283 if (m_ignore_count != 0 || !m_enabled || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
Jim Ingham649492b2010-06-18 01:00:58 +0000284 {
285 if (level == lldb::eDescriptionLevelVerbose)
286 {
287 s->EOL ();
288 s->IndentMore();
289 s->Indent();
290 s->PutCString("Breakpoint Options:\n");
291 s->IndentMore();
292 s->Indent();
293 }
294 else
295 s->PutCString(" Options: ");
296
297 if (m_ignore_count > 0)
298 s->Printf("ignore: %d ", m_ignore_count);
299 s->Printf("%sabled ", m_enabled ? "en" : "dis");
300
301 if (m_thread_spec_ap.get())
302 m_thread_spec_ap->GetDescription (s, level);
303 else if (level == eDescriptionLevelBrief)
304 s->PutCString ("thread spec: no ");
305 if (level == lldb::eDescriptionLevelFull)
306 {
307 s->IndentLess();
308 s->IndentMore();
309 }
310 }
311
312 if (m_callback_baton_sp.get())
313 {
314 if (level != eDescriptionLevelBrief)
315 s->EOL();
316 m_callback_baton_sp->GetDescription (s, level);
Jim Inghamd1686902010-10-14 23:45:03 +0000317 }
318 if (m_condition_ap.get())
319 {
320 if (level != eDescriptionLevelBrief)
321 {
322 s->EOL();
323 s->Printf("Condition: %s\n", m_condition_ap->GetUserText());
324 }
Greg Clayton12bec712010-06-28 21:30:43 +0000325 }
Jim Ingham649492b2010-06-18 01:00:58 +0000326}
327
328void
Chris Lattner24943d22010-06-08 16:52:24 +0000329BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
330{
Chris Lattner24943d22010-06-08 16:52:24 +0000331 CommandData *data = (CommandData *)m_data;
Jim Ingham649492b2010-06-18 01:00:58 +0000332
333 if (level == eDescriptionLevelBrief)
334 {
Greg Clayton12bec712010-06-28 21:30:43 +0000335 s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
Jim Ingham649492b2010-06-18 01:00:58 +0000336 return;
337 }
338
339 s->IndentMore ();
340 s->Indent("Breakpoint commands:\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000341
342 s->IndentMore ();
343 if (data && data->user_source.GetSize() > 0)
344 {
345 const size_t num_strings = data->user_source.GetSize();
346 for (size_t i = 0; i < num_strings; ++i)
347 {
348 s->Indent(data->user_source.GetStringAtIndex(i));
349 s->EOL();
350 }
351 }
352 else
353 {
354 s->PutCString ("No commands.\n");
355 }
356 s->IndentLess ();
Jim Ingham649492b2010-06-18 01:00:58 +0000357 s->IndentLess ();
Chris Lattner24943d22010-06-08 16:52:24 +0000358}
359