blob: 4aadb9515ffdae323aa359f89b0cdf336a7ce38c [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"
Jim Ingham9e376622012-10-23 07:20:06 +000018#include "lldb/Core/Value.h"
19#include "lldb/Core/ValueObject.h"
20#include "lldb/Core/ValueObjectMemory.h"
21#include "lldb/Symbol/ClangASTContext.h"
Johnny Chen712a6282011-10-17 18:58:00 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/ThreadSpec.h"
Jim Ingham14f17cf2012-05-02 00:30:53 +000025#include "lldb/Expression/ClangUserExpression.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026
27using namespace lldb;
28using namespace lldb_private;
29
Jim Ingham9e376622012-10-23 07:20:06 +000030Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, size_t size, const ClangASTType *type, bool hardware) :
Johnny Chen116a5cd2012-02-25 06:44:30 +000031 StoppointLocation (0, addr, size, hardware),
Jim Ingham9e376622012-10-23 07:20:06 +000032 m_target(target),
Johnny Chen116a5cd2012-02-25 06:44:30 +000033 m_enabled(false),
Johnny Chen01acfa72011-09-22 18:04:58 +000034 m_is_hardware(hardware),
Johnny Chen9e985592012-08-13 21:09:54 +000035 m_is_watch_variable(false),
Johnny Chenf84e5662012-08-21 23:17:04 +000036 m_is_ephemeral(false),
Johnny Chen258db3a2012-08-23 22:28:26 +000037 m_disabled_count(0),
Chris Lattner24943d22010-06-08 16:52:24 +000038 m_watch_read(0),
39 m_watch_write(0),
40 m_watch_was_read(0),
41 m_watch_was_written(0),
42 m_ignore_count(0),
Johnny Chen0b093662012-08-14 20:56:37 +000043 m_false_alarms(0),
Johnny Chen41a55ef2011-10-14 19:15:48 +000044 m_decl_str(),
Johnny Chen116a5cd2012-02-25 06:44:30 +000045 m_watch_spec_str(),
Jim Ingham9e376622012-10-23 07:20:06 +000046 m_type(),
Johnny Chenf3ec4612012-08-09 23:09:42 +000047 m_error(),
48 m_options ()
Chris Lattner24943d22010-06-08 16:52:24 +000049{
Jim Ingham9e376622012-10-23 07:20:06 +000050 if (type && type->IsValid())
51 m_type = *type;
52 else
53 {
54 // If we don't have a known type, then we force it to unsigned int of the right size.
55 ClangASTContext *ast_context = target.GetScratchClangASTContext();
Jim Inghamed2b62a2012-10-23 21:09:09 +000056 clang_type_t clang_type = ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
Jim Ingham9e376622012-10-23 07:20:06 +000057 m_type.SetClangType(ast_context->getASTContext(), clang_type);
58 }
59
60 // Set the initial value of the watched variable:
61 if (m_target.GetProcessSP())
62 {
63 ExecutionContext exe_ctx;
64 m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx);
65 CaptureWatchedValue (exe_ctx);
66 }
Chris Lattner24943d22010-06-08 16:52:24 +000067}
68
Johnny Chenecd4feb2011-10-14 00:42:25 +000069Watchpoint::~Watchpoint()
Chris Lattner24943d22010-06-08 16:52:24 +000070{
71}
72
Johnny Chenf3ec4612012-08-09 23:09:42 +000073// This function is used when "baton" doesn't need to be freed
74void
75Watchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
Chris Lattner24943d22010-06-08 16:52:24 +000076{
Johnny Chenf3ec4612012-08-09 23:09:42 +000077 // The default "Baton" class will keep a copy of "baton" and won't free
78 // or delete it when it goes goes out of scope.
79 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
80
81 //SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
82}
83
84// This function is used when a baton needs to be freed and therefore is
85// contained in a "Baton" subclass.
86void
87Watchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
88{
89 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
90}
91
92void
93Watchpoint::ClearCallback ()
94{
95 m_options.ClearCallback ();
Chris Lattner24943d22010-06-08 16:52:24 +000096}
97
Johnny Chen10b12b32011-09-16 21:41:42 +000098void
Johnny Chen9e985592012-08-13 21:09:54 +000099Watchpoint::SetDeclInfo (const std::string &str)
Johnny Chen10b12b32011-09-16 21:41:42 +0000100{
101 m_decl_str = str;
102 return;
103}
104
Johnny Chen9e985592012-08-13 21:09:54 +0000105std::string
106Watchpoint::GetWatchSpec()
107{
108 return m_watch_spec_str;
109}
110
Johnny Chen116a5cd2012-02-25 06:44:30 +0000111void
Johnny Chen9e985592012-08-13 21:09:54 +0000112Watchpoint::SetWatchSpec (const std::string &str)
Johnny Chen116a5cd2012-02-25 06:44:30 +0000113{
114 m_watch_spec_str = str;
115 return;
116}
117
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000118// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
119// member field is more accurate.
Johnny Chen01acfa72011-09-22 18:04:58 +0000120bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000121Watchpoint::IsHardware () const
Johnny Chen01acfa72011-09-22 18:04:58 +0000122{
123 return m_is_hardware;
124}
125
Johnny Chen9e985592012-08-13 21:09:54 +0000126bool
127Watchpoint::IsWatchVariable() const
128{
129 return m_is_watch_variable;
130}
131
132void
133Watchpoint::SetWatchVariable(bool val)
134{
135 m_is_watch_variable = val;
136}
137
Jim Ingham9e376622012-10-23 07:20:06 +0000138bool
139Watchpoint::CaptureWatchedValue (const ExecutionContext &exe_ctx)
140{
141 ConstString watch_name("$__lldb__watch_value");
142 m_old_value_sp = m_new_value_sp;
143 Address watch_address(GetLoadAddress());
Jim Inghamed2b62a2012-10-23 21:09:09 +0000144 if (!m_type.IsValid())
145 {
146 // Don't know how to report new & old values, since we couldn't make a scalar type for this watchpoint.
147 // This works around an assert in ValueObjectMemory::Create.
148 // FIXME: This should not happen, but if it does in some case we care about,
149 // we can go grab the value raw and print it as unsigned.
150 return false;
151 }
Jim Ingham9e376622012-10-23 07:20:06 +0000152 m_new_value_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), watch_name.AsCString(), watch_address, m_type);
153 m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name);
154 if (m_new_value_sp && m_new_value_sp->GetError().Success())
155 return true;
156 else
157 return false;
158}
159
Johnny Chen0b093662012-08-14 20:56:37 +0000160void
161Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
162{
163 ++m_false_alarms;
164 if (m_false_alarms)
165 {
166 if (m_hit_count >= m_false_alarms)
167 {
168 m_hit_count -= m_false_alarms;
169 m_false_alarms = 0;
170 }
171 else
172 {
173 m_false_alarms -= m_hit_count;
174 m_hit_count = 0;
175 }
176 }
177}
178
Chris Lattner24943d22010-06-08 16:52:24 +0000179// RETURNS - true if we should stop at this breakpoint, false if we
180// should continue.
181
182bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000183Watchpoint::ShouldStop (StoppointCallbackContext *context)
Chris Lattner24943d22010-06-08 16:52:24 +0000184{
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000185 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000186
Johnny Chen01acfa72011-09-22 18:04:58 +0000187 if (!IsEnabled())
188 return false;
Johnny Chen043f8c22011-09-21 22:47:15 +0000189
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000190 if (GetHitCount() <= GetIgnoreCount())
Johnny Chen01acfa72011-09-22 18:04:58 +0000191 return false;
192
Johnny Chen712a6282011-10-17 18:58:00 +0000193 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000194}
195
196void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000197Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
Johnny Chen34bbf852011-09-12 23:38:44 +0000198{
Johnny Chen10b12b32011-09-16 21:41:42 +0000199 DumpWithLevel(s, level);
Johnny Chen34bbf852011-09-12 23:38:44 +0000200 return;
201}
202
203void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000204Watchpoint::Dump(Stream *s) const
Chris Lattner24943d22010-06-08 16:52:24 +0000205{
Johnny Chen10b12b32011-09-16 21:41:42 +0000206 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
207}
208
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000209// If prefix is NULL, we display the watch id and ignore the prefix altogether.
Johnny Chen10b12b32011-09-16 21:41:42 +0000210void
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000211Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
Johnny Chen9e985592012-08-13 21:09:54 +0000212{
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000213 if (!prefix)
214 {
215 s->Printf("\nWatchpoint %u hit:", GetID());
216 prefix = "";
217 }
Jim Ingham9e376622012-10-23 07:20:06 +0000218
219 if (m_old_value_sp)
Johnny Chen9e985592012-08-13 21:09:54 +0000220 {
Jim Ingham9e376622012-10-23 07:20:06 +0000221 s->Printf("\n%sold value: %s", prefix, m_old_value_sp->GetValueAsCString());
Johnny Chen9e985592012-08-13 21:09:54 +0000222 }
Jim Ingham9e376622012-10-23 07:20:06 +0000223 if (m_new_value_sp)
Johnny Chen9e985592012-08-13 21:09:54 +0000224 {
Jim Ingham9e376622012-10-23 07:20:06 +0000225 s->Printf("\n%snew value: %s", prefix, m_new_value_sp->GetValueAsCString());
Johnny Chen9e985592012-08-13 21:09:54 +0000226 }
227}
228
229void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000230Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Johnny Chen10b12b32011-09-16 21:41:42 +0000231{
Chris Lattner24943d22010-06-08 16:52:24 +0000232 if (s == NULL)
233 return;
234
Johnny Chen10b12b32011-09-16 21:41:42 +0000235 assert(description_level >= lldb::eDescriptionLevelBrief &&
236 description_level <= lldb::eDescriptionLevelVerbose);
237
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000238 s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 " size = %u state = %s type = %s%s",
Johnny Chen10b12b32011-09-16 21:41:42 +0000239 GetID(),
Johnny Chen1c2d9412012-01-24 00:11:02 +0000240 GetLoadAddress(),
Johnny Chen10b12b32011-09-16 21:41:42 +0000241 m_byte_size,
Johnny Chen116a5cd2012-02-25 06:44:30 +0000242 IsEnabled() ? "enabled" : "disabled",
Johnny Chen10b12b32011-09-16 21:41:42 +0000243 m_watch_read ? "r" : "",
244 m_watch_write ? "w" : "");
245
Johnny Chen712a6282011-10-17 18:58:00 +0000246 if (description_level >= lldb::eDescriptionLevelFull) {
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000247 if (!m_decl_str.empty())
Johnny Chen712a6282011-10-17 18:58:00 +0000248 s->Printf("\n declare @ '%s'", m_decl_str.c_str());
Johnny Chen116a5cd2012-02-25 06:44:30 +0000249 if (!m_watch_spec_str.empty())
Johnny Chen9e985592012-08-13 21:09:54 +0000250 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
251
252 // Dump the snapshots we have taken.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000253 DumpSnapshots(s, " ");
Johnny Chen9e985592012-08-13 21:09:54 +0000254
Johnny Chen712a6282011-10-17 18:58:00 +0000255 if (GetConditionText())
256 s->Printf("\n condition = '%s'", GetConditionText());
Johnny Chenf3ec4612012-08-09 23:09:42 +0000257 m_options.GetCallbackDescription(s, description_level);
Johnny Chen712a6282011-10-17 18:58:00 +0000258 }
Johnny Chen10b12b32011-09-16 21:41:42 +0000259
260 if (description_level >= lldb::eDescriptionLevelVerbose)
Jason Molendaa4a15872012-02-23 22:32:13 +0000261 {
Johnny Chenf3ec4612012-08-09 23:09:42 +0000262 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u",
263 GetHardwareIndex(),
264 GetHitCount(),
265 GetIgnoreCount());
Jason Molendaa4a15872012-02-23 22:32:13 +0000266 }
Chris Lattner24943d22010-06-08 16:52:24 +0000267}
268
269bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000270Watchpoint::IsEnabled() const
Chris Lattner24943d22010-06-08 16:52:24 +0000271{
272 return m_enabled;
273}
274
Johnny Chenf84e5662012-08-21 23:17:04 +0000275// Within StopInfo.cpp, we purposely turn on the ephemeral mode right before temporarily disable the watchpoint
276// in order to perform possible watchpoint actions without triggering further watchpoint events.
277// After the temporary disabled watchpoint is enabled, we then turn off the ephemeral mode.
278
279void
280Watchpoint::TurnOnEphemeralMode()
281{
282 m_is_ephemeral = true;
283}
284
285void
286Watchpoint::TurnOffEphemeralMode()
287{
288 m_is_ephemeral = false;
Johnny Chen258db3a2012-08-23 22:28:26 +0000289 // Leaving ephemeral mode, reset the m_disabled_count!
290 m_disabled_count = 0;
291}
292
293bool
294Watchpoint::IsDisabledDuringEphemeralMode()
295{
296 return m_disabled_count > 1;
Johnny Chenf84e5662012-08-21 23:17:04 +0000297}
298
Chris Lattner24943d22010-06-08 16:52:24 +0000299void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000300Watchpoint::SetEnabled(bool enabled)
Chris Lattner24943d22010-06-08 16:52:24 +0000301{
302 if (!enabled)
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000303 {
Johnny Chenf84e5662012-08-21 23:17:04 +0000304 if (!m_is_ephemeral)
305 SetHardwareIndex(LLDB_INVALID_INDEX32);
Johnny Chen258db3a2012-08-23 22:28:26 +0000306 else
307 ++m_disabled_count;
308
Johnny Chenbd446f12012-08-21 22:06:34 +0000309 // Don't clear the snapshots for now.
310 // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
Johnny Chenc9c2a9b2012-08-13 23:27:50 +0000311 }
Chris Lattner24943d22010-06-08 16:52:24 +0000312 m_enabled = enabled;
313}
314
315void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000316Watchpoint::SetWatchpointType (uint32_t type)
Chris Lattner24943d22010-06-08 16:52:24 +0000317{
318 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
319 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
320}
321
322bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000323Watchpoint::WatchpointRead () const
Chris Lattner24943d22010-06-08 16:52:24 +0000324{
325 return m_watch_read != 0;
326}
327bool
Johnny Chenecd4feb2011-10-14 00:42:25 +0000328Watchpoint::WatchpointWrite () const
Chris Lattner24943d22010-06-08 16:52:24 +0000329{
330 return m_watch_write != 0;
331}
Greg Clayton54e7afa2010-07-09 20:39:50 +0000332uint32_t
Johnny Chenecd4feb2011-10-14 00:42:25 +0000333Watchpoint::GetIgnoreCount () const
Chris Lattner24943d22010-06-08 16:52:24 +0000334{
335 return m_ignore_count;
336}
337
338void
Johnny Chenecd4feb2011-10-14 00:42:25 +0000339Watchpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000340{
341 m_ignore_count = n;
342}
Johnny Chen712a6282011-10-17 18:58:00 +0000343
344bool
345Watchpoint::InvokeCallback (StoppointCallbackContext *context)
346{
Johnny Chenf3ec4612012-08-09 23:09:42 +0000347 return m_options.InvokeCallback (context, GetID());
Johnny Chen712a6282011-10-17 18:58:00 +0000348}
349
350void
351Watchpoint::SetCondition (const char *condition)
352{
353 if (condition == NULL || condition[0] == '\0')
354 {
355 if (m_condition_ap.get())
356 m_condition_ap.reset();
357 }
358 else
359 {
360 // Pass NULL for expr_prefix (no translation-unit level definitions).
Sean Callanandaa6efe2011-12-21 22:22:58 +0000361 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
Johnny Chen712a6282011-10-17 18:58:00 +0000362 }
363}
364
365const char *
366Watchpoint::GetConditionText () const
367{
368 if (m_condition_ap.get())
369 return m_condition_ap->GetUserText();
370 else
371 return NULL;
372}
373