blob: f0f18457fd2a641ffc13fc8baa987ee3ea0731aa [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 Callanan47dc4572011-09-15 02:13:07 +0000202 const bool keep_in_memory = false;
203
204 if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, eExecutionPolicyAlways, keep_in_memory))
Jim Inghamd1686902010-10-14 23:45:03 +0000205 {
206 // Errors mean we should stop.
207 return NULL;
208 }
209 // FIXME: When we can execute static expressions without running the target, we should check that here,
210 // and return something to indicate we should stop or just continue.
211
212 ThreadPlan *new_plan = new ThreadPlanTestCondition (*exe_ctx.thread,
213 exe_ctx,
214 m_condition_ap.get(),
215 break_loc_sp,
216 true);
217
218 return new_plan;
219}
220
221const char *
Jim Inghamac354422011-06-15 21:16:00 +0000222BreakpointOptions::GetConditionText () const
Jim Inghamd1686902010-10-14 23:45:03 +0000223{
224 if (m_condition_ap.get())
225 return m_condition_ap->GetUserText();
226 else
Jim Inghamac354422011-06-15 21:16:00 +0000227 return NULL;
Jim Inghamd1686902010-10-14 23:45:03 +0000228}
229
Chris Lattner24943d22010-06-08 16:52:24 +0000230//------------------------------------------------------------------
231// Enabled/Ignore Count
232//------------------------------------------------------------------
233bool
234BreakpointOptions::IsEnabled () const
235{
236 return m_enabled;
237}
238
239void
240BreakpointOptions::SetEnabled (bool enabled)
241{
242 m_enabled = enabled;
243}
244
Greg Clayton54e7afa2010-07-09 20:39:50 +0000245uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000246BreakpointOptions::GetIgnoreCount () const
247{
248 return m_ignore_count;
249}
250
251void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000252BreakpointOptions::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000253{
254 m_ignore_count = n;
255}
256
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000257const ThreadSpec *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000258BreakpointOptions::GetThreadSpecNoCreate () const
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000259{
260 return m_thread_spec_ap.get();
261}
262
263ThreadSpec *
264BreakpointOptions::GetThreadSpec ()
265{
266 if (m_thread_spec_ap.get() == NULL)
267 m_thread_spec_ap.reset (new ThreadSpec());
268
269 return m_thread_spec_ap.get();
270}
271
Chris Lattner24943d22010-06-08 16:52:24 +0000272void
273BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
274{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000275 GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000276}
277
Chris Lattner24943d22010-06-08 16:52:24 +0000278void
Jim Ingham649492b2010-06-18 01:00:58 +0000279BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
280{
281
282 // Figure out if there are any options not at their default value, and only print
283 // anything if there are:
284
Jim Ingham9c6898b2010-06-22 21:12:54 +0000285 if (m_ignore_count != 0 || !m_enabled || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
Jim Ingham649492b2010-06-18 01:00:58 +0000286 {
287 if (level == lldb::eDescriptionLevelVerbose)
288 {
289 s->EOL ();
290 s->IndentMore();
291 s->Indent();
292 s->PutCString("Breakpoint Options:\n");
293 s->IndentMore();
294 s->Indent();
295 }
296 else
297 s->PutCString(" Options: ");
298
299 if (m_ignore_count > 0)
300 s->Printf("ignore: %d ", m_ignore_count);
301 s->Printf("%sabled ", m_enabled ? "en" : "dis");
302
303 if (m_thread_spec_ap.get())
304 m_thread_spec_ap->GetDescription (s, level);
305 else if (level == eDescriptionLevelBrief)
306 s->PutCString ("thread spec: no ");
307 if (level == lldb::eDescriptionLevelFull)
308 {
309 s->IndentLess();
310 s->IndentMore();
311 }
312 }
313
Johnny Chen7aecabb2011-06-20 18:59:49 +0000314 if (m_callback_baton_sp.get())
315 {
316 if (level != eDescriptionLevelBrief)
317 {
318 s->EOL();
319 m_callback_baton_sp->GetDescription (s, level);
320 }
321 }
Jim Inghamd1686902010-10-14 23:45:03 +0000322 if (m_condition_ap.get())
323 {
324 if (level != eDescriptionLevelBrief)
325 {
326 s->EOL();
327 s->Printf("Condition: %s\n", m_condition_ap->GetUserText());
328 }
Greg Clayton12bec712010-06-28 21:30:43 +0000329 }
Jim Ingham649492b2010-06-18 01:00:58 +0000330}
331
332void
Chris Lattner24943d22010-06-08 16:52:24 +0000333BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
334{
Chris Lattner24943d22010-06-08 16:52:24 +0000335 CommandData *data = (CommandData *)m_data;
Jim Ingham649492b2010-06-18 01:00:58 +0000336
337 if (level == eDescriptionLevelBrief)
338 {
Greg Clayton12bec712010-06-28 21:30:43 +0000339 s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
Jim Ingham649492b2010-06-18 01:00:58 +0000340 return;
341 }
342
343 s->IndentMore ();
344 s->Indent("Breakpoint commands:\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000345
346 s->IndentMore ();
347 if (data && data->user_source.GetSize() > 0)
348 {
349 const size_t num_strings = data->user_source.GetSize();
350 for (size_t i = 0; i < num_strings; ++i)
351 {
352 s->Indent(data->user_source.GetStringAtIndex(i));
353 s->EOL();
354 }
355 }
356 else
357 {
358 s->PutCString ("No commands.\n");
359 }
360 s->IndentLess ();
Jim Ingham649492b2010-06-18 01:00:58 +0000361 s->IndentLess ();
Chris Lattner24943d22010-06-08 16:52:24 +0000362}
363