1 //===-- SBWatchpoint.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/API/SBWatchpoint.h" 10 #include "lldb/API/SBAddress.h" 11 #include "lldb/API/SBDebugger.h" 12 #include "lldb/API/SBDefines.h" 13 #include "lldb/API/SBEvent.h" 14 #include "lldb/API/SBStream.h" 15 #include "lldb/Utility/Instrumentation.h" 16 17 #include "lldb/Breakpoint/Watchpoint.h" 18 #include "lldb/Breakpoint/WatchpointList.h" 19 #include "lldb/Core/StreamFile.h" 20 #include "lldb/Symbol/CompilerType.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Utility/Stream.h" 24 #include "lldb/lldb-defines.h" 25 #include "lldb/lldb-types.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 SBWatchpoint::SBWatchpoint() { LLDB_INSTRUMENT_VA(this); } 31 32 SBWatchpoint::SBWatchpoint(const lldb::WatchpointSP &wp_sp) 33 : m_opaque_wp(wp_sp) { 34 LLDB_INSTRUMENT_VA(this, wp_sp); 35 } 36 37 SBWatchpoint::SBWatchpoint(const SBWatchpoint &rhs) 38 : m_opaque_wp(rhs.m_opaque_wp) { 39 LLDB_INSTRUMENT_VA(this, rhs); 40 } 41 42 const SBWatchpoint &SBWatchpoint::operator=(const SBWatchpoint &rhs) { 43 LLDB_INSTRUMENT_VA(this, rhs); 44 45 m_opaque_wp = rhs.m_opaque_wp; 46 return *this; 47 } 48 49 SBWatchpoint::~SBWatchpoint() = default; 50 51 watch_id_t SBWatchpoint::GetID() { 52 LLDB_INSTRUMENT_VA(this); 53 54 watch_id_t watch_id = LLDB_INVALID_WATCH_ID; 55 lldb::WatchpointSP watchpoint_sp(GetSP()); 56 if (watchpoint_sp) 57 watch_id = watchpoint_sp->GetID(); 58 59 return watch_id; 60 } 61 62 bool SBWatchpoint::IsValid() const { 63 LLDB_INSTRUMENT_VA(this); 64 return this->operator bool(); 65 } 66 SBWatchpoint::operator bool() const { 67 LLDB_INSTRUMENT_VA(this); 68 69 return bool(m_opaque_wp.lock()); 70 } 71 72 bool SBWatchpoint::operator==(const SBWatchpoint &rhs) const { 73 LLDB_INSTRUMENT_VA(this, rhs); 74 75 return GetSP() == rhs.GetSP(); 76 } 77 78 bool SBWatchpoint::operator!=(const SBWatchpoint &rhs) const { 79 LLDB_INSTRUMENT_VA(this, rhs); 80 81 return !(*this == rhs); 82 } 83 84 SBError SBWatchpoint::GetError() { 85 LLDB_INSTRUMENT_VA(this); 86 87 SBError sb_error; 88 lldb::WatchpointSP watchpoint_sp(GetSP()); 89 if (watchpoint_sp) { 90 sb_error.SetError(watchpoint_sp->GetError()); 91 } 92 return sb_error; 93 } 94 95 int32_t SBWatchpoint::GetHardwareIndex() { 96 LLDB_INSTRUMENT_VA(this); 97 98 int32_t hw_index = -1; 99 100 lldb::WatchpointSP watchpoint_sp(GetSP()); 101 if (watchpoint_sp) { 102 std::lock_guard<std::recursive_mutex> guard( 103 watchpoint_sp->GetTarget().GetAPIMutex()); 104 hw_index = watchpoint_sp->GetHardwareIndex(); 105 } 106 107 return hw_index; 108 } 109 110 addr_t SBWatchpoint::GetWatchAddress() { 111 LLDB_INSTRUMENT_VA(this); 112 113 addr_t ret_addr = LLDB_INVALID_ADDRESS; 114 115 lldb::WatchpointSP watchpoint_sp(GetSP()); 116 if (watchpoint_sp) { 117 std::lock_guard<std::recursive_mutex> guard( 118 watchpoint_sp->GetTarget().GetAPIMutex()); 119 ret_addr = watchpoint_sp->GetLoadAddress(); 120 } 121 122 return ret_addr; 123 } 124 125 size_t SBWatchpoint::GetWatchSize() { 126 LLDB_INSTRUMENT_VA(this); 127 128 size_t watch_size = 0; 129 130 lldb::WatchpointSP watchpoint_sp(GetSP()); 131 if (watchpoint_sp) { 132 std::lock_guard<std::recursive_mutex> guard( 133 watchpoint_sp->GetTarget().GetAPIMutex()); 134 watch_size = watchpoint_sp->GetByteSize(); 135 } 136 137 return watch_size; 138 } 139 140 void SBWatchpoint::SetEnabled(bool enabled) { 141 LLDB_INSTRUMENT_VA(this, enabled); 142 143 lldb::WatchpointSP watchpoint_sp(GetSP()); 144 if (watchpoint_sp) { 145 Target &target = watchpoint_sp->GetTarget(); 146 std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex()); 147 ProcessSP process_sp = target.GetProcessSP(); 148 const bool notify = true; 149 if (process_sp) { 150 if (enabled) 151 process_sp->EnableWatchpoint(watchpoint_sp.get(), notify); 152 else 153 process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); 154 } else { 155 watchpoint_sp->SetEnabled(enabled, notify); 156 } 157 } 158 } 159 160 bool SBWatchpoint::IsEnabled() { 161 LLDB_INSTRUMENT_VA(this); 162 163 lldb::WatchpointSP watchpoint_sp(GetSP()); 164 if (watchpoint_sp) { 165 std::lock_guard<std::recursive_mutex> guard( 166 watchpoint_sp->GetTarget().GetAPIMutex()); 167 return watchpoint_sp->IsEnabled(); 168 } else 169 return false; 170 } 171 172 uint32_t SBWatchpoint::GetHitCount() { 173 LLDB_INSTRUMENT_VA(this); 174 175 uint32_t count = 0; 176 lldb::WatchpointSP watchpoint_sp(GetSP()); 177 if (watchpoint_sp) { 178 std::lock_guard<std::recursive_mutex> guard( 179 watchpoint_sp->GetTarget().GetAPIMutex()); 180 count = watchpoint_sp->GetHitCount(); 181 } 182 183 return count; 184 } 185 186 uint32_t SBWatchpoint::GetIgnoreCount() { 187 LLDB_INSTRUMENT_VA(this); 188 189 lldb::WatchpointSP watchpoint_sp(GetSP()); 190 if (watchpoint_sp) { 191 std::lock_guard<std::recursive_mutex> guard( 192 watchpoint_sp->GetTarget().GetAPIMutex()); 193 return watchpoint_sp->GetIgnoreCount(); 194 } else 195 return 0; 196 } 197 198 void SBWatchpoint::SetIgnoreCount(uint32_t n) { 199 LLDB_INSTRUMENT_VA(this, n); 200 201 lldb::WatchpointSP watchpoint_sp(GetSP()); 202 if (watchpoint_sp) { 203 std::lock_guard<std::recursive_mutex> guard( 204 watchpoint_sp->GetTarget().GetAPIMutex()); 205 watchpoint_sp->SetIgnoreCount(n); 206 } 207 } 208 209 const char *SBWatchpoint::GetCondition() { 210 LLDB_INSTRUMENT_VA(this); 211 212 lldb::WatchpointSP watchpoint_sp(GetSP()); 213 if (!watchpoint_sp) 214 return nullptr; 215 216 std::lock_guard<std::recursive_mutex> guard( 217 watchpoint_sp->GetTarget().GetAPIMutex()); 218 return ConstString(watchpoint_sp->GetConditionText()).GetCString(); 219 } 220 221 void SBWatchpoint::SetCondition(const char *condition) { 222 LLDB_INSTRUMENT_VA(this, condition); 223 224 lldb::WatchpointSP watchpoint_sp(GetSP()); 225 if (watchpoint_sp) { 226 std::lock_guard<std::recursive_mutex> guard( 227 watchpoint_sp->GetTarget().GetAPIMutex()); 228 watchpoint_sp->SetCondition(condition); 229 } 230 } 231 232 bool SBWatchpoint::GetDescription(SBStream &description, 233 DescriptionLevel level) { 234 LLDB_INSTRUMENT_VA(this, description, level); 235 236 Stream &strm = description.ref(); 237 238 lldb::WatchpointSP watchpoint_sp(GetSP()); 239 if (watchpoint_sp) { 240 std::lock_guard<std::recursive_mutex> guard( 241 watchpoint_sp->GetTarget().GetAPIMutex()); 242 watchpoint_sp->GetDescription(&strm, level); 243 strm.EOL(); 244 } else 245 strm.PutCString("No value"); 246 247 return true; 248 } 249 250 void SBWatchpoint::Clear() { 251 LLDB_INSTRUMENT_VA(this); 252 253 m_opaque_wp.reset(); 254 } 255 256 lldb::WatchpointSP SBWatchpoint::GetSP() const { 257 LLDB_INSTRUMENT_VA(this); 258 259 return m_opaque_wp.lock(); 260 } 261 262 void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) { 263 LLDB_INSTRUMENT_VA(this, sp); 264 265 m_opaque_wp = sp; 266 } 267 268 bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) { 269 LLDB_INSTRUMENT_VA(event); 270 271 return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) != 272 nullptr; 273 } 274 275 WatchpointEventType 276 SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) { 277 LLDB_INSTRUMENT_VA(event); 278 279 if (event.IsValid()) 280 return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent( 281 event.GetSP()); 282 return eWatchpointEventTypeInvalidType; 283 } 284 285 SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) { 286 LLDB_INSTRUMENT_VA(event); 287 288 SBWatchpoint sb_watchpoint; 289 if (event.IsValid()) 290 sb_watchpoint = 291 Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP()); 292 return sb_watchpoint; 293 } 294 295 lldb::SBType SBWatchpoint::GetType() { 296 LLDB_INSTRUMENT_VA(this); 297 298 lldb::WatchpointSP watchpoint_sp(GetSP()); 299 if (watchpoint_sp) { 300 std::lock_guard<std::recursive_mutex> guard( 301 watchpoint_sp->GetTarget().GetAPIMutex()); 302 const CompilerType &type = watchpoint_sp->GetCompilerType(); 303 return lldb::SBType(type); 304 } 305 return lldb::SBType(); 306 } 307 308 WatchpointValueKind SBWatchpoint::GetWatchValueKind() { 309 LLDB_INSTRUMENT_VA(this); 310 311 lldb::WatchpointSP watchpoint_sp(GetSP()); 312 if (watchpoint_sp) { 313 std::lock_guard<std::recursive_mutex> guard( 314 watchpoint_sp->GetTarget().GetAPIMutex()); 315 if (watchpoint_sp->IsWatchVariable()) 316 return WatchpointValueKind::eWatchPointValueKindVariable; 317 return WatchpointValueKind::eWatchPointValueKindExpression; 318 } 319 return WatchpointValueKind::eWatchPointValueKindInvalid; 320 } 321 322 const char *SBWatchpoint::GetWatchSpec() { 323 LLDB_INSTRUMENT_VA(this); 324 325 lldb::WatchpointSP watchpoint_sp(GetSP()); 326 if (!watchpoint_sp) 327 return nullptr; 328 329 std::lock_guard<std::recursive_mutex> guard( 330 watchpoint_sp->GetTarget().GetAPIMutex()); 331 // Store the result of `GetWatchSpec()` as a ConstString 332 // so that the C string we return has a sufficiently long 333 // lifetime. Note this a memory leak but should be fairly 334 // low impact. 335 return ConstString(watchpoint_sp->GetWatchSpec()).AsCString(); 336 } 337 338 bool SBWatchpoint::IsWatchingReads() { 339 LLDB_INSTRUMENT_VA(this); 340 lldb::WatchpointSP watchpoint_sp(GetSP()); 341 if (watchpoint_sp) { 342 std::lock_guard<std::recursive_mutex> guard( 343 watchpoint_sp->GetTarget().GetAPIMutex()); 344 345 return watchpoint_sp->WatchpointRead(); 346 } 347 348 return false; 349 } 350 351 bool SBWatchpoint::IsWatchingWrites() { 352 LLDB_INSTRUMENT_VA(this); 353 lldb::WatchpointSP watchpoint_sp(GetSP()); 354 if (watchpoint_sp) { 355 std::lock_guard<std::recursive_mutex> guard( 356 watchpoint_sp->GetTarget().GetAPIMutex()); 357 358 return watchpoint_sp->WatchpointWrite(); 359 } 360 361 return false; 362 } 363