1 //===-- Watchpoint.cpp ------------------------------------------*- C++ -*-===//
2 //
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 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Breakpoint/Watchpoint.h"
15 
16 #include "lldb/Breakpoint/StoppointCallbackContext.h"
17 #include "lldb/Core/Stream.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Core/ValueObjectMemory.h"
21 #include "lldb/Symbol/ClangASTContext.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/ThreadSpec.h"
25 #include "lldb/Expression/UserExpression.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware) :
31     StoppointLocation (0, addr, size, hardware),
32     m_target(target),
33     m_enabled(false),
34     m_is_hardware(hardware),
35     m_is_watch_variable(false),
36     m_is_ephemeral(false),
37     m_disabled_count(0),
38     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),
43     m_false_alarms(0),
44     m_decl_str(),
45     m_watch_spec_str(),
46     m_type(),
47     m_error(),
48     m_options (),
49     m_being_created(true)
50 {
51     if (type && type->IsValid())
52         m_type = *type;
53     else
54     {
55         // If we don't have a known type, then we force it to unsigned int of the right size.
56         ClangASTContext *ast_context = target.GetScratchClangASTContext();
57         m_type = ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
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     }
67     m_being_created = false;
68 }
69 
70 Watchpoint::~Watchpoint() = default;
71 
72 // This function is used when "baton" doesn't need to be freed
73 void
74 Watchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
75 {
76     // The default "Baton" class will keep a copy of "baton" and won't free
77     // or delete it when it goes goes out of scope.
78     m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
79 
80     SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
81 }
82 
83 // This function is used when a baton needs to be freed and therefore is
84 // contained in a "Baton" subclass.
85 void
86 Watchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
87 {
88     m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
89     SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
90 }
91 
92 void
93 Watchpoint::ClearCallback ()
94 {
95     m_options.ClearCallback ();
96     SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
97 }
98 
99 void
100 Watchpoint::SetDeclInfo (const std::string &str)
101 {
102     m_decl_str = str;
103 }
104 
105 std::string
106 Watchpoint::GetWatchSpec()
107 {
108     return m_watch_spec_str;
109 }
110 
111 void
112 Watchpoint::SetWatchSpec (const std::string &str)
113 {
114     m_watch_spec_str = str;
115 }
116 
117 // Override default impl of StoppointLocation::IsHardware() since m_is_hardware
118 // member field is more accurate.
119 bool
120 Watchpoint::IsHardware () const
121 {
122     return m_is_hardware;
123 }
124 
125 bool
126 Watchpoint::IsWatchVariable() const
127 {
128     return m_is_watch_variable;
129 }
130 
131 void
132 Watchpoint::SetWatchVariable(bool val)
133 {
134     m_is_watch_variable = val;
135 }
136 
137 bool
138 Watchpoint::CaptureWatchedValue (const ExecutionContext &exe_ctx)
139 {
140     ConstString watch_name("$__lldb__watch_value");
141     m_old_value_sp = m_new_value_sp;
142     Address watch_address(GetLoadAddress());
143     if (!m_type.IsValid())
144     {
145         // Don't know how to report new & old values, since we couldn't make a scalar type for this watchpoint.
146         // This works around an assert in ValueObjectMemory::Create.
147         // FIXME: This should not happen, but if it does in some case we care about,
148         // we can go grab the value raw and print it as unsigned.
149         return false;
150     }
151     m_new_value_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), watch_name.AsCString(), watch_address, m_type);
152     m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name);
153     return (m_new_value_sp && m_new_value_sp->GetError().Success());
154 }
155 
156 void
157 Watchpoint::IncrementFalseAlarmsAndReviseHitCount()
158 {
159     ++m_false_alarms;
160     if (m_false_alarms)
161     {
162         if (m_hit_count >= m_false_alarms)
163         {
164             m_hit_count -= m_false_alarms;
165             m_false_alarms = 0;
166         }
167         else
168         {
169             m_false_alarms -= m_hit_count;
170             m_hit_count = 0;
171         }
172     }
173 }
174 
175 // RETURNS - true if we should stop at this breakpoint, false if we
176 // should continue.
177 
178 bool
179 Watchpoint::ShouldStop (StoppointCallbackContext *context)
180 {
181     IncrementHitCount();
182 
183     if (!IsEnabled())
184         return false;
185 
186     return true;
187 }
188 
189 void
190 Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
191 {
192     DumpWithLevel(s, level);
193 }
194 
195 void
196 Watchpoint::Dump(Stream *s) const
197 {
198     DumpWithLevel(s, lldb::eDescriptionLevelBrief);
199 }
200 
201 // If prefix is nullptr, we display the watch id and ignore the prefix altogether.
202 void
203 Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
204 {
205     if (!prefix)
206     {
207         s->Printf("\nWatchpoint %u hit:", GetID());
208         prefix = "";
209     }
210 
211     if (m_old_value_sp)
212     {
213         const char *old_value_cstr =  m_old_value_sp->GetValueAsCString();
214         if (old_value_cstr && old_value_cstr[0])
215             s->Printf("\n%sold value: %s", prefix, old_value_cstr);
216         else
217         {
218             const char *old_summary_cstr =  m_old_value_sp-> GetSummaryAsCString();
219             if (old_summary_cstr && old_summary_cstr[0])
220                 s->Printf("\n%sold value: %s", prefix, old_summary_cstr);
221         }
222     }
223 
224     if (m_new_value_sp)
225     {
226         const char *new_value_cstr =  m_new_value_sp->GetValueAsCString();
227         if (new_value_cstr && new_value_cstr[0])
228             s->Printf("\n%snew value: %s", prefix, new_value_cstr);
229         else
230         {
231             const char *new_summary_cstr =  m_new_value_sp-> GetSummaryAsCString();
232             if (new_summary_cstr && new_summary_cstr[0])
233                 s->Printf("\n%snew value: %s", prefix, new_summary_cstr);
234         }
235     }
236 }
237 
238 void
239 Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
240 {
241     if (s == nullptr)
242         return;
243 
244     assert(description_level >= lldb::eDescriptionLevelBrief &&
245            description_level <= lldb::eDescriptionLevelVerbose);
246 
247     s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 " size = %u state = %s type = %s%s",
248               GetID(),
249               GetLoadAddress(),
250               m_byte_size,
251               IsEnabled() ? "enabled" : "disabled",
252               m_watch_read ? "r" : "",
253               m_watch_write ? "w" : "");
254 
255     if (description_level >= lldb::eDescriptionLevelFull) {
256         if (!m_decl_str.empty())
257             s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
258         if (!m_watch_spec_str.empty())
259             s->Printf("\n    watchpoint spec = '%s'", m_watch_spec_str.c_str());
260 
261         // Dump the snapshots we have taken.
262         DumpSnapshots(s, "    ");
263 
264         if (GetConditionText())
265             s->Printf("\n    condition = '%s'", GetConditionText());
266         m_options.GetCallbackDescription(s, description_level);
267     }
268 
269     if (description_level >= lldb::eDescriptionLevelVerbose)
270     {
271         s->Printf("\n    hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
272                   GetHardwareIndex(),
273                   GetHitCount(),
274                   GetIgnoreCount());
275     }
276 }
277 
278 bool
279 Watchpoint::IsEnabled() const
280 {
281     return m_enabled;
282 }
283 
284 // Within StopInfo.cpp, we purposely turn on the ephemeral mode right before temporarily disable the watchpoint
285 // in order to perform possible watchpoint actions without triggering further watchpoint events.
286 // After the temporary disabled watchpoint is enabled, we then turn off the ephemeral mode.
287 
288 void
289 Watchpoint::TurnOnEphemeralMode()
290 {
291     m_is_ephemeral = true;
292 }
293 
294 void
295 Watchpoint::TurnOffEphemeralMode()
296 {
297     m_is_ephemeral = false;
298     // Leaving ephemeral mode, reset the m_disabled_count!
299     m_disabled_count = 0;
300 }
301 
302 bool
303 Watchpoint::IsDisabledDuringEphemeralMode()
304 {
305     return m_disabled_count > 1;
306 }
307 
308 void
309 Watchpoint::SetEnabled(bool enabled, bool notify)
310 {
311     if (!enabled)
312     {
313         if (!m_is_ephemeral)
314             SetHardwareIndex(LLDB_INVALID_INDEX32);
315         else
316             ++m_disabled_count;
317 
318         // Don't clear the snapshots for now.
319         // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
320     }
321     bool changed = enabled != m_enabled;
322     m_enabled = enabled;
323     if (notify && !m_is_ephemeral && changed)
324         SendWatchpointChangedEvent (enabled ? eWatchpointEventTypeEnabled : eWatchpointEventTypeDisabled);
325 }
326 
327 void
328 Watchpoint::SetWatchpointType (uint32_t type, bool notify)
329 {
330     int old_watch_read = m_watch_read;
331     int old_watch_write = m_watch_write;
332     m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
333     m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
334     if (notify && (old_watch_read != m_watch_read || old_watch_write != m_watch_write))
335         SendWatchpointChangedEvent (eWatchpointEventTypeTypeChanged);
336 }
337 
338 bool
339 Watchpoint::WatchpointRead () const
340 {
341     return m_watch_read != 0;
342 }
343 
344 bool
345 Watchpoint::WatchpointWrite () const
346 {
347     return m_watch_write != 0;
348 }
349 
350 uint32_t
351 Watchpoint::GetIgnoreCount () const
352 {
353     return m_ignore_count;
354 }
355 
356 void
357 Watchpoint::SetIgnoreCount (uint32_t n)
358 {
359     bool changed = m_ignore_count != n;
360     m_ignore_count = n;
361     if (changed)
362         SendWatchpointChangedEvent (eWatchpointEventTypeIgnoreChanged);
363 }
364 
365 bool
366 Watchpoint::InvokeCallback (StoppointCallbackContext *context)
367 {
368     return m_options.InvokeCallback (context, GetID());
369 }
370 
371 void
372 Watchpoint::SetCondition (const char *condition)
373 {
374     if (condition == nullptr || condition[0] == '\0')
375     {
376         if (m_condition_ap.get())
377             m_condition_ap.reset();
378     }
379     else
380     {
381         // Pass nullptr for expr_prefix (no translation-unit level definitions).
382         Error error;
383         m_condition_ap.reset(m_target.GetUserExpressionForLanguage(condition,
384                                                                    nullptr,
385                                                                    lldb::eLanguageTypeUnknown,
386                                                                    UserExpression::eResultTypeAny,
387                                                                    EvaluateExpressionOptions(),
388                                                                    error));
389         if (error.Fail())
390         {
391             // FIXME: Log something...
392             m_condition_ap.reset();
393         }
394     }
395     SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged);
396 }
397 
398 const char *
399 Watchpoint::GetConditionText () const
400 {
401     if (m_condition_ap.get())
402         return m_condition_ap->GetUserText();
403     else
404         return nullptr;
405 }
406 
407 void
408 Watchpoint::SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind)
409 {
410     if (!m_being_created
411         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
412     {
413         WatchpointEventData *data = new Watchpoint::WatchpointEventData (eventKind, shared_from_this());
414         GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
415     }
416 }
417 
418 void
419 Watchpoint::SendWatchpointChangedEvent (WatchpointEventData *data)
420 {
421     if (data == nullptr)
422         return;
423 
424     if (!m_being_created
425         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
426         GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
427     else
428         delete data;
429 }
430 
431 Watchpoint::WatchpointEventData::WatchpointEventData (WatchpointEventType sub_type,
432                                                       const WatchpointSP &new_watchpoint_sp) :
433     EventData (),
434     m_watchpoint_event (sub_type),
435     m_new_watchpoint_sp (new_watchpoint_sp)
436 {
437 }
438 
439 Watchpoint::WatchpointEventData::~WatchpointEventData() = default;
440 
441 const ConstString &
442 Watchpoint::WatchpointEventData::GetFlavorString ()
443 {
444     static ConstString g_flavor ("Watchpoint::WatchpointEventData");
445     return g_flavor;
446 }
447 
448 const ConstString &
449 Watchpoint::WatchpointEventData::GetFlavor () const
450 {
451     return WatchpointEventData::GetFlavorString ();
452 }
453 
454 WatchpointSP &
455 Watchpoint::WatchpointEventData::GetWatchpoint ()
456 {
457     return m_new_watchpoint_sp;
458 }
459 
460 WatchpointEventType
461 Watchpoint::WatchpointEventData::GetWatchpointEventType () const
462 {
463     return m_watchpoint_event;
464 }
465 
466 void
467 Watchpoint::WatchpointEventData::Dump (Stream *s) const
468 {
469 }
470 
471 const Watchpoint::WatchpointEventData *
472 Watchpoint::WatchpointEventData::GetEventDataFromEvent (const Event *event)
473 {
474     if (event)
475     {
476         const EventData *event_data = event->GetData();
477         if (event_data && event_data->GetFlavor() == WatchpointEventData::GetFlavorString())
478             return static_cast <const WatchpointEventData *> (event->GetData());
479     }
480     return nullptr;
481 }
482 
483 WatchpointEventType
484 Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent (const EventSP &event_sp)
485 {
486     const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
487 
488     if (data == nullptr)
489         return eWatchpointEventTypeInvalidType;
490     else
491         return data->GetWatchpointEventType();
492 }
493 
494 WatchpointSP
495 Watchpoint::WatchpointEventData::GetWatchpointFromEvent (const EventSP &event_sp)
496 {
497     WatchpointSP wp_sp;
498 
499     const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
500     if (data)
501         wp_sp = data->m_new_watchpoint_sp;
502 
503     return wp_sp;
504 }
505