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