1254721Semaste//===-- Watchpoint.cpp ------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Breakpoint/Watchpoint.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Breakpoint/StoppointCallbackContext.h"
17254721Semaste#include "lldb/Core/Stream.h"
18254721Semaste#include "lldb/Core/Value.h"
19254721Semaste#include "lldb/Core/ValueObject.h"
20254721Semaste#include "lldb/Core/ValueObjectMemory.h"
21254721Semaste#include "lldb/Symbol/ClangASTContext.h"
22254721Semaste#include "lldb/Target/Process.h"
23254721Semaste#include "lldb/Target/Target.h"
24254721Semaste#include "lldb/Target/ThreadSpec.h"
25254721Semaste#include "lldb/Expression/ClangUserExpression.h"
26254721Semaste
27254721Semasteusing namespace lldb;
28254721Semasteusing namespace lldb_private;
29254721Semaste
30254721SemasteWatchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware) :
31254721Semaste    StoppointLocation (0, addr, size, hardware),
32254721Semaste    m_target(target),
33254721Semaste    m_enabled(false),
34254721Semaste    m_is_hardware(hardware),
35254721Semaste    m_is_watch_variable(false),
36254721Semaste    m_is_ephemeral(false),
37254721Semaste    m_disabled_count(0),
38254721Semaste    m_watch_read(0),
39254721Semaste    m_watch_write(0),
40254721Semaste    m_watch_was_read(0),
41254721Semaste    m_watch_was_written(0),
42254721Semaste    m_ignore_count(0),
43254721Semaste    m_false_alarms(0),
44254721Semaste    m_decl_str(),
45254721Semaste    m_watch_spec_str(),
46254721Semaste    m_type(),
47254721Semaste    m_error(),
48254721Semaste    m_options (),
49254721Semaste    m_being_created(true)
50254721Semaste{
51254721Semaste    if (type && type->IsValid())
52254721Semaste        m_type = *type;
53254721Semaste    else
54254721Semaste    {
55254721Semaste        // If we don't have a known type, then we force it to unsigned int of the right size.
56254721Semaste        ClangASTContext *ast_context = target.GetScratchClangASTContext();
57254721Semaste        m_type = ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
58254721Semaste    }
59254721Semaste
60254721Semaste    // Set the initial value of the watched variable:
61254721Semaste    if (m_target.GetProcessSP())
62254721Semaste    {
63254721Semaste        ExecutionContext exe_ctx;
64254721Semaste        m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx);
65254721Semaste        CaptureWatchedValue (exe_ctx);
66254721Semaste    }
67254721Semaste    m_being_created = false;
68254721Semaste}
69254721Semaste
70254721SemasteWatchpoint::~Watchpoint()
71254721Semaste{
72254721Semaste}
73254721Semaste
74254721Semaste// This function is used when "baton" doesn't need to be freed
75254721Semastevoid
76254721SemasteWatchpoint::SetCallback (WatchpointHitCallback callback, void *baton, bool is_synchronous)
77254721Semaste{
78254721Semaste    // The default "Baton" class will keep a copy of "baton" and won't free
79254721Semaste    // or delete it when it goes goes out of scope.
80254721Semaste    m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
81254721Semaste
82254721Semaste    SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
83254721Semaste}
84254721Semaste
85254721Semaste// This function is used when a baton needs to be freed and therefore is
86254721Semaste// contained in a "Baton" subclass.
87254721Semastevoid
88254721SemasteWatchpoint::SetCallback (WatchpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
89254721Semaste{
90254721Semaste    m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
91254721Semaste    SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
92254721Semaste}
93254721Semaste
94254721Semastevoid
95254721SemasteWatchpoint::ClearCallback ()
96254721Semaste{
97254721Semaste    m_options.ClearCallback ();
98254721Semaste    SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
99254721Semaste}
100254721Semaste
101254721Semastevoid
102254721SemasteWatchpoint::SetDeclInfo (const std::string &str)
103254721Semaste{
104254721Semaste    m_decl_str = str;
105254721Semaste    return;
106254721Semaste}
107254721Semaste
108254721Semastestd::string
109254721SemasteWatchpoint::GetWatchSpec()
110254721Semaste{
111254721Semaste    return m_watch_spec_str;
112254721Semaste}
113254721Semaste
114254721Semastevoid
115254721SemasteWatchpoint::SetWatchSpec (const std::string &str)
116254721Semaste{
117254721Semaste    m_watch_spec_str = str;
118254721Semaste    return;
119254721Semaste}
120254721Semaste
121254721Semaste// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
122254721Semaste// member field is more accurate.
123254721Semastebool
124254721SemasteWatchpoint::IsHardware () const
125254721Semaste{
126254721Semaste    return m_is_hardware;
127254721Semaste}
128254721Semaste
129254721Semastebool
130254721SemasteWatchpoint::IsWatchVariable() const
131254721Semaste{
132254721Semaste    return m_is_watch_variable;
133254721Semaste}
134254721Semaste
135254721Semastevoid
136254721SemasteWatchpoint::SetWatchVariable(bool val)
137254721Semaste{
138254721Semaste    m_is_watch_variable = val;
139254721Semaste}
140254721Semaste
141254721Semastebool
142254721SemasteWatchpoint::CaptureWatchedValue (const ExecutionContext &exe_ctx)
143254721Semaste{
144254721Semaste    ConstString watch_name("$__lldb__watch_value");
145254721Semaste    m_old_value_sp = m_new_value_sp;
146254721Semaste    Address watch_address(GetLoadAddress());
147254721Semaste    if (!m_type.IsValid())
148254721Semaste    {
149254721Semaste        // Don't know how to report new & old values, since we couldn't make a scalar type for this watchpoint.
150254721Semaste        // This works around an assert in ValueObjectMemory::Create.
151254721Semaste        // FIXME: This should not happen, but if it does in some case we care about,
152254721Semaste        // we can go grab the value raw and print it as unsigned.
153254721Semaste        return false;
154254721Semaste    }
155254721Semaste    m_new_value_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), watch_name.AsCString(), watch_address, m_type);
156254721Semaste    m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name);
157254721Semaste    if (m_new_value_sp && m_new_value_sp->GetError().Success())
158254721Semaste        return true;
159254721Semaste    else
160254721Semaste        return false;
161254721Semaste}
162254721Semaste
163254721Semastevoid
164254721SemasteWatchpoint::IncrementFalseAlarmsAndReviseHitCount()
165254721Semaste{
166254721Semaste    ++m_false_alarms;
167254721Semaste    if (m_false_alarms)
168254721Semaste    {
169254721Semaste        if (m_hit_count >= m_false_alarms)
170254721Semaste        {
171254721Semaste            m_hit_count -= m_false_alarms;
172254721Semaste            m_false_alarms = 0;
173254721Semaste        }
174254721Semaste        else
175254721Semaste        {
176254721Semaste            m_false_alarms -= m_hit_count;
177254721Semaste            m_hit_count = 0;
178254721Semaste        }
179254721Semaste    }
180254721Semaste}
181254721Semaste
182254721Semaste// RETURNS - true if we should stop at this breakpoint, false if we
183254721Semaste// should continue.
184254721Semaste
185254721Semastebool
186254721SemasteWatchpoint::ShouldStop (StoppointCallbackContext *context)
187254721Semaste{
188254721Semaste    IncrementHitCount();
189254721Semaste
190254721Semaste    if (!IsEnabled())
191254721Semaste        return false;
192254721Semaste
193254721Semaste    if (GetHitCount() <= GetIgnoreCount())
194254721Semaste        return false;
195254721Semaste
196254721Semaste    return true;
197254721Semaste}
198254721Semaste
199254721Semastevoid
200254721SemasteWatchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
201254721Semaste{
202254721Semaste    DumpWithLevel(s, level);
203254721Semaste    return;
204254721Semaste}
205254721Semaste
206254721Semastevoid
207254721SemasteWatchpoint::Dump(Stream *s) const
208254721Semaste{
209254721Semaste    DumpWithLevel(s, lldb::eDescriptionLevelBrief);
210254721Semaste}
211254721Semaste
212254721Semaste// If prefix is NULL, we display the watch id and ignore the prefix altogether.
213254721Semastevoid
214254721SemasteWatchpoint::DumpSnapshots(Stream *s, const char *prefix) const
215254721Semaste{
216254721Semaste    if (!prefix)
217254721Semaste    {
218254721Semaste        s->Printf("\nWatchpoint %u hit:", GetID());
219254721Semaste        prefix = "";
220254721Semaste    }
221254721Semaste
222254721Semaste    if (m_old_value_sp)
223254721Semaste    {
224254721Semaste        s->Printf("\n%sold value: %s", prefix, m_old_value_sp->GetValueAsCString());
225254721Semaste    }
226254721Semaste    if (m_new_value_sp)
227254721Semaste    {
228254721Semaste        s->Printf("\n%snew value: %s", prefix, m_new_value_sp->GetValueAsCString());
229254721Semaste    }
230254721Semaste}
231254721Semaste
232254721Semastevoid
233254721SemasteWatchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
234254721Semaste{
235254721Semaste    if (s == NULL)
236254721Semaste        return;
237254721Semaste
238254721Semaste    assert(description_level >= lldb::eDescriptionLevelBrief &&
239254721Semaste           description_level <= lldb::eDescriptionLevelVerbose);
240254721Semaste
241254721Semaste    s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 " size = %u state = %s type = %s%s",
242254721Semaste              GetID(),
243254721Semaste              GetLoadAddress(),
244254721Semaste              m_byte_size,
245254721Semaste              IsEnabled() ? "enabled" : "disabled",
246254721Semaste              m_watch_read ? "r" : "",
247254721Semaste              m_watch_write ? "w" : "");
248254721Semaste
249254721Semaste    if (description_level >= lldb::eDescriptionLevelFull) {
250254721Semaste        if (!m_decl_str.empty())
251254721Semaste            s->Printf("\n    declare @ '%s'", m_decl_str.c_str());
252254721Semaste        if (!m_watch_spec_str.empty())
253254721Semaste            s->Printf("\n    watchpoint spec = '%s'", m_watch_spec_str.c_str());
254254721Semaste
255254721Semaste        // Dump the snapshots we have taken.
256254721Semaste        DumpSnapshots(s, "    ");
257254721Semaste
258254721Semaste        if (GetConditionText())
259254721Semaste            s->Printf("\n    condition = '%s'", GetConditionText());
260254721Semaste        m_options.GetCallbackDescription(s, description_level);
261254721Semaste    }
262254721Semaste
263254721Semaste    if (description_level >= lldb::eDescriptionLevelVerbose)
264254721Semaste    {
265254721Semaste        s->Printf("\n    hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
266254721Semaste                  GetHardwareIndex(),
267254721Semaste                  GetHitCount(),
268254721Semaste                  GetIgnoreCount());
269254721Semaste    }
270254721Semaste}
271254721Semaste
272254721Semastebool
273254721SemasteWatchpoint::IsEnabled() const
274254721Semaste{
275254721Semaste    return m_enabled;
276254721Semaste}
277254721Semaste
278254721Semaste// Within StopInfo.cpp, we purposely turn on the ephemeral mode right before temporarily disable the watchpoint
279254721Semaste// in order to perform possible watchpoint actions without triggering further watchpoint events.
280254721Semaste// After the temporary disabled watchpoint is enabled, we then turn off the ephemeral mode.
281254721Semaste
282254721Semastevoid
283254721SemasteWatchpoint::TurnOnEphemeralMode()
284254721Semaste{
285254721Semaste    m_is_ephemeral = true;
286254721Semaste}
287254721Semaste
288254721Semastevoid
289254721SemasteWatchpoint::TurnOffEphemeralMode()
290254721Semaste{
291254721Semaste    m_is_ephemeral = false;
292254721Semaste    // Leaving ephemeral mode, reset the m_disabled_count!
293254721Semaste    m_disabled_count = 0;
294254721Semaste}
295254721Semaste
296254721Semastebool
297254721SemasteWatchpoint::IsDisabledDuringEphemeralMode()
298254721Semaste{
299254721Semaste    return m_disabled_count > 1;
300254721Semaste}
301254721Semaste
302254721Semastevoid
303254721SemasteWatchpoint::SetEnabled(bool enabled, bool notify)
304254721Semaste{
305254721Semaste    if (!enabled)
306254721Semaste    {
307254721Semaste        if (!m_is_ephemeral)
308254721Semaste            SetHardwareIndex(LLDB_INVALID_INDEX32);
309254721Semaste        else
310254721Semaste            ++m_disabled_count;
311254721Semaste
312254721Semaste        // Don't clear the snapshots for now.
313254721Semaste        // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
314254721Semaste    }
315254721Semaste    bool changed = enabled != m_enabled;
316254721Semaste    m_enabled = enabled;
317254721Semaste    if (notify && !m_is_ephemeral && changed)
318254721Semaste        SendWatchpointChangedEvent (enabled ? eWatchpointEventTypeEnabled : eWatchpointEventTypeDisabled);
319254721Semaste}
320254721Semaste
321254721Semastevoid
322254721SemasteWatchpoint::SetWatchpointType (uint32_t type, bool notify)
323254721Semaste{
324254721Semaste    int old_watch_read = m_watch_read;
325254721Semaste    int old_watch_write = m_watch_write;
326254721Semaste    m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0;
327254721Semaste    m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0;
328254721Semaste    if (notify && (old_watch_read != m_watch_read || old_watch_write != m_watch_write))
329254721Semaste        SendWatchpointChangedEvent (eWatchpointEventTypeTypeChanged);
330254721Semaste}
331254721Semaste
332254721Semastebool
333254721SemasteWatchpoint::WatchpointRead () const
334254721Semaste{
335254721Semaste    return m_watch_read != 0;
336254721Semaste}
337254721Semastebool
338254721SemasteWatchpoint::WatchpointWrite () const
339254721Semaste{
340254721Semaste    return m_watch_write != 0;
341254721Semaste}
342254721Semasteuint32_t
343254721SemasteWatchpoint::GetIgnoreCount () const
344254721Semaste{
345254721Semaste    return m_ignore_count;
346254721Semaste}
347254721Semaste
348254721Semastevoid
349254721SemasteWatchpoint::SetIgnoreCount (uint32_t n)
350254721Semaste{
351254721Semaste    bool changed = m_ignore_count != n;
352254721Semaste    m_ignore_count = n;
353254721Semaste    if (changed)
354254721Semaste        SendWatchpointChangedEvent (eWatchpointEventTypeIgnoreChanged);
355254721Semaste}
356254721Semaste
357254721Semastebool
358254721SemasteWatchpoint::InvokeCallback (StoppointCallbackContext *context)
359254721Semaste{
360254721Semaste    return m_options.InvokeCallback (context, GetID());
361254721Semaste}
362254721Semaste
363254721Semastevoid
364254721SemasteWatchpoint::SetCondition (const char *condition)
365254721Semaste{
366254721Semaste    if (condition == NULL || condition[0] == '\0')
367254721Semaste    {
368254721Semaste        if (m_condition_ap.get())
369254721Semaste            m_condition_ap.reset();
370254721Semaste    }
371254721Semaste    else
372254721Semaste    {
373254721Semaste        // Pass NULL for expr_prefix (no translation-unit level definitions).
374254721Semaste        m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
375254721Semaste    }
376254721Semaste    SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged);
377254721Semaste}
378254721Semaste
379254721Semasteconst char *
380254721SemasteWatchpoint::GetConditionText () const
381254721Semaste{
382254721Semaste    if (m_condition_ap.get())
383254721Semaste        return m_condition_ap->GetUserText();
384254721Semaste    else
385254721Semaste        return NULL;
386254721Semaste}
387254721Semaste
388254721Semastevoid
389254721SemasteWatchpoint::SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind)
390254721Semaste{
391254721Semaste    if (!m_being_created
392254721Semaste        && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
393254721Semaste    {
394254721Semaste        WatchpointEventData *data = new Watchpoint::WatchpointEventData (eventKind, shared_from_this());
395254721Semaste        GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
396254721Semaste    }
397254721Semaste}
398254721Semaste
399254721Semastevoid
400254721SemasteWatchpoint::SendWatchpointChangedEvent (WatchpointEventData *data)
401254721Semaste{
402254721Semaste
403254721Semaste    if (data == NULL)
404254721Semaste        return;
405254721Semaste
406254721Semaste    if (!m_being_created
407254721Semaste        && GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
408254721Semaste        GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, data);
409254721Semaste    else
410254721Semaste        delete data;
411254721Semaste}
412254721Semaste
413254721SemasteWatchpoint::WatchpointEventData::WatchpointEventData (WatchpointEventType sub_type,
414254721Semaste                                                      const WatchpointSP &new_watchpoint_sp) :
415254721Semaste    EventData (),
416254721Semaste    m_watchpoint_event (sub_type),
417254721Semaste    m_new_watchpoint_sp (new_watchpoint_sp)
418254721Semaste{
419254721Semaste}
420254721Semaste
421254721SemasteWatchpoint::WatchpointEventData::~WatchpointEventData ()
422254721Semaste{
423254721Semaste}
424254721Semaste
425254721Semasteconst ConstString &
426254721SemasteWatchpoint::WatchpointEventData::GetFlavorString ()
427254721Semaste{
428254721Semaste    static ConstString g_flavor ("Watchpoint::WatchpointEventData");
429254721Semaste    return g_flavor;
430254721Semaste}
431254721Semaste
432254721Semasteconst ConstString &
433254721SemasteWatchpoint::WatchpointEventData::GetFlavor () const
434254721Semaste{
435254721Semaste    return WatchpointEventData::GetFlavorString ();
436254721Semaste}
437254721Semaste
438254721Semaste
439254721SemasteWatchpointSP &
440254721SemasteWatchpoint::WatchpointEventData::GetWatchpoint ()
441254721Semaste{
442254721Semaste    return m_new_watchpoint_sp;
443254721Semaste}
444254721Semaste
445254721SemasteWatchpointEventType
446254721SemasteWatchpoint::WatchpointEventData::GetWatchpointEventType () const
447254721Semaste{
448254721Semaste    return m_watchpoint_event;
449254721Semaste}
450254721Semaste
451254721Semastevoid
452254721SemasteWatchpoint::WatchpointEventData::Dump (Stream *s) const
453254721Semaste{
454254721Semaste}
455254721Semaste
456254721Semasteconst Watchpoint::WatchpointEventData *
457254721SemasteWatchpoint::WatchpointEventData::GetEventDataFromEvent (const Event *event)
458254721Semaste{
459254721Semaste    if (event)
460254721Semaste    {
461254721Semaste        const EventData *event_data = event->GetData();
462254721Semaste        if (event_data && event_data->GetFlavor() == WatchpointEventData::GetFlavorString())
463254721Semaste            return static_cast <const WatchpointEventData *> (event->GetData());
464254721Semaste    }
465254721Semaste    return NULL;
466254721Semaste}
467254721Semaste
468254721SemasteWatchpointEventType
469254721SemasteWatchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent (const EventSP &event_sp)
470254721Semaste{
471254721Semaste    const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
472254721Semaste
473254721Semaste    if (data == NULL)
474254721Semaste        return eWatchpointEventTypeInvalidType;
475254721Semaste    else
476254721Semaste        return data->GetWatchpointEventType();
477254721Semaste}
478254721Semaste
479254721SemasteWatchpointSP
480254721SemasteWatchpoint::WatchpointEventData::GetWatchpointFromEvent (const EventSP &event_sp)
481254721Semaste{
482254721Semaste    WatchpointSP wp_sp;
483254721Semaste
484254721Semaste    const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
485254721Semaste    if (data)
486254721Semaste        wp_sp = data->m_new_watchpoint_sp;
487254721Semaste
488254721Semaste    return wp_sp;
489254721Semaste}
490