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/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 int32_t hw_index = -1; 98 99 lldb::WatchpointSP watchpoint_sp(GetSP()); 100 if (watchpoint_sp) { 101 std::lock_guard<std::recursive_mutex> guard( 102 watchpoint_sp->GetTarget().GetAPIMutex()); 103 hw_index = watchpoint_sp->GetHardwareIndex(); 104 } 105 106 return hw_index; 107 } 108 109 addr_t SBWatchpoint::GetWatchAddress() { 110 LLDB_INSTRUMENT_VA(this); 111 112 addr_t ret_addr = LLDB_INVALID_ADDRESS; 113 114 lldb::WatchpointSP watchpoint_sp(GetSP()); 115 if (watchpoint_sp) { 116 std::lock_guard<std::recursive_mutex> guard( 117 watchpoint_sp->GetTarget().GetAPIMutex()); 118 ret_addr = watchpoint_sp->GetLoadAddress(); 119 } 120 121 return ret_addr; 122 } 123 124 size_t SBWatchpoint::GetWatchSize() { 125 LLDB_INSTRUMENT_VA(this); 126 127 size_t watch_size = 0; 128 129 lldb::WatchpointSP watchpoint_sp(GetSP()); 130 if (watchpoint_sp) { 131 std::lock_guard<std::recursive_mutex> guard( 132 watchpoint_sp->GetTarget().GetAPIMutex()); 133 watch_size = watchpoint_sp->GetByteSize(); 134 } 135 136 return watch_size; 137 } 138 139 void SBWatchpoint::SetEnabled(bool enabled) { 140 LLDB_INSTRUMENT_VA(this, enabled); 141 142 lldb::WatchpointSP watchpoint_sp(GetSP()); 143 if (watchpoint_sp) { 144 Target &target = watchpoint_sp->GetTarget(); 145 std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex()); 146 ProcessSP process_sp = target.GetProcessSP(); 147 const bool notify = true; 148 if (process_sp) { 149 if (enabled) 150 process_sp->EnableWatchpoint(watchpoint_sp.get(), notify); 151 else 152 process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); 153 } else { 154 watchpoint_sp->SetEnabled(enabled, notify); 155 } 156 } 157 } 158 159 bool SBWatchpoint::IsEnabled() { 160 LLDB_INSTRUMENT_VA(this); 161 162 lldb::WatchpointSP watchpoint_sp(GetSP()); 163 if (watchpoint_sp) { 164 std::lock_guard<std::recursive_mutex> guard( 165 watchpoint_sp->GetTarget().GetAPIMutex()); 166 return watchpoint_sp->IsEnabled(); 167 } else 168 return false; 169 } 170 171 uint32_t SBWatchpoint::GetHitCount() { 172 LLDB_INSTRUMENT_VA(this); 173 174 uint32_t count = 0; 175 lldb::WatchpointSP watchpoint_sp(GetSP()); 176 if (watchpoint_sp) { 177 std::lock_guard<std::recursive_mutex> guard( 178 watchpoint_sp->GetTarget().GetAPIMutex()); 179 count = watchpoint_sp->GetHitCount(); 180 } 181 182 return count; 183 } 184 185 uint32_t SBWatchpoint::GetIgnoreCount() { 186 LLDB_INSTRUMENT_VA(this); 187 188 lldb::WatchpointSP watchpoint_sp(GetSP()); 189 if (watchpoint_sp) { 190 std::lock_guard<std::recursive_mutex> guard( 191 watchpoint_sp->GetTarget().GetAPIMutex()); 192 return watchpoint_sp->GetIgnoreCount(); 193 } else 194 return 0; 195 } 196 197 void SBWatchpoint::SetIgnoreCount(uint32_t n) { 198 LLDB_INSTRUMENT_VA(this, n); 199 200 lldb::WatchpointSP watchpoint_sp(GetSP()); 201 if (watchpoint_sp) { 202 std::lock_guard<std::recursive_mutex> guard( 203 watchpoint_sp->GetTarget().GetAPIMutex()); 204 watchpoint_sp->SetIgnoreCount(n); 205 } 206 } 207 208 const char *SBWatchpoint::GetCondition() { 209 LLDB_INSTRUMENT_VA(this); 210 211 lldb::WatchpointSP watchpoint_sp(GetSP()); 212 if (watchpoint_sp) { 213 std::lock_guard<std::recursive_mutex> guard( 214 watchpoint_sp->GetTarget().GetAPIMutex()); 215 return watchpoint_sp->GetConditionText(); 216 } 217 return nullptr; 218 } 219 220 void SBWatchpoint::SetCondition(const char *condition) { 221 LLDB_INSTRUMENT_VA(this, condition); 222 223 lldb::WatchpointSP watchpoint_sp(GetSP()); 224 if (watchpoint_sp) { 225 std::lock_guard<std::recursive_mutex> guard( 226 watchpoint_sp->GetTarget().GetAPIMutex()); 227 watchpoint_sp->SetCondition(condition); 228 } 229 } 230 231 bool SBWatchpoint::GetDescription(SBStream &description, 232 DescriptionLevel level) { 233 LLDB_INSTRUMENT_VA(this, description, level); 234 235 Stream &strm = description.ref(); 236 237 lldb::WatchpointSP watchpoint_sp(GetSP()); 238 if (watchpoint_sp) { 239 std::lock_guard<std::recursive_mutex> guard( 240 watchpoint_sp->GetTarget().GetAPIMutex()); 241 watchpoint_sp->GetDescription(&strm, level); 242 strm.EOL(); 243 } else 244 strm.PutCString("No value"); 245 246 return true; 247 } 248 249 void SBWatchpoint::Clear() { 250 LLDB_INSTRUMENT_VA(this); 251 252 m_opaque_wp.reset(); 253 } 254 255 lldb::WatchpointSP SBWatchpoint::GetSP() const { 256 LLDB_INSTRUMENT_VA(this); 257 258 return m_opaque_wp.lock(); 259 } 260 261 void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) { 262 LLDB_INSTRUMENT_VA(this, sp); 263 264 m_opaque_wp = sp; 265 } 266 267 bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) { 268 LLDB_INSTRUMENT_VA(event); 269 270 return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) != 271 nullptr; 272 } 273 274 WatchpointEventType 275 SBWatchpoint::GetWatchpointEventTypeFromEvent(const SBEvent &event) { 276 LLDB_INSTRUMENT_VA(event); 277 278 if (event.IsValid()) 279 return Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent( 280 event.GetSP()); 281 return eWatchpointEventTypeInvalidType; 282 } 283 284 SBWatchpoint SBWatchpoint::GetWatchpointFromEvent(const lldb::SBEvent &event) { 285 LLDB_INSTRUMENT_VA(event); 286 287 SBWatchpoint sb_watchpoint; 288 if (event.IsValid()) 289 sb_watchpoint = 290 Watchpoint::WatchpointEventData::GetWatchpointFromEvent(event.GetSP()); 291 return sb_watchpoint; 292 } 293