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