blob: ca5503ff2d347bb6f411b0022304fe939858d364 [file] [log] [blame]
Johnny Chenecd4feb2011-10-14 00:42:25 +00001//===-- Watchpoint.cpp ------------------------------------------*- C++ -*-===//
Chris Lattner24943d22010-06-08 16:52:24 +00002//
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
Johnny Chenecd4feb2011-10-14 00:42:25 +000010#include "lldb/Breakpoint/Watchpoint.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Johnny Chen712a6282011-10-17 18:58:00 +000016#include "lldb/Breakpoint/StoppointCallbackContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/Stream.h"
Johnny Chen712a6282011-10-17 18:58:00 +000018#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/ThreadSpec.h"
Jim Ingham14f17cf2012-05-02 00:30:53 +000021#include "lldb/Expression/ClangUserExpression.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chenecd4feb2011-10-14 00:42:25 +000026Watchpoint::Watchpoint (lldb::addr_t addr, size_t size, bool hardware) :
Johnny Chen116a5cd2012-02-25 06:44:30 +000027 StoppointLocation (0, addr, size, hardware),
Johnny Chen096c2932011-09-26 22:40:50 +000028 m_target(NULL),
Johnny Chen116a5cd2012-02-25 06:44:30 +000029 m_enabled(false),
Johnny Chen01acfa72011-09-22 18:04:58 +000030 m_is_hardware(hardware),
Johnny Chen9e985592012-08-13 21:09:54 +000031 m_is_watch_variable(false),
Johnny Chenf84e5662012-08-21 23:17:04 +000032 m_is_ephemeral(false),
Johnny Chen258db3a2012-08-23 22:28:26 +000033 m_disabled_count(0),
Chris Lattner24943d22010-06-08 16:52:24 +000034 m_watch_read(0),
35 m_watch_write(0),
36 m_watch_was_read(0),
37 m_watch_was_written(0),
38 m_ignore_count(0),
Johnny Chen0b093662012-08-14 20:56:37 +000039 m_false_alarms(0),
Johnny Chen41a55ef2011-10-14 19:15:48 +000040 m_decl_str(),
Johnny Chen116a5cd2012-02-25 06:44:30 +000041 m_watch_spec_str(),
Johnny Chen9e985592012-08-13 21:09:54 +000042 m_snapshot_old_str(),
43 m_snapshot_new_str(),
44 m_snapshot_old_val(0),
45 m_snapshot_new_val(0),
Johnny Chenf3ec4612012-08-09 23:09:42 +000046 m_error(),
47 m_options ()
Chris Lattner24943d22010-06-08 16:52:24 +000048{
49}
50
Johnny Chenecd4feb2011-10-14 00:42:25 +000051Watchpoint::~Watchpoint()
Chris Lattner24943d22010-06-08 16:52:24 +000052{
53}
54
Johnny Chenf3ec4612012-08-09 23:09:42 +000055// This function is used when "baton" doesn't need to be freed
56void
57Watchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
Chris Lattner24943d22010-06-08 16:52:24 +000058{
Johnny Chenf3ec4612012-08-09 23:09:42 +000059 // The default "Baton" class will keep a copy of "baton" and won't free
60 // or delete it when it goes goes out of scope.
61 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
62
63 //SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
64}
65
66// This function is used when a baton needs to be freed and therefore is
67// contained in a "Baton" subclass.
68void
69Watchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
70{
71 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
72}
73
74void
75Watchpoint::ClearCallback ()
76{
77 m_options.ClearCallback ();
Chris Lattner24943d22010-06-08 16:52:24 +000078}
79
Johnny Chen10b12b32011-09-16 21:41:42 +000080void
Johnny Chen9e985592012-08-13 21:09:54 +000081Watchpoint::SetDeclInfo (const std::string &str)
Johnny Chen10b12b32011-09-16 21:41:42 +000082{
83 m_decl_str = str;
84 return;
85}
86
Johnny Chen9e985592012-08-13 21:09:54 +000087std::string
88Watchpoint::GetWatchSpec()
89{
90 return m_watch_spec_str;
91}
92
Johnny Chen116a5cd2012-02-25 06:44:30 +000093void
Johnny Chen9e985592012-08-13 21:09:54 +000094Watchpoint::SetWatchSpec (const std::string &str)
Johnny Chen116a5cd2012-02-25 06:44:30 +000095{
96 m_watch_spec_str = str;
97 return;
98}
99
Johnny Chen519274f2012-08-14 23:09:48 +0000100// Strip at most one character from the end of the string.
101static inline std::string
102RStripOnce(const std::string &str, const char c)
103{
104 std::string res = str;
105 size_t len = res.length();
106 if (len && res.at(len - 1) == '\n')
107 res.resize(len - 1);
108 return res;
109}
110
Johnny Chen9e985592012-08-13 21:09:54 +0000111std::string
112Watchpoint::GetOldSnapshot() const
113{
114 return m_snapshot_old_str;
115}
116
117void
118Watchpoint::SetOldSnapshot (const std::string &str)
119{
Johnny Chen519274f2012-08-14 23:09:48 +0000120 m_snapshot_old_str = RStripOnce(str, '\n');
Johnny Chen9e985592012-08-13 21:09:54 +0000121}
122
123std::string
124Watchpoint::GetNewSnapshot() const
125{
126 return m_snapshot_new_str;
127}
128
129void
130Watchpoint::SetNewSnapshot (const std::string &str)
131{
132 m_snapshot_old_str = m_snapshot_new_str;
Johnny Chen519274f2012-08-14 23:09:48 +0000133 m_snapshot_new_str = RStripOnce(str, '\n');
Johnny Chen9e985592012-08-13 21:09:54 +0000134}
135
136uint64_t
137Watchpoint::GetOldSnapshotVal() const
138{
139 return m_snapshot_old_val;
140}
141
142void
143Watchpoint::SetOldSnapshotVal (uint64_t val)
144{
145 m_snapshot_old_val = val;
146 return;
147}
148
149uint64_t
150Watchpoint::GetNewSnapshotVal() const
151{
152 return m_snapshot_new_val;
153}
154
155void
156Watchpoint::SetNewSnapshotVal (uint64_t val)
157{
158 m_snapshot_old_val = m_snapshot_new_val;
159 m_snapshot_new_val = val;
160 return;
161}
162
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000163void
164Watchpoint::ClearSnapshots()
165{
166 m_snapshot_old_str.clear();
167 m_snapshot_new_str.clear();
168 m_snapshot_old_val = 0;
169 m_snapshot_new_val = 0;
170}
171
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000172// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
173// member field is more accurate.
Johnny Chen01acfa72011-09-22 18:04:58 +0000174bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000175Watchpoint::IsHardware () const
Johnny Chen01acfa72011-09-22 18:04:58 +0000176{
177 return m_is_hardware;
178}
179
Johnny Chen9e985592012-08-13 21:09:54 +0000180bool
181Watchpoint::IsWatchVariable() const
182{
183 return m_is_watch_variable;
184}
185
186void
187Watchpoint::SetWatchVariable(bool val)
188{
189 m_is_watch_variable = val;
190}
191
Johnny Chen0b093662012-08-14 20:56:37 +0000192void
193Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
194{
195 ++m_false_alarms;
196 if (m_false_alarms)
197 {
198 if (m_hit_count >= m_false_alarms)
199 {
200 m_hit_count -= m_false_alarms;
201 m_false_alarms = 0;
202 }
203 else
204 {
205 m_false_alarms -= m_hit_count;
206 m_hit_count = 0;
207 }
208 }
209}
210
Chris Lattner24943d22010-06-08 16:52:24 +0000211// RETURNS - true if we should stop at this breakpoint, false if we
212// should continue.
213
214bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000215Watchpoint::ShouldStop (StoppointCallbackContext *context)
Chris Lattner24943d22010-06-08 16:52:24 +0000216{
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000217 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000218
Johnny Chen01acfa72011-09-22 18:04:58 +0000219 if (!IsEnabled())
220 return false;
Johnny Chen043f8c22011-09-21 22:47:15 +0000221
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000222 if (GetHitCount() <= GetIgnoreCount())
Johnny Chen01acfa72011-09-22 18:04:58 +0000223 return false;
224
Johnny Chen712a6282011-10-17 18:58:00 +0000225 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000226}
227
228void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000229Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
Johnny Chen34bbf852011-09-12 23:38:44 +0000230{
Johnny Chen10b12b32011-09-16 21:41:42 +0000231 DumpWithLevel(s, level);
Johnny Chen34bbf852011-09-12 23:38:44 +0000232 return;
233}
234
235void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000236Watchpoint::Dump(Stream *s) const
Chris Lattner24943d22010-06-08 16:52:24 +0000237{
Johnny Chen10b12b32011-09-16 21:41:42 +0000238 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
239}
240
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000241// If prefix is NULL, we display the watch id and ignore the prefix altogether.
Johnny Chen10b12b32011-09-16 21:41:42 +0000242void
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000243Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
Johnny Chen9e985592012-08-13 21:09:54 +0000244{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000245 if (!prefix)
246 {
247 s->Printf("\nWatchpoint %u hit:", GetID());
248 prefix = "";
249 }
250
Johnny Chen9e985592012-08-13 21:09:54 +0000251 if (IsWatchVariable())
252 {
253 if (!m_snapshot_old_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000254 s->Printf("\n%sold value: %s", prefix, m_snapshot_old_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000255 if (!m_snapshot_new_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000256 s->Printf("\n%snew value: %s", prefix, m_snapshot_new_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000257 }
258 else
259 {
260 uint32_t num_hex_digits = GetByteSize() * 2;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000261 s->Printf("\n%sold value: 0x%0*.*llx", prefix, num_hex_digits, num_hex_digits, m_snapshot_old_val);
262 s->Printf("\n%snew value: 0x%0*.*llx", prefix, num_hex_digits, num_hex_digits, m_snapshot_new_val);
Johnny Chen9e985592012-08-13 21:09:54 +0000263 }
264}
265
266void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000267Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Johnny Chen10b12b32011-09-16 21:41:42 +0000268{
Chris Lattner24943d22010-06-08 16:52:24 +0000269 if (s == NULL)
270 return;
271
Johnny Chen10b12b32011-09-16 21:41:42 +0000272 assert(description_level >= lldb::eDescriptionLevelBrief &&
273 description_level <= lldb::eDescriptionLevelVerbose);
274
Greg Claytonbae39c52011-12-03 00:46:21 +0000275 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s",
Johnny Chen10b12b32011-09-16 21:41:42 +0000276 GetID(),
Johnny Chen1c2d9412012-01-24 00:11:02 +0000277 GetLoadAddress(),
Johnny Chen10b12b32011-09-16 21:41:42 +0000278 m_byte_size,
Johnny Chen116a5cd2012-02-25 06:44:30 +0000279 IsEnabled() ? "enabled" : "disabled",
Johnny Chen10b12b32011-09-16 21:41:42 +0000280 m_watch_read ? "r" : "",
281 m_watch_write ? "w" : "");
282
Johnny Chen712a6282011-10-17 18:58:00 +0000283 if (description_level >= lldb::eDescriptionLevelFull) {
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000284 if (!m_decl_str.empty())
Johnny Chen712a6282011-10-17 18:58:00 +0000285 s->Printf("\n declare @ '%s'", m_decl_str.c_str());
Johnny Chen116a5cd2012-02-25 06:44:30 +0000286 if (!m_watch_spec_str.empty())
Johnny Chen9e985592012-08-13 21:09:54 +0000287 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
288
289 // Dump the snapshots we have taken.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000290 DumpSnapshots(s, " ");
Johnny Chen9e985592012-08-13 21:09:54 +0000291
Johnny Chen712a6282011-10-17 18:58:00 +0000292 if (GetConditionText())
293 s->Printf("\n condition = '%s'", GetConditionText());
Johnny Chenf3ec4612012-08-09 23:09:42 +0000294 m_options.GetCallbackDescription(s, description_level);
Johnny Chen712a6282011-10-17 18:58:00 +0000295 }
Johnny Chen10b12b32011-09-16 21:41:42 +0000296
297 if (description_level >= lldb::eDescriptionLevelVerbose)
Jason Molendaa4a15872012-02-23 22:32:13 +0000298 {
Johnny Chenf3ec4612012-08-09 23:09:42 +0000299 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u",
300 GetHardwareIndex(),
301 GetHitCount(),
302 GetIgnoreCount());
Jason Molendaa4a15872012-02-23 22:32:13 +0000303 }
Chris Lattner24943d22010-06-08 16:52:24 +0000304}
305
306bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000307Watchpoint::IsEnabled() const
Chris Lattner24943d22010-06-08 16:52:24 +0000308{
309 return m_enabled;
310}
311
Johnny Chenf84e5662012-08-21 23:17:04 +0000312// Within StopInfo.cpp, we purposely turn on the ephemeral mode right before temporarily disable the watchpoint
313// in order to perform possible watchpoint actions without triggering further watchpoint events.
314// After the temporary disabled watchpoint is enabled, we then turn off the ephemeral mode.
315
316void
317Watchpoint::TurnOnEphemeralMode()
318{
319 m_is_ephemeral = true;
320}
321
322void
323Watchpoint::TurnOffEphemeralMode()
324{
325 m_is_ephemeral = false;
Johnny Chen258db3a2012-08-23 22:28:26 +0000326 // Leaving ephemeral mode, reset the m_disabled_count!
327 m_disabled_count = 0;
328}
329
330bool
331Watchpoint::IsDisabledDuringEphemeralMode()
332{
333 return m_disabled_count > 1;
Johnny Chenf84e5662012-08-21 23:17:04 +0000334}
335
Chris Lattner24943d22010-06-08 16:52:24 +0000336void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000337Watchpoint::SetEnabled(bool enabled)
Chris Lattner24943d22010-06-08 16:52:24 +0000338{
339 if (!enabled)
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000340 {
Johnny Chenf84e5662012-08-21 23:17:04 +0000341 if (!m_is_ephemeral)
342 SetHardwareIndex(LLDB_INVALID_INDEX32);
Johnny Chen258db3a2012-08-23 22:28:26 +0000343 else
344 ++m_disabled_count;
345
Johnny Chenbd446f12012-08-21 22:06:34 +0000346 // Don't clear the snapshots for now.
347 // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
348 //ClearSnapshots();
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000349 }
Chris Lattner24943d22010-06-08 16:52:24 +0000350 m_enabled = enabled;
351}
352
353void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000354Watchpoint::SetWatchpointType (uint32_t type)
Chris Lattner24943d22010-06-08 16:52:24 +0000355{
356 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
357 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
358}
359
360bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000361Watchpoint::WatchpointRead () const
Chris Lattner24943d22010-06-08 16:52:24 +0000362{
363 return m_watch_read != 0;
364}
365bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000366Watchpoint::WatchpointWrite () const
Chris Lattner24943d22010-06-08 16:52:24 +0000367{
368 return m_watch_write != 0;
369}
Greg Clayton54e7afa2010-07-09 20:39:50 +0000370uint32_t
Johnny Chenecd4feb2011-10-14 00:42:25 +0000371Watchpoint::GetIgnoreCount () const
Chris Lattner24943d22010-06-08 16:52:24 +0000372{
373 return m_ignore_count;
374}
375
376void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000377Watchpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000378{
379 m_ignore_count = n;
380}
Johnny Chen712a6282011-10-17 18:58:00 +0000381
382bool
383Watchpoint::InvokeCallback (StoppointCallbackContext *context)
384{
Johnny Chenf3ec4612012-08-09 23:09:42 +0000385 return m_options.InvokeCallback (context, GetID());
Johnny Chen712a6282011-10-17 18:58:00 +0000386}
387
388void
389Watchpoint::SetCondition (const char *condition)
390{
391 if (condition == NULL || condition[0] == '\0')
392 {
393 if (m_condition_ap.get())
394 m_condition_ap.reset();
395 }
396 else
397 {
398 // Pass NULL for expr_prefix (no translation-unit level definitions).
Sean Callanandaa6efe2011-12-21 22:22:58 +0000399 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
Johnny Chen712a6282011-10-17 18:58:00 +0000400 }
401}
402
403const char *
404Watchpoint::GetConditionText () const
405{
406 if (m_condition_ap.get())
407 return m_condition_ap->GetUserText();
408 else
409 return NULL;
410}
411