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/Value.h" 18 #include "lldb/Core/ValueObject.h" 19 #include "lldb/Core/ValueObjectMemory.h" 20 #include "lldb/Expression/UserExpression.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/Utility/Stream.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size, 31 const CompilerType *type, bool hardware) 32 : StoppointLocation(0, addr, size, hardware), m_target(target), 33 m_enabled(false), m_is_hardware(hardware), m_is_watch_variable(false), 34 m_is_ephemeral(false), m_disabled_count(0), m_watch_read(0), 35 m_watch_write(0), m_watch_was_read(0), m_watch_was_written(0), 36 m_ignore_count(0), m_false_alarms(0), m_decl_str(), m_watch_spec_str(), 37 m_type(), m_error(), m_options(), m_being_created(true) { 38 if (type && type->IsValid()) 39 m_type = *type; 40 else { 41 // If we don't have a known type, then we force it to unsigned int of the 42 // right size. 43 ClangASTContext *ast_context = target.GetScratchClangASTContext(); 44 m_type = ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 45 8 * size); 46 } 47 48 // Set the initial value of the watched variable: 49 if (m_target.GetProcessSP()) { 50 ExecutionContext exe_ctx; 51 m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx); 52 CaptureWatchedValue(exe_ctx); 53 } 54 m_being_created = false; 55 } 56 57 Watchpoint::~Watchpoint() = default; 58 59 // This function is used when "baton" doesn't need to be freed 60 void Watchpoint::SetCallback(WatchpointHitCallback callback, void *baton, 61 bool is_synchronous) { 62 // The default "Baton" class will keep a copy of "baton" and won't free or 63 // delete it when it goes goes out of scope. 64 m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton), 65 is_synchronous); 66 67 SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged); 68 } 69 70 // This function is used when a baton needs to be freed and therefore is 71 // contained in a "Baton" subclass. 72 void Watchpoint::SetCallback(WatchpointHitCallback callback, 73 const BatonSP &callback_baton_sp, 74 bool is_synchronous) { 75 m_options.SetCallback(callback, callback_baton_sp, is_synchronous); 76 SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged); 77 } 78 79 void Watchpoint::ClearCallback() { 80 m_options.ClearCallback(); 81 SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged); 82 } 83 84 void Watchpoint::SetDeclInfo(const std::string &str) { m_decl_str = str; } 85 86 std::string Watchpoint::GetWatchSpec() { return m_watch_spec_str; } 87 88 void Watchpoint::SetWatchSpec(const std::string &str) { 89 m_watch_spec_str = str; 90 } 91 92 // Override default impl of StoppointLocation::IsHardware() since m_is_hardware 93 // member field is more accurate. 94 bool Watchpoint::IsHardware() const { return m_is_hardware; } 95 96 bool Watchpoint::IsWatchVariable() const { return m_is_watch_variable; } 97 98 void Watchpoint::SetWatchVariable(bool val) { m_is_watch_variable = val; } 99 100 bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) { 101 ConstString watch_name("$__lldb__watch_value"); 102 m_old_value_sp = m_new_value_sp; 103 Address watch_address(GetLoadAddress()); 104 if (!m_type.IsValid()) { 105 // Don't know how to report new & old values, since we couldn't make a 106 // scalar type for this watchpoint. This works around an assert in 107 // ValueObjectMemory::Create. 108 // FIXME: This should not happen, but if it does in some case we care about, 109 // we can go grab the value raw and print it as unsigned. 110 return false; 111 } 112 m_new_value_sp = ValueObjectMemory::Create( 113 exe_ctx.GetBestExecutionContextScope(), watch_name.GetStringRef(), 114 watch_address, m_type); 115 m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name); 116 return (m_new_value_sp && m_new_value_sp->GetError().Success()); 117 } 118 119 void Watchpoint::IncrementFalseAlarmsAndReviseHitCount() { 120 ++m_false_alarms; 121 if (m_false_alarms) { 122 if (m_hit_count >= m_false_alarms) { 123 m_hit_count -= m_false_alarms; 124 m_false_alarms = 0; 125 } else { 126 m_false_alarms -= m_hit_count; 127 m_hit_count = 0; 128 } 129 } 130 } 131 132 // RETURNS - true if we should stop at this breakpoint, false if we 133 // should continue. 134 135 bool Watchpoint::ShouldStop(StoppointCallbackContext *context) { 136 IncrementHitCount(); 137 138 if (!IsEnabled()) 139 return false; 140 141 return true; 142 } 143 144 void Watchpoint::GetDescription(Stream *s, lldb::DescriptionLevel level) { 145 DumpWithLevel(s, level); 146 } 147 148 void Watchpoint::Dump(Stream *s) const { 149 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 150 } 151 152 // If prefix is nullptr, we display the watch id and ignore the prefix 153 // altogether. 154 void Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const { 155 if (!prefix) { 156 s->Printf("\nWatchpoint %u hit:", GetID()); 157 prefix = ""; 158 } 159 160 if (m_old_value_sp) { 161 const char *old_value_cstr = m_old_value_sp->GetValueAsCString(); 162 if (old_value_cstr && old_value_cstr[0]) 163 s->Printf("\n%sold value: %s", prefix, old_value_cstr); 164 else { 165 const char *old_summary_cstr = m_old_value_sp->GetSummaryAsCString(); 166 if (old_summary_cstr && old_summary_cstr[0]) 167 s->Printf("\n%sold value: %s", prefix, old_summary_cstr); 168 } 169 } 170 171 if (m_new_value_sp) { 172 const char *new_value_cstr = m_new_value_sp->GetValueAsCString(); 173 if (new_value_cstr && new_value_cstr[0]) 174 s->Printf("\n%snew value: %s", prefix, new_value_cstr); 175 else { 176 const char *new_summary_cstr = m_new_value_sp->GetSummaryAsCString(); 177 if (new_summary_cstr && new_summary_cstr[0]) 178 s->Printf("\n%snew value: %s", prefix, new_summary_cstr); 179 } 180 } 181 } 182 183 void Watchpoint::DumpWithLevel(Stream *s, 184 lldb::DescriptionLevel description_level) const { 185 if (s == nullptr) 186 return; 187 188 assert(description_level >= lldb::eDescriptionLevelBrief && 189 description_level <= lldb::eDescriptionLevelVerbose); 190 191 s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 192 " size = %u state = %s type = %s%s", 193 GetID(), GetLoadAddress(), m_byte_size, 194 IsEnabled() ? "enabled" : "disabled", m_watch_read ? "r" : "", 195 m_watch_write ? "w" : ""); 196 197 if (description_level >= lldb::eDescriptionLevelFull) { 198 if (!m_decl_str.empty()) 199 s->Printf("\n declare @ '%s'", m_decl_str.c_str()); 200 if (!m_watch_spec_str.empty()) 201 s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str()); 202 203 // Dump the snapshots we have taken. 204 DumpSnapshots(s, " "); 205 206 if (GetConditionText()) 207 s->Printf("\n condition = '%s'", GetConditionText()); 208 m_options.GetCallbackDescription(s, description_level); 209 } 210 211 if (description_level >= lldb::eDescriptionLevelVerbose) { 212 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u", 213 GetHardwareIndex(), GetHitCount(), GetIgnoreCount()); 214 } 215 } 216 217 bool Watchpoint::IsEnabled() const { return m_enabled; } 218 219 // Within StopInfo.cpp, we purposely turn on the ephemeral mode right before 220 // temporarily disable the watchpoint in order to perform possible watchpoint 221 // actions without triggering further watchpoint events. After the temporary 222 // disabled watchpoint is enabled, we then turn off the ephemeral mode. 223 224 void Watchpoint::TurnOnEphemeralMode() { m_is_ephemeral = true; } 225 226 void Watchpoint::TurnOffEphemeralMode() { 227 m_is_ephemeral = false; 228 // Leaving ephemeral mode, reset the m_disabled_count! 229 m_disabled_count = 0; 230 } 231 232 bool Watchpoint::IsDisabledDuringEphemeralMode() { 233 return m_disabled_count > 1 && m_is_ephemeral; 234 } 235 236 void Watchpoint::SetEnabled(bool enabled, bool notify) { 237 if (!enabled) { 238 if (!m_is_ephemeral) 239 SetHardwareIndex(LLDB_INVALID_INDEX32); 240 else 241 ++m_disabled_count; 242 243 // Don't clear the snapshots for now. 244 // Within StopInfo.cpp, we purposely do disable/enable watchpoint while 245 // performing watchpoint actions. 246 } 247 bool changed = enabled != m_enabled; 248 m_enabled = enabled; 249 if (notify && !m_is_ephemeral && changed) 250 SendWatchpointChangedEvent(enabled ? eWatchpointEventTypeEnabled 251 : eWatchpointEventTypeDisabled); 252 } 253 254 void Watchpoint::SetWatchpointType(uint32_t type, bool notify) { 255 int old_watch_read = m_watch_read; 256 int old_watch_write = m_watch_write; 257 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0; 258 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0; 259 if (notify && 260 (old_watch_read != m_watch_read || old_watch_write != m_watch_write)) 261 SendWatchpointChangedEvent(eWatchpointEventTypeTypeChanged); 262 } 263 264 bool Watchpoint::WatchpointRead() const { return m_watch_read != 0; } 265 266 bool Watchpoint::WatchpointWrite() const { return m_watch_write != 0; } 267 268 uint32_t Watchpoint::GetIgnoreCount() const { return m_ignore_count; } 269 270 void Watchpoint::SetIgnoreCount(uint32_t n) { 271 bool changed = m_ignore_count != n; 272 m_ignore_count = n; 273 if (changed) 274 SendWatchpointChangedEvent(eWatchpointEventTypeIgnoreChanged); 275 } 276 277 bool Watchpoint::InvokeCallback(StoppointCallbackContext *context) { 278 return m_options.InvokeCallback(context, GetID()); 279 } 280 281 void Watchpoint::SetCondition(const char *condition) { 282 if (condition == nullptr || condition[0] == '\0') { 283 if (m_condition_ap.get()) 284 m_condition_ap.reset(); 285 } else { 286 // Pass nullptr for expr_prefix (no translation-unit level definitions). 287 Status error; 288 m_condition_ap.reset(m_target.GetUserExpressionForLanguage( 289 condition, llvm::StringRef(), lldb::eLanguageTypeUnknown, 290 UserExpression::eResultTypeAny, EvaluateExpressionOptions(), error)); 291 if (error.Fail()) { 292 // FIXME: Log something... 293 m_condition_ap.reset(); 294 } 295 } 296 SendWatchpointChangedEvent(eWatchpointEventTypeConditionChanged); 297 } 298 299 const char *Watchpoint::GetConditionText() const { 300 if (m_condition_ap.get()) 301 return m_condition_ap->GetUserText(); 302 else 303 return nullptr; 304 } 305 306 void Watchpoint::SendWatchpointChangedEvent( 307 lldb::WatchpointEventType eventKind) { 308 if (!m_being_created && 309 GetTarget().EventTypeHasListeners( 310 Target::eBroadcastBitWatchpointChanged)) { 311 WatchpointEventData *data = 312 new Watchpoint::WatchpointEventData(eventKind, shared_from_this()); 313 GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged, data); 314 } 315 } 316 317 void Watchpoint::SendWatchpointChangedEvent(WatchpointEventData *data) { 318 if (data == nullptr) 319 return; 320 321 if (!m_being_created && 322 GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) 323 GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged, data); 324 else 325 delete data; 326 } 327 328 Watchpoint::WatchpointEventData::WatchpointEventData( 329 WatchpointEventType sub_type, const WatchpointSP &new_watchpoint_sp) 330 : EventData(), m_watchpoint_event(sub_type), 331 m_new_watchpoint_sp(new_watchpoint_sp) {} 332 333 Watchpoint::WatchpointEventData::~WatchpointEventData() = default; 334 335 const ConstString &Watchpoint::WatchpointEventData::GetFlavorString() { 336 static ConstString g_flavor("Watchpoint::WatchpointEventData"); 337 return g_flavor; 338 } 339 340 const ConstString &Watchpoint::WatchpointEventData::GetFlavor() const { 341 return WatchpointEventData::GetFlavorString(); 342 } 343 344 WatchpointSP &Watchpoint::WatchpointEventData::GetWatchpoint() { 345 return m_new_watchpoint_sp; 346 } 347 348 WatchpointEventType 349 Watchpoint::WatchpointEventData::GetWatchpointEventType() const { 350 return m_watchpoint_event; 351 } 352 353 void Watchpoint::WatchpointEventData::Dump(Stream *s) const {} 354 355 const Watchpoint::WatchpointEventData * 356 Watchpoint::WatchpointEventData::GetEventDataFromEvent(const Event *event) { 357 if (event) { 358 const EventData *event_data = event->GetData(); 359 if (event_data && 360 event_data->GetFlavor() == WatchpointEventData::GetFlavorString()) 361 return static_cast<const WatchpointEventData *>(event->GetData()); 362 } 363 return nullptr; 364 } 365 366 WatchpointEventType 367 Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent( 368 const EventSP &event_sp) { 369 const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get()); 370 371 if (data == nullptr) 372 return eWatchpointEventTypeInvalidType; 373 else 374 return data->GetWatchpointEventType(); 375 } 376 377 WatchpointSP Watchpoint::WatchpointEventData::GetWatchpointFromEvent( 378 const EventSP &event_sp) { 379 WatchpointSP wp_sp; 380 381 const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get()); 382 if (data) 383 wp_sp = data->m_new_watchpoint_sp; 384 385 return wp_sp; 386 } 387