blob: d4c099be0c1fe2de856856c9de2ae86c2096048f [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 Chen9e985592012-08-13 21:09:54 +000098std::string
99Watchpoint::GetOldSnapshot() const
100{
101 return m_snapshot_old_str;
102}
103
104void
105Watchpoint::SetOldSnapshot (const std::string &str)
106{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000107 size_t len = str.length();
Johnny Chen9e985592012-08-13 21:09:54 +0000108 m_snapshot_old_str = str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000109 if (len && str.at(len - 1) == '\n')
110 m_snapshot_old_str.resize(len - 1);
Johnny Chen9e985592012-08-13 21:09:54 +0000111 return;
112}
113
114std::string
115Watchpoint::GetNewSnapshot() const
116{
117 return m_snapshot_new_str;
118}
119
120void
121Watchpoint::SetNewSnapshot (const std::string &str)
122{
123 m_snapshot_old_str = m_snapshot_new_str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000124 size_t len = str.length();
Johnny Chen9e985592012-08-13 21:09:54 +0000125 m_snapshot_new_str = str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000126 if (len && str.at(len - 1) == '\n')
127 m_snapshot_new_str.resize(len - 1);
Johnny Chen9e985592012-08-13 21:09:54 +0000128 return;
129}
130
131uint64_t
132Watchpoint::GetOldSnapshotVal() const
133{
134 return m_snapshot_old_val;
135}
136
137void
138Watchpoint::SetOldSnapshotVal (uint64_t val)
139{
140 m_snapshot_old_val = val;
141 return;
142}
143
144uint64_t
145Watchpoint::GetNewSnapshotVal() const
146{
147 return m_snapshot_new_val;
148}
149
150void
151Watchpoint::SetNewSnapshotVal (uint64_t val)
152{
153 m_snapshot_old_val = m_snapshot_new_val;
154 m_snapshot_new_val = val;
155 return;
156}
157
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000158void
159Watchpoint::ClearSnapshots()
160{
161 m_snapshot_old_str.clear();
162 m_snapshot_new_str.clear();
163 m_snapshot_old_val = 0;
164 m_snapshot_new_val = 0;
165}
166
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000167// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
168// member field is more accurate.
Johnny Chen01acfa72011-09-22 18:04:58 +0000169bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000170Watchpoint::IsHardware () const
Johnny Chen01acfa72011-09-22 18:04:58 +0000171{
172 return m_is_hardware;
173}
174
Johnny Chen9e985592012-08-13 21:09:54 +0000175bool
176Watchpoint::IsWatchVariable() const
177{
178 return m_is_watch_variable;
179}
180
181void
182Watchpoint::SetWatchVariable(bool val)
183{
184 m_is_watch_variable = val;
185}
186
Johnny Chen0b093662012-08-14 20:56:37 +0000187void
188Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
189{
190 ++m_false_alarms;
191 if (m_false_alarms)
192 {
193 if (m_hit_count >= m_false_alarms)
194 {
195 m_hit_count -= m_false_alarms;
196 m_false_alarms = 0;
197 }
198 else
199 {
200 m_false_alarms -= m_hit_count;
201 m_hit_count = 0;
202 }
203 }
204}
205
Chris Lattner24943d22010-06-08 16:52:24 +0000206// RETURNS - true if we should stop at this breakpoint, false if we
207// should continue.
208
209bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000210Watchpoint::ShouldStop (StoppointCallbackContext *context)
Chris Lattner24943d22010-06-08 16:52:24 +0000211{
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000212 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000213
Johnny Chen01acfa72011-09-22 18:04:58 +0000214 if (!IsEnabled())
215 return false;
Johnny Chen043f8c22011-09-21 22:47:15 +0000216
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000217 if (GetHitCount() <= GetIgnoreCount())
Johnny Chen01acfa72011-09-22 18:04:58 +0000218 return false;
219
Johnny Chen712a6282011-10-17 18:58:00 +0000220 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000221}
222
223void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000224Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
Johnny Chen34bbf852011-09-12 23:38:44 +0000225{
Johnny Chen10b12b32011-09-16 21:41:42 +0000226 DumpWithLevel(s, level);
Johnny Chen34bbf852011-09-12 23:38:44 +0000227 return;
228}
229
230void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000231Watchpoint::Dump(Stream *s) const
Chris Lattner24943d22010-06-08 16:52:24 +0000232{
Johnny Chen10b12b32011-09-16 21:41:42 +0000233 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
234}
235
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000236// If prefix is NULL, we display the watch id and ignore the prefix altogether.
Johnny Chen10b12b32011-09-16 21:41:42 +0000237void
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000238Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
Johnny Chen9e985592012-08-13 21:09:54 +0000239{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000240 if (!prefix)
241 {
242 s->Printf("\nWatchpoint %u hit:", GetID());
243 prefix = "";
244 }
245
Johnny Chen9e985592012-08-13 21:09:54 +0000246 if (IsWatchVariable())
247 {
248 if (!m_snapshot_old_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000249 s->Printf("\n%sold value: %s", prefix, m_snapshot_old_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000250 if (!m_snapshot_new_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000251 s->Printf("\n%snew value: %s", prefix, m_snapshot_new_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000252 }
253 else
254 {
255 uint32_t num_hex_digits = GetByteSize() * 2;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000256 s->Printf("\n%sold value: 0x%0*.*llx", prefix, num_hex_digits, num_hex_digits, m_snapshot_old_val);
257 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 +0000258 }
259}
260
261void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000262Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Johnny Chen10b12b32011-09-16 21:41:42 +0000263{
Chris Lattner24943d22010-06-08 16:52:24 +0000264 if (s == NULL)
265 return;
266
Johnny Chen10b12b32011-09-16 21:41:42 +0000267 assert(description_level >= lldb::eDescriptionLevelBrief &&
268 description_level <= lldb::eDescriptionLevelVerbose);
269
Greg Claytonbae39c52011-12-03 00:46:21 +0000270 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s",
Johnny Chen10b12b32011-09-16 21:41:42 +0000271 GetID(),
Johnny Chen1c2d9412012-01-24 00:11:02 +0000272 GetLoadAddress(),
Johnny Chen10b12b32011-09-16 21:41:42 +0000273 m_byte_size,
Johnny Chen116a5cd2012-02-25 06:44:30 +0000274 IsEnabled() ? "enabled" : "disabled",
Johnny Chen10b12b32011-09-16 21:41:42 +0000275 m_watch_read ? "r" : "",
276 m_watch_write ? "w" : "");
277
Johnny Chen712a6282011-10-17 18:58:00 +0000278 if (description_level >= lldb::eDescriptionLevelFull) {
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000279 if (!m_decl_str.empty())
Johnny Chen712a6282011-10-17 18:58:00 +0000280 s->Printf("\n declare @ '%s'", m_decl_str.c_str());
Johnny Chen116a5cd2012-02-25 06:44:30 +0000281 if (!m_watch_spec_str.empty())
Johnny Chen9e985592012-08-13 21:09:54 +0000282 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
283
284 // Dump the snapshots we have taken.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000285 DumpSnapshots(s, " ");
Johnny Chen9e985592012-08-13 21:09:54 +0000286
Johnny Chen712a6282011-10-17 18:58:00 +0000287 if (GetConditionText())
288 s->Printf("\n condition = '%s'", GetConditionText());
Johnny Chenf3ec4612012-08-09 23:09:42 +0000289 m_options.GetCallbackDescription(s, description_level);
Johnny Chen712a6282011-10-17 18:58:00 +0000290 }
Johnny Chen10b12b32011-09-16 21:41:42 +0000291
292 if (description_level >= lldb::eDescriptionLevelVerbose)
Jason Molendaa4a15872012-02-23 22:32:13 +0000293 {
Johnny Chenf3ec4612012-08-09 23:09:42 +0000294 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u",
295 GetHardwareIndex(),
296 GetHitCount(),
297 GetIgnoreCount());
Jason Molendaa4a15872012-02-23 22:32:13 +0000298 }
Chris Lattner24943d22010-06-08 16:52:24 +0000299}
300
301bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000302Watchpoint::IsEnabled() const
Chris Lattner24943d22010-06-08 16:52:24 +0000303{
304 return m_enabled;
305}
306
307void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000308Watchpoint::SetEnabled(bool enabled)
Chris Lattner24943d22010-06-08 16:52:24 +0000309{
310 if (!enabled)
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000311 {
Chris Lattner24943d22010-06-08 16:52:24 +0000312 SetHardwareIndex(LLDB_INVALID_INDEX32);
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000313 ClearSnapshots();
314 }
Chris Lattner24943d22010-06-08 16:52:24 +0000315 m_enabled = enabled;
316}
317
318void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000319Watchpoint::SetWatchpointType (uint32_t type)
Chris Lattner24943d22010-06-08 16:52:24 +0000320{
321 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
322 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
323}
324
325bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000326Watchpoint::WatchpointRead () const
Chris Lattner24943d22010-06-08 16:52:24 +0000327{
328 return m_watch_read != 0;
329}
330bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000331Watchpoint::WatchpointWrite () const
Chris Lattner24943d22010-06-08 16:52:24 +0000332{
333 return m_watch_write != 0;
334}
Greg Clayton54e7afa2010-07-09 20:39:50 +0000335uint32_t
Johnny Chenecd4feb2011-10-14 00:42:25 +0000336Watchpoint::GetIgnoreCount () const
Chris Lattner24943d22010-06-08 16:52:24 +0000337{
338 return m_ignore_count;
339}
340
341void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000342Watchpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000343{
344 m_ignore_count = n;
345}
Johnny Chen712a6282011-10-17 18:58:00 +0000346
347bool
348Watchpoint::InvokeCallback (StoppointCallbackContext *context)
349{
Johnny Chenf3ec4612012-08-09 23:09:42 +0000350 return m_options.InvokeCallback (context, GetID());
Johnny Chen712a6282011-10-17 18:58:00 +0000351}
352
353void
354Watchpoint::SetCondition (const char *condition)
355{
356 if (condition == NULL || condition[0] == '\0')
357 {
358 if (m_condition_ap.get())
359 m_condition_ap.reset();
360 }
361 else
362 {
363 // Pass NULL for expr_prefix (no translation-unit level definitions).
Sean Callanandaa6efe2011-12-21 22:22:58 +0000364 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
Johnny Chen712a6282011-10-17 18:58:00 +0000365 }
366}
367
368const char *
369Watchpoint::GetConditionText () const
370{
371 if (m_condition_ap.get())
372 return m_condition_ap->GetUserText();
373 else
374 return NULL;
375}
376