1 //===-- 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"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Breakpoint/StoppointCallbackContext.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/ThreadSpec.h"
23 #include "lldb/Expression/ClangUserExpression.h"
24
25 using namespace lldb;
26 using namespace lldb_private;
27
28 bool
NullCallback(void * baton,StoppointCallbackContext * context,lldb::user_id_t break_id,lldb::user_id_t break_loc_id)29 BreakpointOptions::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 //----------------------------------------------------------------------
BreakpointOptions()37 BreakpointOptions::BreakpointOptions() :
38 m_callback (BreakpointOptions::NullCallback),
39 m_callback_baton_sp (),
40 m_callback_is_synchronous (false),
41 m_enabled (true),
42 m_one_shot (false),
43 m_ignore_count (0),
44 m_thread_spec_ap (),
45 m_condition_text (),
46 m_condition_text_hash (0)
47 {
48 }
49
50 //----------------------------------------------------------------------
51 // BreakpointOptions copy constructor
52 //----------------------------------------------------------------------
BreakpointOptions(const BreakpointOptions & rhs)53 BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
54 m_callback (rhs.m_callback),
55 m_callback_baton_sp (rhs.m_callback_baton_sp),
56 m_callback_is_synchronous (rhs.m_callback_is_synchronous),
57 m_enabled (rhs.m_enabled),
58 m_one_shot (rhs.m_one_shot),
59 m_ignore_count (rhs.m_ignore_count),
60 m_thread_spec_ap ()
61 {
62 if (rhs.m_thread_spec_ap.get() != NULL)
63 m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
64 m_condition_text = rhs.m_condition_text;
65 m_condition_text_hash = rhs.m_condition_text_hash;
66 }
67
68 //----------------------------------------------------------------------
69 // BreakpointOptions assignment operator
70 //----------------------------------------------------------------------
71 const BreakpointOptions&
operator =(const BreakpointOptions & rhs)72 BreakpointOptions::operator=(const BreakpointOptions& rhs)
73 {
74 m_callback = rhs.m_callback;
75 m_callback_baton_sp = rhs.m_callback_baton_sp;
76 m_callback_is_synchronous = rhs.m_callback_is_synchronous;
77 m_enabled = rhs.m_enabled;
78 m_one_shot = rhs.m_one_shot;
79 m_ignore_count = rhs.m_ignore_count;
80 if (rhs.m_thread_spec_ap.get() != NULL)
81 m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
82 m_condition_text = rhs.m_condition_text;
83 m_condition_text_hash = rhs.m_condition_text_hash;
84 return *this;
85 }
86
87 BreakpointOptions *
CopyOptionsNoCallback(BreakpointOptions & orig)88 BreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig)
89 {
90 BreakpointHitCallback orig_callback = orig.m_callback;
91 lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
92 bool orig_is_sync = orig.m_callback_is_synchronous;
93
94 orig.ClearCallback();
95 BreakpointOptions *ret_val = new BreakpointOptions(orig);
96
97 orig.SetCallback (orig_callback, orig_callback_baton_sp, orig_is_sync);
98
99 return ret_val;
100 }
101
102 //----------------------------------------------------------------------
103 // Destructor
104 //----------------------------------------------------------------------
~BreakpointOptions()105 BreakpointOptions::~BreakpointOptions()
106 {
107 }
108
109 //------------------------------------------------------------------
110 // Callbacks
111 //------------------------------------------------------------------
112 void
SetCallback(BreakpointHitCallback callback,const BatonSP & callback_baton_sp,bool callback_is_synchronous)113 BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
114 {
115 m_callback_is_synchronous = callback_is_synchronous;
116 m_callback = callback;
117 m_callback_baton_sp = callback_baton_sp;
118 }
119
120 void
ClearCallback()121 BreakpointOptions::ClearCallback ()
122 {
123 m_callback = BreakpointOptions::NullCallback;
124 m_callback_is_synchronous = false;
125 m_callback_baton_sp.reset();
126 }
127
128 Baton *
GetBaton()129 BreakpointOptions::GetBaton ()
130 {
131 return m_callback_baton_sp.get();
132 }
133
134 const Baton *
GetBaton() const135 BreakpointOptions::GetBaton () const
136 {
137 return m_callback_baton_sp.get();
138 }
139
140 bool
InvokeCallback(StoppointCallbackContext * context,lldb::user_id_t break_id,lldb::user_id_t break_loc_id)141 BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
142 lldb::user_id_t break_id,
143 lldb::user_id_t break_loc_id)
144 {
145 if (m_callback && context->is_synchronous == IsCallbackSynchronous())
146 {
147 return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
148 context,
149 break_id,
150 break_loc_id);
151 }
152 else
153 return true;
154 }
155
156 bool
HasCallback()157 BreakpointOptions::HasCallback ()
158 {
159 return m_callback != BreakpointOptions::NullCallback;
160 }
161
162 void
SetCondition(const char * condition)163 BreakpointOptions::SetCondition (const char *condition)
164 {
165 if (!condition)
166 condition = "";
167
168 m_condition_text.assign(condition);
169 std::hash<std::string> hasher;
170 m_condition_text_hash = hasher(m_condition_text);
171 }
172
173 const char *
GetConditionText(size_t * hash) const174 BreakpointOptions::GetConditionText (size_t *hash) const
175 {
176 if (!m_condition_text.empty())
177 {
178 if (hash)
179 *hash = m_condition_text_hash;
180
181 return m_condition_text.c_str();
182 }
183 else
184 {
185 return NULL;
186 }
187 }
188
189 const ThreadSpec *
GetThreadSpecNoCreate() const190 BreakpointOptions::GetThreadSpecNoCreate () const
191 {
192 return m_thread_spec_ap.get();
193 }
194
195 ThreadSpec *
GetThreadSpec()196 BreakpointOptions::GetThreadSpec ()
197 {
198 if (m_thread_spec_ap.get() == NULL)
199 m_thread_spec_ap.reset (new ThreadSpec());
200
201 return m_thread_spec_ap.get();
202 }
203
204 void
SetThreadID(lldb::tid_t thread_id)205 BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
206 {
207 GetThreadSpec()->SetTID(thread_id);
208 }
209
210 void
GetDescription(Stream * s,lldb::DescriptionLevel level) const211 BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
212 {
213
214 // Figure out if there are any options not at their default value, and only print
215 // anything if there are:
216
217 if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
218 {
219 if (level == lldb::eDescriptionLevelVerbose)
220 {
221 s->EOL ();
222 s->IndentMore();
223 s->Indent();
224 s->PutCString("Breakpoint Options:\n");
225 s->IndentMore();
226 s->Indent();
227 }
228 else
229 s->PutCString(" Options: ");
230
231 if (m_ignore_count > 0)
232 s->Printf("ignore: %d ", m_ignore_count);
233 s->Printf("%sabled ", m_enabled ? "en" : "dis");
234
235 if (m_one_shot)
236 s->Printf ("one-shot ");
237
238 if (m_thread_spec_ap.get())
239 m_thread_spec_ap->GetDescription (s, level);
240 else if (level == eDescriptionLevelBrief)
241 s->PutCString ("thread spec: no ");
242 if (level == lldb::eDescriptionLevelFull)
243 {
244 s->IndentLess();
245 s->IndentMore();
246 }
247 }
248
249 if (m_callback_baton_sp.get())
250 {
251 if (level != eDescriptionLevelBrief)
252 {
253 s->EOL();
254 m_callback_baton_sp->GetDescription (s, level);
255 }
256 }
257 if (!m_condition_text.empty())
258 {
259 if (level != eDescriptionLevelBrief)
260 {
261 s->EOL();
262 s->Printf("Condition: %s\n", m_condition_text.c_str());
263 }
264 }
265 }
266
267 void
GetDescription(Stream * s,lldb::DescriptionLevel level) const268 BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
269 {
270 CommandData *data = (CommandData *)m_data;
271
272 if (level == eDescriptionLevelBrief)
273 {
274 s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
275 return;
276 }
277
278 s->IndentMore ();
279 s->Indent("Breakpoint commands:\n");
280
281 s->IndentMore ();
282 if (data && data->user_source.GetSize() > 0)
283 {
284 const size_t num_strings = data->user_source.GetSize();
285 for (size_t i = 0; i < num_strings; ++i)
286 {
287 s->Indent(data->user_source.GetStringAtIndex(i));
288 s->EOL();
289 }
290 }
291 else
292 {
293 s->PutCString ("No commands.\n");
294 }
295 s->IndentLess ();
296 s->IndentLess ();
297 }
298
299