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