blob: a9fe4ee4a22fbdfef76f679fe5437327ac9add97 [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),
Chris Lattner24943d22010-06-08 16:52:24 +000032 m_watch_read(0),
33 m_watch_write(0),
34 m_watch_was_read(0),
35 m_watch_was_written(0),
36 m_ignore_count(0),
Johnny Chen0b093662012-08-14 20:56:37 +000037 m_false_alarms(0),
Johnny Chen41a55ef2011-10-14 19:15:48 +000038 m_decl_str(),
Johnny Chen116a5cd2012-02-25 06:44:30 +000039 m_watch_spec_str(),
Johnny Chen9e985592012-08-13 21:09:54 +000040 m_snapshot_old_str(),
41 m_snapshot_new_str(),
42 m_snapshot_old_val(0),
43 m_snapshot_new_val(0),
Johnny Chenf3ec4612012-08-09 23:09:42 +000044 m_error(),
45 m_options ()
Chris Lattner24943d22010-06-08 16:52:24 +000046{
47}
48
Johnny Chenecd4feb2011-10-14 00:42:25 +000049Watchpoint::~Watchpoint()
Chris Lattner24943d22010-06-08 16:52:24 +000050{
51}
52
Johnny Chenf3ec4612012-08-09 23:09:42 +000053// This function is used when "baton" doesn't need to be freed
54void
55Watchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
Chris Lattner24943d22010-06-08 16:52:24 +000056{
Johnny Chenf3ec4612012-08-09 23:09:42 +000057 // The default "Baton" class will keep a copy of "baton" and won't free
58 // or delete it when it goes goes out of scope.
59 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
60
61 //SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
62}
63
64// This function is used when a baton needs to be freed and therefore is
65// contained in a "Baton" subclass.
66void
67Watchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
68{
69 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
70}
71
72void
73Watchpoint::ClearCallback ()
74{
75 m_options.ClearCallback ();
Chris Lattner24943d22010-06-08 16:52:24 +000076}
77
Johnny Chen10b12b32011-09-16 21:41:42 +000078void
Johnny Chen9e985592012-08-13 21:09:54 +000079Watchpoint::SetDeclInfo (const std::string &str)
Johnny Chen10b12b32011-09-16 21:41:42 +000080{
81 m_decl_str = str;
82 return;
83}
84
Johnny Chen9e985592012-08-13 21:09:54 +000085std::string
86Watchpoint::GetWatchSpec()
87{
88 return m_watch_spec_str;
89}
90
Johnny Chen116a5cd2012-02-25 06:44:30 +000091void
Johnny Chen9e985592012-08-13 21:09:54 +000092Watchpoint::SetWatchSpec (const std::string &str)
Johnny Chen116a5cd2012-02-25 06:44:30 +000093{
94 m_watch_spec_str = str;
95 return;
96}
97
Johnny Chen519274f2012-08-14 23:09:48 +000098// Strip at most one character from the end of the string.
99static inline std::string
100RStripOnce(const std::string &str, const char c)
101{
102 std::string res = str;
103 size_t len = res.length();
104 if (len && res.at(len - 1) == '\n')
105 res.resize(len - 1);
106 return res;
107}
108
Johnny Chen9e985592012-08-13 21:09:54 +0000109std::string
110Watchpoint::GetOldSnapshot() const
111{
112 return m_snapshot_old_str;
113}
114
115void
116Watchpoint::SetOldSnapshot (const std::string &str)
117{
Johnny Chen519274f2012-08-14 23:09:48 +0000118 m_snapshot_old_str = RStripOnce(str, '\n');
Johnny Chen9e985592012-08-13 21:09:54 +0000119}
120
121std::string
122Watchpoint::GetNewSnapshot() const
123{
124 return m_snapshot_new_str;
125}
126
127void
128Watchpoint::SetNewSnapshot (const std::string &str)
129{
130 m_snapshot_old_str = m_snapshot_new_str;
Johnny Chen519274f2012-08-14 23:09:48 +0000131 m_snapshot_new_str = RStripOnce(str, '\n');
Johnny Chen9e985592012-08-13 21:09:54 +0000132}
133
134uint64_t
135Watchpoint::GetOldSnapshotVal() const
136{
137 return m_snapshot_old_val;
138}
139
140void
141Watchpoint::SetOldSnapshotVal (uint64_t val)
142{
143 m_snapshot_old_val = val;
144 return;
145}
146
147uint64_t
148Watchpoint::GetNewSnapshotVal() const
149{
150 return m_snapshot_new_val;
151}
152
153void
154Watchpoint::SetNewSnapshotVal (uint64_t val)
155{
156 m_snapshot_old_val = m_snapshot_new_val;
157 m_snapshot_new_val = val;
158 return;
159}
160
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000161void
162Watchpoint::ClearSnapshots()
163{
164 m_snapshot_old_str.clear();
165 m_snapshot_new_str.clear();
166 m_snapshot_old_val = 0;
167 m_snapshot_new_val = 0;
168}
169
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000170// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
171// member field is more accurate.
Johnny Chen01acfa72011-09-22 18:04:58 +0000172bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000173Watchpoint::IsHardware () const
Johnny Chen01acfa72011-09-22 18:04:58 +0000174{
175 return m_is_hardware;
176}
177
Johnny Chen9e985592012-08-13 21:09:54 +0000178bool
179Watchpoint::IsWatchVariable() const
180{
181 return m_is_watch_variable;
182}
183
184void
185Watchpoint::SetWatchVariable(bool val)
186{
187 m_is_watch_variable = val;
188}
189
Johnny Chen0b093662012-08-14 20:56:37 +0000190void
191Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
192{
193 ++m_false_alarms;
194 if (m_false_alarms)
195 {
196 if (m_hit_count >= m_false_alarms)
197 {
198 m_hit_count -= m_false_alarms;
199 m_false_alarms = 0;
200 }
201 else
202 {
203 m_false_alarms -= m_hit_count;
204 m_hit_count = 0;
205 }
206 }
207}
208
Chris Lattner24943d22010-06-08 16:52:24 +0000209// RETURNS - true if we should stop at this breakpoint, false if we
210// should continue.
211
212bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000213Watchpoint::ShouldStop (StoppointCallbackContext *context)
Chris Lattner24943d22010-06-08 16:52:24 +0000214{
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000215 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000216
Johnny Chen01acfa72011-09-22 18:04:58 +0000217 if (!IsEnabled())
218 return false;
Johnny Chen043f8c22011-09-21 22:47:15 +0000219
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000220 if (GetHitCount() <= GetIgnoreCount())
Johnny Chen01acfa72011-09-22 18:04:58 +0000221 return false;
222
Johnny Chen712a6282011-10-17 18:58:00 +0000223 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000224}
225
226void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000227Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
Johnny Chen34bbf852011-09-12 23:38:44 +0000228{
Johnny Chen10b12b32011-09-16 21:41:42 +0000229 DumpWithLevel(s, level);
Johnny Chen34bbf852011-09-12 23:38:44 +0000230 return;
231}
232
233void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000234Watchpoint::Dump(Stream *s) const
Chris Lattner24943d22010-06-08 16:52:24 +0000235{
Johnny Chen10b12b32011-09-16 21:41:42 +0000236 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
237}
238
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000239// If prefix is NULL, we display the watch id and ignore the prefix altogether.
Johnny Chen10b12b32011-09-16 21:41:42 +0000240void
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000241Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
Johnny Chen9e985592012-08-13 21:09:54 +0000242{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000243 if (!prefix)
244 {
245 s->Printf("\nWatchpoint %u hit:", GetID());
246 prefix = "";
247 }
248
Johnny Chen9e985592012-08-13 21:09:54 +0000249 if (IsWatchVariable())
250 {
251 if (!m_snapshot_old_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000252 s->Printf("\n%sold value: %s", prefix, m_snapshot_old_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000253 if (!m_snapshot_new_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000254 s->Printf("\n%snew value: %s", prefix, m_snapshot_new_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000255 }
256 else
257 {
258 uint32_t num_hex_digits = GetByteSize() * 2;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000259 s->Printf("\n%sold value: 0x%0*.*llx", prefix, num_hex_digits, num_hex_digits, m_snapshot_old_val);
260 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 +0000261 }
262}
263
264void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000265Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Johnny Chen10b12b32011-09-16 21:41:42 +0000266{
Chris Lattner24943d22010-06-08 16:52:24 +0000267 if (s == NULL)
268 return;
269
Johnny Chen10b12b32011-09-16 21:41:42 +0000270 assert(description_level >= lldb::eDescriptionLevelBrief &&
271 description_level <= lldb::eDescriptionLevelVerbose);
272
Greg Claytonbae39c52011-12-03 00:46:21 +0000273 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s",
Johnny Chen10b12b32011-09-16 21:41:42 +0000274 GetID(),
Johnny Chen1c2d9412012-01-24 00:11:02 +0000275 GetLoadAddress(),
Johnny Chen10b12b32011-09-16 21:41:42 +0000276 m_byte_size,
Johnny Chen116a5cd2012-02-25 06:44:30 +0000277 IsEnabled() ? "enabled" : "disabled",
Johnny Chen10b12b32011-09-16 21:41:42 +0000278 m_watch_read ? "r" : "",
279 m_watch_write ? "w" : "");
280
Johnny Chen712a6282011-10-17 18:58:00 +0000281 if (description_level >= lldb::eDescriptionLevelFull) {
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000282 if (!m_decl_str.empty())
Johnny Chen712a6282011-10-17 18:58:00 +0000283 s->Printf("\n declare @ '%s'", m_decl_str.c_str());
Johnny Chen116a5cd2012-02-25 06:44:30 +0000284 if (!m_watch_spec_str.empty())
Johnny Chen9e985592012-08-13 21:09:54 +0000285 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
286
287 // Dump the snapshots we have taken.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000288 DumpSnapshots(s, " ");
Johnny Chen9e985592012-08-13 21:09:54 +0000289
Johnny Chen712a6282011-10-17 18:58:00 +0000290 if (GetConditionText())
291 s->Printf("\n condition = '%s'", GetConditionText());
Johnny Chenf3ec4612012-08-09 23:09:42 +0000292 m_options.GetCallbackDescription(s, description_level);
Johnny Chen712a6282011-10-17 18:58:00 +0000293 }
Johnny Chen10b12b32011-09-16 21:41:42 +0000294
295 if (description_level >= lldb::eDescriptionLevelVerbose)
Jason Molendaa4a15872012-02-23 22:32:13 +0000296 {
Johnny Chenf3ec4612012-08-09 23:09:42 +0000297 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u",
298 GetHardwareIndex(),
299 GetHitCount(),
300 GetIgnoreCount());
Jason Molendaa4a15872012-02-23 22:32:13 +0000301 }
Chris Lattner24943d22010-06-08 16:52:24 +0000302}
303
304bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000305Watchpoint::IsEnabled() const
Chris Lattner24943d22010-06-08 16:52:24 +0000306{
307 return m_enabled;
308}
309
310void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000311Watchpoint::SetEnabled(bool enabled)
Chris Lattner24943d22010-06-08 16:52:24 +0000312{
313 if (!enabled)
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000314 {
Chris Lattner24943d22010-06-08 16:52:24 +0000315 SetHardwareIndex(LLDB_INVALID_INDEX32);
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000316 ClearSnapshots();
317 }
Chris Lattner24943d22010-06-08 16:52:24 +0000318 m_enabled = enabled;
319}
320
321void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000322Watchpoint::SetWatchpointType (uint32_t type)
Chris Lattner24943d22010-06-08 16:52:24 +0000323{
324 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
325 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
326}
327
328bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000329Watchpoint::WatchpointRead () const
Chris Lattner24943d22010-06-08 16:52:24 +0000330{
331 return m_watch_read != 0;
332}
333bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000334Watchpoint::WatchpointWrite () const
Chris Lattner24943d22010-06-08 16:52:24 +0000335{
336 return m_watch_write != 0;
337}
Greg Clayton54e7afa2010-07-09 20:39:50 +0000338uint32_t
Johnny Chenecd4feb2011-10-14 00:42:25 +0000339Watchpoint::GetIgnoreCount () const
Chris Lattner24943d22010-06-08 16:52:24 +0000340{
341 return m_ignore_count;
342}
343
344void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000345Watchpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000346{
347 m_ignore_count = n;
348}
Johnny Chen712a6282011-10-17 18:58:00 +0000349
350bool
351Watchpoint::InvokeCallback (StoppointCallbackContext *context)
352{
Johnny Chenf3ec4612012-08-09 23:09:42 +0000353 return m_options.InvokeCallback (context, GetID());
Johnny Chen712a6282011-10-17 18:58:00 +0000354}
355
356void
357Watchpoint::SetCondition (const char *condition)
358{
359 if (condition == NULL || condition[0] == '\0')
360 {
361 if (m_condition_ap.get())
362 m_condition_ap.reset();
363 }
364 else
365 {
366 // Pass NULL for expr_prefix (no translation-unit level definitions).
Sean Callanandaa6efe2011-12-21 22:22:58 +0000367 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
Johnny Chen712a6282011-10-17 18:58:00 +0000368 }
369}
370
371const char *
372Watchpoint::GetConditionText () const
373{
374 if (m_condition_ap.get())
375 return m_condition_ap->GetUserText();
376 else
377 return NULL;
378}
379