blob: 6ba2f9c89f4b850d48448e0416b583f2a6909754 [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 Chen41a55ef2011-10-14 19:15:48 +000037 m_decl_str(),
Johnny Chen116a5cd2012-02-25 06:44:30 +000038 m_watch_spec_str(),
Johnny Chen9e985592012-08-13 21:09:54 +000039 m_snapshot_old_str(),
40 m_snapshot_new_str(),
41 m_snapshot_old_val(0),
42 m_snapshot_new_val(0),
Johnny Chenf3ec4612012-08-09 23:09:42 +000043 m_error(),
44 m_options ()
Chris Lattner24943d22010-06-08 16:52:24 +000045{
46}
47
Johnny Chenecd4feb2011-10-14 00:42:25 +000048Watchpoint::~Watchpoint()
Chris Lattner24943d22010-06-08 16:52:24 +000049{
50}
51
Johnny Chenf3ec4612012-08-09 23:09:42 +000052// This function is used when "baton" doesn't need to be freed
53void
54Watchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
Chris Lattner24943d22010-06-08 16:52:24 +000055{
Johnny Chenf3ec4612012-08-09 23:09:42 +000056 // The default "Baton" class will keep a copy of "baton" and won't free
57 // or delete it when it goes goes out of scope.
58 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
59
60 //SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
61}
62
63// This function is used when a baton needs to be freed and therefore is
64// contained in a "Baton" subclass.
65void
66Watchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
67{
68 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
69}
70
71void
72Watchpoint::ClearCallback ()
73{
74 m_options.ClearCallback ();
Chris Lattner24943d22010-06-08 16:52:24 +000075}
76
Johnny Chen10b12b32011-09-16 21:41:42 +000077void
Johnny Chen9e985592012-08-13 21:09:54 +000078Watchpoint::SetDeclInfo (const std::string &str)
Johnny Chen10b12b32011-09-16 21:41:42 +000079{
80 m_decl_str = str;
81 return;
82}
83
Johnny Chen9e985592012-08-13 21:09:54 +000084std::string
85Watchpoint::GetWatchSpec()
86{
87 return m_watch_spec_str;
88}
89
Johnny Chen116a5cd2012-02-25 06:44:30 +000090void
Johnny Chen9e985592012-08-13 21:09:54 +000091Watchpoint::SetWatchSpec (const std::string &str)
Johnny Chen116a5cd2012-02-25 06:44:30 +000092{
93 m_watch_spec_str = str;
94 return;
95}
96
Johnny Chen9e985592012-08-13 21:09:54 +000097std::string
98Watchpoint::GetOldSnapshot() const
99{
100 return m_snapshot_old_str;
101}
102
103void
104Watchpoint::SetOldSnapshot (const std::string &str)
105{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000106 size_t len = str.length();
Johnny Chen9e985592012-08-13 21:09:54 +0000107 m_snapshot_old_str = str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000108 if (len && str.at(len - 1) == '\n')
109 m_snapshot_old_str.resize(len - 1);
Johnny Chen9e985592012-08-13 21:09:54 +0000110 return;
111}
112
113std::string
114Watchpoint::GetNewSnapshot() const
115{
116 return m_snapshot_new_str;
117}
118
119void
120Watchpoint::SetNewSnapshot (const std::string &str)
121{
122 m_snapshot_old_str = m_snapshot_new_str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000123 size_t len = str.length();
Johnny Chen9e985592012-08-13 21:09:54 +0000124 m_snapshot_new_str = str;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000125 if (len && str.at(len - 1) == '\n')
126 m_snapshot_new_str.resize(len - 1);
Johnny Chen9e985592012-08-13 21:09:54 +0000127 return;
128}
129
130uint64_t
131Watchpoint::GetOldSnapshotVal() const
132{
133 return m_snapshot_old_val;
134}
135
136void
137Watchpoint::SetOldSnapshotVal (uint64_t val)
138{
139 m_snapshot_old_val = val;
140 return;
141}
142
143uint64_t
144Watchpoint::GetNewSnapshotVal() const
145{
146 return m_snapshot_new_val;
147}
148
149void
150Watchpoint::SetNewSnapshotVal (uint64_t val)
151{
152 m_snapshot_old_val = m_snapshot_new_val;
153 m_snapshot_new_val = val;
154 return;
155}
156
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000157void
158Watchpoint::ClearSnapshots()
159{
160 m_snapshot_old_str.clear();
161 m_snapshot_new_str.clear();
162 m_snapshot_old_val = 0;
163 m_snapshot_new_val = 0;
164}
165
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000166// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
167// member field is more accurate.
Johnny Chen01acfa72011-09-22 18:04:58 +0000168bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000169Watchpoint::IsHardware () const
Johnny Chen01acfa72011-09-22 18:04:58 +0000170{
171 return m_is_hardware;
172}
173
Johnny Chen9e985592012-08-13 21:09:54 +0000174bool
175Watchpoint::IsWatchVariable() const
176{
177 return m_is_watch_variable;
178}
179
180void
181Watchpoint::SetWatchVariable(bool val)
182{
183 m_is_watch_variable = val;
184}
185
Chris Lattner24943d22010-06-08 16:52:24 +0000186// RETURNS - true if we should stop at this breakpoint, false if we
187// should continue.
188
189bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000190Watchpoint::ShouldStop (StoppointCallbackContext *context)
Chris Lattner24943d22010-06-08 16:52:24 +0000191{
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000192 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000193
Johnny Chen01acfa72011-09-22 18:04:58 +0000194 if (!IsEnabled())
195 return false;
Johnny Chen043f8c22011-09-21 22:47:15 +0000196
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000197 if (GetHitCount() <= GetIgnoreCount())
Johnny Chen01acfa72011-09-22 18:04:58 +0000198 return false;
199
Johnny Chen712a6282011-10-17 18:58:00 +0000200 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000201}
202
203void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000204Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
Johnny Chen34bbf852011-09-12 23:38:44 +0000205{
Johnny Chen10b12b32011-09-16 21:41:42 +0000206 DumpWithLevel(s, level);
Johnny Chen34bbf852011-09-12 23:38:44 +0000207 return;
208}
209
210void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000211Watchpoint::Dump(Stream *s) const
Chris Lattner24943d22010-06-08 16:52:24 +0000212{
Johnny Chen10b12b32011-09-16 21:41:42 +0000213 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
214}
215
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000216// If prefix is NULL, we display the watch id and ignore the prefix altogether.
Johnny Chen10b12b32011-09-16 21:41:42 +0000217void
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000218Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
Johnny Chen9e985592012-08-13 21:09:54 +0000219{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000220 if (!prefix)
221 {
222 s->Printf("\nWatchpoint %u hit:", GetID());
223 prefix = "";
224 }
225
Johnny Chen9e985592012-08-13 21:09:54 +0000226 if (IsWatchVariable())
227 {
228 if (!m_snapshot_old_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000229 s->Printf("\n%sold value: %s", prefix, m_snapshot_old_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000230 if (!m_snapshot_new_str.empty())
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000231 s->Printf("\n%snew value: %s", prefix, m_snapshot_new_str.c_str());
Johnny Chen9e985592012-08-13 21:09:54 +0000232 }
233 else
234 {
235 uint32_t num_hex_digits = GetByteSize() * 2;
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000236 s->Printf("\n%sold value: 0x%0*.*llx", prefix, num_hex_digits, num_hex_digits, m_snapshot_old_val);
237 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 +0000238 }
239}
240
241void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000242Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Johnny Chen10b12b32011-09-16 21:41:42 +0000243{
Chris Lattner24943d22010-06-08 16:52:24 +0000244 if (s == NULL)
245 return;
246
Johnny Chen10b12b32011-09-16 21:41:42 +0000247 assert(description_level >= lldb::eDescriptionLevelBrief &&
248 description_level <= lldb::eDescriptionLevelVerbose);
249
Greg Claytonbae39c52011-12-03 00:46:21 +0000250 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s",
Johnny Chen10b12b32011-09-16 21:41:42 +0000251 GetID(),
Johnny Chen1c2d9412012-01-24 00:11:02 +0000252 GetLoadAddress(),
Johnny Chen10b12b32011-09-16 21:41:42 +0000253 m_byte_size,
Johnny Chen116a5cd2012-02-25 06:44:30 +0000254 IsEnabled() ? "enabled" : "disabled",
Johnny Chen10b12b32011-09-16 21:41:42 +0000255 m_watch_read ? "r" : "",
256 m_watch_write ? "w" : "");
257
Johnny Chen712a6282011-10-17 18:58:00 +0000258 if (description_level >= lldb::eDescriptionLevelFull) {
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000259 if (!m_decl_str.empty())
Johnny Chen712a6282011-10-17 18:58:00 +0000260 s->Printf("\n declare @ '%s'", m_decl_str.c_str());
Johnny Chen116a5cd2012-02-25 06:44:30 +0000261 if (!m_watch_spec_str.empty())
Johnny Chen9e985592012-08-13 21:09:54 +0000262 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
263
264 // Dump the snapshots we have taken.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000265 DumpSnapshots(s, " ");
Johnny Chen9e985592012-08-13 21:09:54 +0000266
Johnny Chen712a6282011-10-17 18:58:00 +0000267 if (GetConditionText())
268 s->Printf("\n condition = '%s'", GetConditionText());
Johnny Chenf3ec4612012-08-09 23:09:42 +0000269 m_options.GetCallbackDescription(s, description_level);
Johnny Chen712a6282011-10-17 18:58:00 +0000270 }
Johnny Chen10b12b32011-09-16 21:41:42 +0000271
272 if (description_level >= lldb::eDescriptionLevelVerbose)
Jason Molendaa4a15872012-02-23 22:32:13 +0000273 {
Johnny Chenf3ec4612012-08-09 23:09:42 +0000274 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u",
275 GetHardwareIndex(),
276 GetHitCount(),
277 GetIgnoreCount());
Jason Molendaa4a15872012-02-23 22:32:13 +0000278 }
Chris Lattner24943d22010-06-08 16:52:24 +0000279}
280
281bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000282Watchpoint::IsEnabled() const
Chris Lattner24943d22010-06-08 16:52:24 +0000283{
284 return m_enabled;
285}
286
287void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000288Watchpoint::SetEnabled(bool enabled)
Chris Lattner24943d22010-06-08 16:52:24 +0000289{
290 if (!enabled)
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000291 {
Chris Lattner24943d22010-06-08 16:52:24 +0000292 SetHardwareIndex(LLDB_INVALID_INDEX32);
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000293 ClearSnapshots();
294 }
Chris Lattner24943d22010-06-08 16:52:24 +0000295 m_enabled = enabled;
296}
297
298void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000299Watchpoint::SetWatchpointType (uint32_t type)
Chris Lattner24943d22010-06-08 16:52:24 +0000300{
301 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
302 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
303}
304
305bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000306Watchpoint::WatchpointRead () const
Chris Lattner24943d22010-06-08 16:52:24 +0000307{
308 return m_watch_read != 0;
309}
310bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000311Watchpoint::WatchpointWrite () const
Chris Lattner24943d22010-06-08 16:52:24 +0000312{
313 return m_watch_write != 0;
314}
Greg Clayton54e7afa2010-07-09 20:39:50 +0000315uint32_t
Johnny Chenecd4feb2011-10-14 00:42:25 +0000316Watchpoint::GetIgnoreCount () const
Chris Lattner24943d22010-06-08 16:52:24 +0000317{
318 return m_ignore_count;
319}
320
321void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000322Watchpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000323{
324 m_ignore_count = n;
325}
Johnny Chen712a6282011-10-17 18:58:00 +0000326
327bool
328Watchpoint::InvokeCallback (StoppointCallbackContext *context)
329{
Johnny Chenf3ec4612012-08-09 23:09:42 +0000330 return m_options.InvokeCallback (context, GetID());
Johnny Chen712a6282011-10-17 18:58:00 +0000331}
332
333void
334Watchpoint::SetCondition (const char *condition)
335{
336 if (condition == NULL || condition[0] == '\0')
337 {
338 if (m_condition_ap.get())
339 m_condition_ap.reset();
340 }
341 else
342 {
343 // Pass NULL for expr_prefix (no translation-unit level definitions).
Sean Callanandaa6efe2011-12-21 22:22:58 +0000344 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
Johnny Chen712a6282011-10-17 18:58:00 +0000345 }
346}
347
348const char *
349Watchpoint::GetConditionText () const
350{
351 if (m_condition_ap.get())
352 return m_condition_ap->GetUserText();
353 else
354 return NULL;
355}
356