blob: c2277dbc910191caffc842ad583374e1ebe12e59 [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 Callanan5b658cc2011-11-07 23:35:40 +000063 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown));
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 Callanan5b658cc2011-11-07 23:35:40 +000080 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown));
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 Callanan5b658cc2011-11-07 23:35:40 +0000169 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown));
Jim Inghamd1686902010-10-14 23:45:03 +0000170 }
171}
172
173ThreadPlan *
174BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
Greg Clayton987c7eb2011-09-17 08:33:22 +0000175 const BreakpointLocationSP &break_loc_sp,
Jim Inghamd1686902010-10-14 23:45:03 +0000176 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:
Greg Clayton567e7f32011-09-22 04:58:26 +0000183 Process *process = exe_ctx.GetProcessPtr();
184 if (!process->GetDynamicCheckers())
Jim Inghamd1686902010-10-14 23:45:03 +0000185 {
186 DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
187
188 StreamString install_errors;
189
190 if (!dynamic_checkers->Install(install_errors, exe_ctx))
191 {
192 error_stream.Printf("Couldn't install dynamic checkers into the execution context: %s\n", install_errors.GetData());
193 return NULL;
194 }
195
Greg Clayton567e7f32011-09-22 04:58:26 +0000196 process->SetDynamicCheckers(dynamic_checkers);
Jim Inghamd1686902010-10-14 23:45:03 +0000197 }
Sean Callanana91dd992010-11-19 02:52:21 +0000198
199 // Get the boolean type from the process's scratch AST context
Greg Clayton567e7f32011-09-22 04:58:26 +0000200 ClangASTContext *ast_context = exe_ctx.GetTargetRef().GetScratchClangASTContext();
Sean Callanana91dd992010-11-19 02:52:21 +0000201 TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
Jim Inghamd1686902010-10-14 23:45:03 +0000202
Sean Callanan47dc4572011-09-15 02:13:07 +0000203 const bool keep_in_memory = false;
204
205 if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, eExecutionPolicyAlways, keep_in_memory))
Jim Inghamd1686902010-10-14 23:45:03 +0000206 {
207 // Errors mean we should stop.
208 return NULL;
209 }
210 // FIXME: When we can execute static expressions without running the target, we should check that here,
211 // and return something to indicate we should stop or just continue.
212
Greg Clayton567e7f32011-09-22 04:58:26 +0000213 ThreadPlan *new_plan = new ThreadPlanTestCondition (exe_ctx.GetThreadRef(),
Jim Inghamd1686902010-10-14 23:45:03 +0000214 exe_ctx,
215 m_condition_ap.get(),
216 break_loc_sp,
217 true);
218
219 return new_plan;
220}
221
222const char *
Jim Inghamac354422011-06-15 21:16:00 +0000223BreakpointOptions::GetConditionText () const
Jim Inghamd1686902010-10-14 23:45:03 +0000224{
225 if (m_condition_ap.get())
226 return m_condition_ap->GetUserText();
227 else
Jim Inghamac354422011-06-15 21:16:00 +0000228 return NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000229}
230
Chris Lattner24943d22010-06-08 16:52:24 +0000231//------------------------------------------------------------------
232// Enabled/Ignore Count
233//------------------------------------------------------------------
234bool
235BreakpointOptions::IsEnabled () const
236{
237 return m_enabled;
238}
239
240void
241BreakpointOptions::SetEnabled (bool enabled)
242{
243 m_enabled = enabled;
244}
245
Greg Clayton54e7afa2010-07-09 20:39:50 +0000246uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000247BreakpointOptions::GetIgnoreCount () const
248{
249 return m_ignore_count;
250}
251
252void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000253BreakpointOptions::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000254{
255 m_ignore_count = n;
256}
257
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000258const ThreadSpec *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000259BreakpointOptions::GetThreadSpecNoCreate () const
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000260{
261 return m_thread_spec_ap.get();
262}
263
264ThreadSpec *
265BreakpointOptions::GetThreadSpec ()
266{
267 if (m_thread_spec_ap.get() == NULL)
268 m_thread_spec_ap.reset (new ThreadSpec());
269
270 return m_thread_spec_ap.get();
271}
272
Chris Lattner24943d22010-06-08 16:52:24 +0000273void
274BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
275{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000276 GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000277}
278
Chris Lattner24943d22010-06-08 16:52:24 +0000279void
Jim Ingham649492b2010-06-18 01:00:58 +0000280BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
281{
282
283 // Figure out if there are any options not at their default value, and only print
284 // anything if there are:
285
Jim Ingham9c6898b2010-06-22 21:12:54 +0000286 if (m_ignore_count != 0 || !m_enabled || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
Jim Ingham649492b2010-06-18 01:00:58 +0000287 {
288 if (level == lldb::eDescriptionLevelVerbose)
289 {
290 s->EOL ();
291 s->IndentMore();
292 s->Indent();
293 s->PutCString("Breakpoint Options:\n");
294 s->IndentMore();
295 s->Indent();
296 }
297 else
298 s->PutCString(" Options: ");
299
300 if (m_ignore_count > 0)
301 s->Printf("ignore: %d ", m_ignore_count);
302 s->Printf("%sabled ", m_enabled ? "en" : "dis");
303
304 if (m_thread_spec_ap.get())
305 m_thread_spec_ap->GetDescription (s, level);
306 else if (level == eDescriptionLevelBrief)
307 s->PutCString ("thread spec: no ");
308 if (level == lldb::eDescriptionLevelFull)
309 {
310 s->IndentLess();
311 s->IndentMore();
312 }
313 }
314
Johnny Chen7aecabb2011-06-20 18:59:49 +0000315 if (m_callback_baton_sp.get())
316 {
317 if (level != eDescriptionLevelBrief)
318 {
319 s->EOL();
320 m_callback_baton_sp->GetDescription (s, level);
321 }
322 }
Jim Inghamd1686902010-10-14 23:45:03 +0000323 if (m_condition_ap.get())
324 {
325 if (level != eDescriptionLevelBrief)
326 {
327 s->EOL();
328 s->Printf("Condition: %s\n", m_condition_ap->GetUserText());
329 }
Greg Clayton12bec712010-06-28 21:30:43 +0000330 }
Jim Ingham649492b2010-06-18 01:00:58 +0000331}
332
333void
Chris Lattner24943d22010-06-08 16:52:24 +0000334BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
335{
Chris Lattner24943d22010-06-08 16:52:24 +0000336 CommandData *data = (CommandData *)m_data;
Jim Ingham649492b2010-06-18 01:00:58 +0000337
338 if (level == eDescriptionLevelBrief)
339 {
Greg Clayton12bec712010-06-28 21:30:43 +0000340 s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
Jim Ingham649492b2010-06-18 01:00:58 +0000341 return;
342 }
343
344 s->IndentMore ();
345 s->Indent("Breakpoint commands:\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000346
347 s->IndentMore ();
348 if (data && data->user_source.GetSize() > 0)
349 {
350 const size_t num_strings = data->user_source.GetSize();
351 for (size_t i = 0; i < num_strings; ++i)
352 {
353 s->Indent(data->user_source.GetStringAtIndex(i));
354 s->EOL();
355 }
356 }
357 else
358 {
359 s->PutCString ("No commands.\n");
360 }
361 s->IndentLess ();
Jim Ingham649492b2010-06-18 01:00:58 +0000362 s->IndentLess ();
Chris Lattner24943d22010-06-08 16:52:24 +0000363}
364