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