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     if (GetHitCount() <= GetIgnoreCount())
187         return false;
188 
189     return true;
190 }
191 
192 void
193 Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
194 {
195     DumpWithLevel(s, level);
196 }
197 
198 void
199 Watchpoint::Dump(Stream *s) const
200 {
201     DumpWithLevel(s, lldb::eDescriptionLevelBrief);
202 }
203 
204 // If prefix is nullptr, we display the watch id and ignore the prefix altogether.
205 void
206 Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
207 {
208     if (!prefix)
209     {
210         s->Printf("\nWatchpoint %u hit:", GetID());
211         prefix = "";
212     }
213 
214     if (m_old_value_sp)
215     {
216         const char *old_value_cstr =  m_old_value_sp->GetValueAsCString();
217         if (old_value_cstr && old_value_cstr[0])
218             s->Printf("\n%sold value: %s", prefix, old_value_cstr);
219         else
220         {
221             const char *old_summary_cstr =  m_old_value_sp-> GetSummaryAsCString();
222             if (old_summary_cstr && old_summary_cstr[0])
223                 s->Printf("\n%sold value: %s", prefix, old_summary_cstr);
224         }
225     }
226 
227     if (m_new_value_sp)
228     {
229         const char *new_value_cstr =  m_new_value_sp->GetValueAsCString();
230         if (new_value_cstr && new_value_cstr[0])
231             s->Printf("\n%snew value: %s", prefix, new_value_cstr);
232         else
233         {
234             const char *new_summary_cstr =  m_new_value_sp-> GetSummaryAsCString();
235             if (new_summary_cstr && new_summary_cstr[0])
236                 s->Printf("\n%snew value: %s", prefix, new_summary_cstr);
237         }
238     }
239 }
240 
241 void
242 Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
243 {
244     if (s == nullptr)
245         return;
246 
247     assert(description_level >= lldb::eDescriptionLevelBrief &&
248            description_level <= lldb::eDescriptionLevelVerbose);
249 
250     s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 " size = %u state = %s type = %s%s",
251               GetID(),
252               GetLoadAddress(),
253               m_byte_size,
254               IsEnabled() ? "enabled" : "disabled",
255               m_watch_read ? "r" : "",
256               m_watch_write ? "w" : "");
257 
258     if (description_level >= lldb::eDescriptionLevelFull) {
259         if (!m_decl_str.empty())
260             s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
261         if (!m_watch_spec_str.empty())
262             s->Printf("\n    watchpoint spec = '%s'", m_watch_spec_str.c_str());
263 
264         // Dump the snapshots we have taken.
265         DumpSnapshots(s, "    ");
266 
267         if (GetConditionText())
268             s->Printf("\n    condition = '%s'", GetConditionText());
269         m_options.GetCallbackDescription(s, description_level);
270     }
271 
272     if (description_level >= lldb::eDescriptionLevelVerbose)
273     {
274         s->Printf("\n    hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
275                   GetHardwareIndex(),
276                   GetHitCount(),
277                   GetIgnoreCount());
278     }
279 }
280 
281 bool
282 Watchpoint::IsEnabled() const
283 {
284     return m_enabled;
285 }
286 
287 // Within StopInfo.cpp, we purposely turn on the ephemeral mode right before temporarily disable the watchpoint
288 // in order to perform possible watchpoint actions without triggering further watchpoint events.
289 // After the temporary disabled watchpoint is enabled, we then turn off the ephemeral mode.
290 
291 void
292 Watchpoint::TurnOnEphemeralMode()
293 {
294     m_is_ephemeral = true;
295 }
296 
297 void
298 Watchpoint::TurnOffEphemeralMode()
299 {
300     m_is_ephemeral = false;
301     // Leaving ephemeral mode, reset the m_disabled_count!
302     m_disabled_count = 0;
303 }
304 
305 bool
306 Watchpoint::IsDisabledDuringEphemeralMode()
307 {
308     return m_disabled_count > 1;
309 }
310 
311 void
312 Watchpoint::SetEnabled(bool enabled, bool notify)
313 {
314     if (!enabled)
315     {
316         if (!m_is_ephemeral)
317             SetHardwareIndex(LLDB_INVALID_INDEX32);
318         else
319             ++m_disabled_count;
320 
321         // Don't clear the snapshots for now.
322         // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
323     }
324     bool changed = enabled != m_enabled;
325     m_enabled = enabled;
326     if (notify && !m_is_ephemeral && changed)
327         SendWatchpointChangedEvent (enabled ? eWatchpointEventTypeEnabled : eWatchpointEventTypeDisabled);
328 }
329 
330 void
331 Watchpoint::SetWatchpointType (uint32_t type, bool notify)
332 {
333     int old_watch_read = m_watch_read;
334     int old_watch_write = m_watch_write;
335     m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
336     m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
337     if (notify && (old_watch_read != m_watch_read || old_watch_write != m_watch_write))
338         SendWatchpointChangedEvent (eWatchpointEventTypeTypeChanged);
339 }
340 
341 bool
342 Watchpoint::WatchpointRead () const
343 {
344     return m_watch_read != 0;
345 }
346 
347 bool
348 Watchpoint::WatchpointWrite () const
349 {
350     return m_watch_write != 0;
351 }
352 
353 uint32_t
354 Watchpoint::GetIgnoreCount () const
355 {
356     return m_ignore_count;
357 }
358 
359 void
360 Watchpoint::SetIgnoreCount (uint32_t n)
361 {
362     bool changed = m_ignore_count != n;
363     m_ignore_count = n;
364     if (changed)
365         SendWatchpointChangedEvent (eWatchpointEventTypeIgnoreChanged);
366 }
367 
368 bool
369 Watchpoint::InvokeCallback (StoppointCallbackContext *context)
370 {
371     return m_options.InvokeCallback (context, GetID());
372 }
373 
374 void
375 Watchpoint::SetCondition (const char *condition)
376 {
377     if (condition == nullptr || condition[0] == '\0')
378     {
379         if (m_condition_ap.get())
380             m_condition_ap.reset();
381     }
382     else
383     {
384         // Pass nullptr for expr_prefix (no translation-unit level definitions).
385         Error error;
386         m_condition_ap.reset(m_target.GetUserExpressionForLanguage(condition,
387                                                                    nullptr,
388                                                                    lldb::eLanguageTypeUnknown,
389                                                                    UserExpression::eResultTypeAny,
390                                                                    error));
391         if (error.Fail())
392         {
393             // FIXME: Log something...
394             m_condition_ap.reset();
395         }
396     }
397     SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged);
398 }
399 
400 const char *
401 Watchpoint::GetConditionText () const
402 {
403     if (m_condition_ap.get())
404         return m_condition_ap->GetUserText();
405     else
406         return nullptr;
407 }
408 
409 void
410 Watchpoint::SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind)
411 {
412     if (!m_being_created
413         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
414     {
415         WatchpointEventData *data = new Watchpoint::WatchpointEventData (eventKind, shared_from_this());
416         GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
417     }
418 }
419 
420 void
421 Watchpoint::SendWatchpointChangedEvent (WatchpointEventData *data)
422 {
423     if (data == nullptr)
424         return;
425 
426     if (!m_being_created
427         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
428         GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
429     else
430         delete data;
431 }
432 
433 Watchpoint::WatchpointEventData::WatchpointEventData (WatchpointEventType sub_type,
434                                                       const WatchpointSP &new_watchpoint_sp) :
435     EventData (),
436     m_watchpoint_event (sub_type),
437     m_new_watchpoint_sp (new_watchpoint_sp)
438 {
439 }
440 
441 Watchpoint::WatchpointEventData::~WatchpointEventData() = default;
442 
443 const ConstString &
444 Watchpoint::WatchpointEventData::GetFlavorString ()
445 {
446     static ConstString g_flavor ("Watchpoint::WatchpointEventData");
447     return g_flavor;
448 }
449 
450 const ConstString &
451 Watchpoint::WatchpointEventData::GetFlavor () const
452 {
453     return WatchpointEventData::GetFlavorString ();
454 }
455 
456 WatchpointSP &
457 Watchpoint::WatchpointEventData::GetWatchpoint ()
458 {
459     return m_new_watchpoint_sp;
460 }
461 
462 WatchpointEventType
463 Watchpoint::WatchpointEventData::GetWatchpointEventType () const
464 {
465     return m_watchpoint_event;
466 }
467 
468 void
469 Watchpoint::WatchpointEventData::Dump (Stream *s) const
470 {
471 }
472 
473 const Watchpoint::WatchpointEventData *
474 Watchpoint::WatchpointEventData::GetEventDataFromEvent (const Event *event)
475 {
476     if (event)
477     {
478         const EventData *event_data = event->GetData();
479         if (event_data && event_data->GetFlavor() == WatchpointEventData::GetFlavorString())
480             return static_cast <const WatchpointEventData *> (event->GetData());
481     }
482     return nullptr;
483 }
484 
485 WatchpointEventType
486 Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent (const EventSP &event_sp)
487 {
488     const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
489 
490     if (data == nullptr)
491         return eWatchpointEventTypeInvalidType;
492     else
493         return data->GetWatchpointEventType();
494 }
495 
496 WatchpointSP
497 Watchpoint::WatchpointEventData::GetWatchpointFromEvent (const EventSP &event_sp)
498 {
499     WatchpointSP wp_sp;
500 
501     const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
502     if (data)
503         wp_sp = data->m_new_watchpoint_sp;
504 
505     return wp_sp;
506 }
507