Johnny Chen | 01a6786 | 2011-10-14 00:42:25 +0000 | [diff] [blame] | 1 | //===-- Watchpoint.cpp ------------------------------------------*- C++ -*-===// |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 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 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 10 | // C Includes |
| 11 | // C++ Includes |
| 12 | // Other libraries and framework includes |
| 13 | // Project includes |
Eugene Zelenko | 16fd751 | 2015-10-30 18:50:12 +0000 | [diff] [blame] | 14 | #include "lldb/Breakpoint/Watchpoint.h" |
| 15 | |
Johnny Chen | 16dcf71 | 2011-10-17 18:58:00 +0000 | [diff] [blame] | 16 | #include "lldb/Breakpoint/StoppointCallbackContext.h" |
Jim Ingham | a7dfb66 | 2012-10-23 07:20:06 +0000 | [diff] [blame] | 17 | #include "lldb/Core/Value.h" |
| 18 | #include "lldb/Core/ValueObject.h" |
| 19 | #include "lldb/Core/ValueObjectMemory.h" |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 20 | #include "lldb/Expression/UserExpression.h" |
Jim Ingham | a7dfb66 | 2012-10-23 07:20:06 +0000 | [diff] [blame] | 21 | #include "lldb/Symbol/ClangASTContext.h" |
Johnny Chen | 16dcf71 | 2011-10-17 18:58:00 +0000 | [diff] [blame] | 22 | #include "lldb/Target/Process.h" |
| 23 | #include "lldb/Target/Target.h" |
| 24 | #include "lldb/Target/ThreadSpec.h" |
Zachary Turner | bf9a773 | 2017-02-02 21:39:50 +0000 | [diff] [blame] | 25 | #include "lldb/Utility/Stream.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 26 | |
| 27 | using namespace lldb; |
| 28 | using namespace lldb_private; |
| 29 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 55 | } |
| 56 | |
Eugene Zelenko | 16fd751 | 2015-10-30 18:50:12 +0000 | [diff] [blame] | 57 | Watchpoint::~Watchpoint() = default; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 58 | |
Johnny Chen | e9a5627 | 2012-08-09 23:09:42 +0000 | [diff] [blame] | 59 | // This function is used when "baton" doesn't need to be freed |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 |
| 63 | // or delete it when it goes goes out of scope. |
Zachary Turner | 4e4fbe8 | 2016-09-13 17:53:38 +0000 | [diff] [blame] | 64 | m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton), |
| 65 | is_synchronous); |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 66 | |
| 67 | SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged); |
Johnny Chen | e9a5627 | 2012-08-09 23:09:42 +0000 | [diff] [blame] | 68 | } |
| 69 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 70 | // This function is used when a baton needs to be freed and therefore is |
Johnny Chen | e9a5627 | 2012-08-09 23:09:42 +0000 | [diff] [blame] | 71 | // contained in a "Baton" subclass. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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); |
Johnny Chen | e9a5627 | 2012-08-09 23:09:42 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 79 | void Watchpoint::ClearCallback() { |
| 80 | m_options.ClearCallback(); |
| 81 | SendWatchpointChangedEvent(eWatchpointEventTypeCommandChanged); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 84 | void Watchpoint::SetDeclInfo(const std::string &str) { m_decl_str = str; } |
Johnny Chen | de6bd24 | 2011-09-16 21:41:42 +0000 | [diff] [blame] | 85 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 86 | std::string Watchpoint::GetWatchSpec() { return m_watch_spec_str; } |
Johnny Chen | 209bd65 | 2012-08-13 21:09:54 +0000 | [diff] [blame] | 87 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 88 | void Watchpoint::SetWatchSpec(const std::string &str) { |
| 89 | m_watch_spec_str = str; |
Johnny Chen | a4d6bc9 | 2012-02-25 06:44:30 +0000 | [diff] [blame] | 90 | } |
| 91 | |
Johnny Chen | fab7a91 | 2012-01-23 23:03:59 +0000 | [diff] [blame] | 92 | // Override default impl of StoppointLocation::IsHardware() since m_is_hardware |
| 93 | // member field is more accurate. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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. |
| 107 | // This works around an assert in 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 | } |
Zachary Turner | 22a2628 | 2016-11-12 18:17:36 +0000 | [diff] [blame] | 112 | m_new_value_sp = ValueObjectMemory::Create( |
| 113 | exe_ctx.GetBestExecutionContextScope(), watch_name.GetStringRef(), |
| 114 | watch_address, m_type); |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 115 | m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name); |
| 116 | return (m_new_value_sp && m_new_value_sp->GetError().Success()); |
Johnny Chen | f04ee93 | 2011-09-22 18:04:58 +0000 | [diff] [blame] | 117 | } |
| 118 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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; |
Jim Ingham | ce0740d | 2012-10-23 21:09:09 +0000 | [diff] [blame] | 128 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 129 | } |
Johnny Chen | 25c0eb4 | 2012-08-14 20:56:37 +0000 | [diff] [blame] | 130 | } |
| 131 | |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 132 | // RETURNS - true if we should stop at this breakpoint, false if we |
| 133 | // should continue. |
| 134 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 135 | bool Watchpoint::ShouldStop(StoppointCallbackContext *context) { |
| 136 | IncrementHitCount(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 137 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 138 | if (!IsEnabled()) |
| 139 | return false; |
Johnny Chen | fd158f4 | 2011-09-21 22:47:15 +0000 | [diff] [blame] | 140 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 141 | return true; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 144 | void Watchpoint::GetDescription(Stream *s, lldb::DescriptionLevel level) { |
| 145 | DumpWithLevel(s, level); |
Johnny Chen | 887062a | 2011-09-12 23:38:44 +0000 | [diff] [blame] | 146 | } |
| 147 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 148 | void Watchpoint::Dump(Stream *s) const { |
| 149 | DumpWithLevel(s, lldb::eDescriptionLevelBrief); |
Johnny Chen | de6bd24 | 2011-09-16 21:41:42 +0000 | [diff] [blame] | 150 | } |
| 151 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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); |
Johnny Chen | 88fc73b | 2012-08-13 23:27:50 +0000 | [diff] [blame] | 168 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 169 | } |
Mohit K. Bhakkad | 18af8a2 | 2015-10-09 15:13:20 +0000 | [diff] [blame] | 170 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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); |
Johnny Chen | 209bd65 | 2012-08-13 21:09:54 +0000 | [diff] [blame] | 179 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 180 | } |
Johnny Chen | 209bd65 | 2012-08-13 21:09:54 +0000 | [diff] [blame] | 181 | } |
| 182 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 183 | void Watchpoint::DumpWithLevel(Stream *s, |
| 184 | lldb::DescriptionLevel description_level) const { |
| 185 | if (s == nullptr) |
| 186 | return; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 187 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 188 | assert(description_level >= lldb::eDescriptionLevelBrief && |
| 189 | description_level <= lldb::eDescriptionLevelVerbose); |
Johnny Chen | de6bd24 | 2011-09-16 21:41:42 +0000 | [diff] [blame] | 190 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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" : ""); |
Johnny Chen | de6bd24 | 2011-09-16 21:41:42 +0000 | [diff] [blame] | 196 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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()); |
Johnny Chen | 209bd65 | 2012-08-13 21:09:54 +0000 | [diff] [blame] | 202 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 203 | // Dump the snapshots we have taken. |
| 204 | DumpSnapshots(s, " "); |
Johnny Chen | 209bd65 | 2012-08-13 21:09:54 +0000 | [diff] [blame] | 205 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 206 | if (GetConditionText()) |
| 207 | s->Printf("\n condition = '%s'", GetConditionText()); |
| 208 | m_options.GetCallbackDescription(s, description_level); |
| 209 | } |
Johnny Chen | de6bd24 | 2011-09-16 21:41:42 +0000 | [diff] [blame] | 210 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 211 | if (description_level >= lldb::eDescriptionLevelVerbose) { |
| 212 | s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u", |
| 213 | GetHardwareIndex(), GetHitCount(), GetIgnoreCount()); |
| 214 | } |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 215 | } |
| 216 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 |
| 221 | // in order to perform possible watchpoint actions without triggering further |
| 222 | // watchpoint events. |
| 223 | // After the temporary disabled watchpoint is enabled, we then turn off the |
| 224 | // ephemeral mode. |
| 225 | |
| 226 | void Watchpoint::TurnOnEphemeralMode() { m_is_ephemeral = true; } |
| 227 | |
| 228 | void Watchpoint::TurnOffEphemeralMode() { |
| 229 | m_is_ephemeral = false; |
| 230 | // Leaving ephemeral mode, reset the m_disabled_count! |
| 231 | m_disabled_count = 0; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 232 | } |
| 233 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 234 | bool Watchpoint::IsDisabledDuringEphemeralMode() { |
Jim Ingham | 209a77d | 2016-10-25 20:34:32 +0000 | [diff] [blame] | 235 | return m_disabled_count > 1 && m_is_ephemeral; |
Johnny Chen | 4fe2302 | 2012-08-21 23:17:04 +0000 | [diff] [blame] | 236 | } |
| 237 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 238 | void Watchpoint::SetEnabled(bool enabled, bool notify) { |
| 239 | if (!enabled) { |
| 240 | if (!m_is_ephemeral) |
| 241 | SetHardwareIndex(LLDB_INVALID_INDEX32); |
Johnny Chen | 16dcf71 | 2011-10-17 18:58:00 +0000 | [diff] [blame] | 242 | else |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 243 | ++m_disabled_count; |
| 244 | |
| 245 | // Don't clear the snapshots for now. |
| 246 | // Within StopInfo.cpp, we purposely do disable/enable watchpoint while |
| 247 | // performing watchpoint actions. |
| 248 | } |
| 249 | bool changed = enabled != m_enabled; |
| 250 | m_enabled = enabled; |
| 251 | if (notify && !m_is_ephemeral && changed) |
| 252 | SendWatchpointChangedEvent(enabled ? eWatchpointEventTypeEnabled |
| 253 | : eWatchpointEventTypeDisabled); |
Johnny Chen | 16dcf71 | 2011-10-17 18:58:00 +0000 | [diff] [blame] | 254 | } |
| 255 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 256 | void Watchpoint::SetWatchpointType(uint32_t type, bool notify) { |
| 257 | int old_watch_read = m_watch_read; |
| 258 | int old_watch_write = m_watch_write; |
| 259 | m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0; |
| 260 | m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0; |
| 261 | if (notify && |
| 262 | (old_watch_read != m_watch_read || old_watch_write != m_watch_write)) |
| 263 | SendWatchpointChangedEvent(eWatchpointEventTypeTypeChanged); |
| 264 | } |
| 265 | |
| 266 | bool Watchpoint::WatchpointRead() const { return m_watch_read != 0; } |
| 267 | |
| 268 | bool Watchpoint::WatchpointWrite() const { return m_watch_write != 0; } |
| 269 | |
| 270 | uint32_t Watchpoint::GetIgnoreCount() const { return m_ignore_count; } |
| 271 | |
| 272 | void Watchpoint::SetIgnoreCount(uint32_t n) { |
| 273 | bool changed = m_ignore_count != n; |
| 274 | m_ignore_count = n; |
| 275 | if (changed) |
| 276 | SendWatchpointChangedEvent(eWatchpointEventTypeIgnoreChanged); |
| 277 | } |
| 278 | |
| 279 | bool Watchpoint::InvokeCallback(StoppointCallbackContext *context) { |
| 280 | return m_options.InvokeCallback(context, GetID()); |
| 281 | } |
| 282 | |
| 283 | void Watchpoint::SetCondition(const char *condition) { |
| 284 | if (condition == nullptr || condition[0] == '\0') { |
Johnny Chen | 16dcf71 | 2011-10-17 18:58:00 +0000 | [diff] [blame] | 285 | if (m_condition_ap.get()) |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 286 | m_condition_ap.reset(); |
| 287 | } else { |
| 288 | // Pass nullptr for expr_prefix (no translation-unit level definitions). |
| 289 | Error error; |
| 290 | m_condition_ap.reset(m_target.GetUserExpressionForLanguage( |
Zachary Turner | c5d7df9 | 2016-11-08 04:52:16 +0000 | [diff] [blame] | 291 | condition, llvm::StringRef(), lldb::eLanguageTypeUnknown, |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 292 | UserExpression::eResultTypeAny, EvaluateExpressionOptions(), error)); |
| 293 | if (error.Fail()) { |
| 294 | // FIXME: Log something... |
| 295 | m_condition_ap.reset(); |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 296 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 297 | } |
| 298 | SendWatchpointChangedEvent(eWatchpointEventTypeConditionChanged); |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 299 | } |
| 300 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 301 | const char *Watchpoint::GetConditionText() const { |
| 302 | if (m_condition_ap.get()) |
| 303 | return m_condition_ap->GetUserText(); |
| 304 | else |
Eugene Zelenko | 16fd751 | 2015-10-30 18:50:12 +0000 | [diff] [blame] | 305 | return nullptr; |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 306 | } |
| 307 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 308 | void Watchpoint::SendWatchpointChangedEvent( |
| 309 | lldb::WatchpointEventType eventKind) { |
| 310 | if (!m_being_created && |
| 311 | GetTarget().EventTypeHasListeners( |
| 312 | Target::eBroadcastBitWatchpointChanged)) { |
| 313 | WatchpointEventData *data = |
| 314 | new Watchpoint::WatchpointEventData(eventKind, shared_from_this()); |
| 315 | GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged, data); |
| 316 | } |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 317 | } |
| 318 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 319 | void Watchpoint::SendWatchpointChangedEvent(WatchpointEventData *data) { |
| 320 | if (data == nullptr) |
| 321 | return; |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 322 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 323 | if (!m_being_created && |
| 324 | GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) |
| 325 | GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged, data); |
| 326 | else |
| 327 | delete data; |
| 328 | } |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 329 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 330 | Watchpoint::WatchpointEventData::WatchpointEventData( |
| 331 | WatchpointEventType sub_type, const WatchpointSP &new_watchpoint_sp) |
| 332 | : EventData(), m_watchpoint_event(sub_type), |
| 333 | m_new_watchpoint_sp(new_watchpoint_sp) {} |
| 334 | |
| 335 | Watchpoint::WatchpointEventData::~WatchpointEventData() = default; |
| 336 | |
| 337 | const ConstString &Watchpoint::WatchpointEventData::GetFlavorString() { |
| 338 | static ConstString g_flavor("Watchpoint::WatchpointEventData"); |
| 339 | return g_flavor; |
| 340 | } |
| 341 | |
| 342 | const ConstString &Watchpoint::WatchpointEventData::GetFlavor() const { |
| 343 | return WatchpointEventData::GetFlavorString(); |
| 344 | } |
| 345 | |
| 346 | WatchpointSP &Watchpoint::WatchpointEventData::GetWatchpoint() { |
| 347 | return m_new_watchpoint_sp; |
| 348 | } |
| 349 | |
| 350 | WatchpointEventType |
| 351 | Watchpoint::WatchpointEventData::GetWatchpointEventType() const { |
| 352 | return m_watchpoint_event; |
| 353 | } |
| 354 | |
| 355 | void Watchpoint::WatchpointEventData::Dump(Stream *s) const {} |
| 356 | |
| 357 | const Watchpoint::WatchpointEventData * |
| 358 | Watchpoint::WatchpointEventData::GetEventDataFromEvent(const Event *event) { |
| 359 | if (event) { |
| 360 | const EventData *event_data = event->GetData(); |
| 361 | if (event_data && |
| 362 | event_data->GetFlavor() == WatchpointEventData::GetFlavorString()) |
| 363 | return static_cast<const WatchpointEventData *>(event->GetData()); |
| 364 | } |
| 365 | return nullptr; |
| 366 | } |
| 367 | |
| 368 | WatchpointEventType |
| 369 | Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent( |
| 370 | const EventSP &event_sp) { |
| 371 | const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get()); |
| 372 | |
| 373 | if (data == nullptr) |
| 374 | return eWatchpointEventTypeInvalidType; |
| 375 | else |
| 376 | return data->GetWatchpointEventType(); |
| 377 | } |
| 378 | |
| 379 | WatchpointSP Watchpoint::WatchpointEventData::GetWatchpointFromEvent( |
| 380 | const EventSP &event_sp) { |
| 381 | WatchpointSP wp_sp; |
| 382 | |
| 383 | const WatchpointEventData *data = GetEventDataFromEvent(event_sp.get()); |
| 384 | if (data) |
| 385 | wp_sp = data->m_new_watchpoint_sp; |
| 386 | |
| 387 | return wp_sp; |
Jim Ingham | 1b5792e | 2012-12-18 02:03:49 +0000 | [diff] [blame] | 388 | } |