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