358 lines · cpp
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-exception6//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 26using namespace lldb;27using namespace lldb_private;28 29SBWatchpoint::SBWatchpoint() { LLDB_INSTRUMENT_VA(this); }30 31SBWatchpoint::SBWatchpoint(const lldb::WatchpointSP &wp_sp)32 : m_opaque_wp(wp_sp) {33 LLDB_INSTRUMENT_VA(this, wp_sp);34}35 36SBWatchpoint::SBWatchpoint(const SBWatchpoint &rhs)37 : m_opaque_wp(rhs.m_opaque_wp) {38 LLDB_INSTRUMENT_VA(this, rhs);39}40 41const 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 48SBWatchpoint::~SBWatchpoint() = default;49 50watch_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 61bool SBWatchpoint::IsValid() const {62 LLDB_INSTRUMENT_VA(this);63 return this->operator bool();64}65SBWatchpoint::operator bool() const {66 LLDB_INSTRUMENT_VA(this);67 68 return bool(m_opaque_wp.lock());69}70 71bool SBWatchpoint::operator==(const SBWatchpoint &rhs) const {72 LLDB_INSTRUMENT_VA(this, rhs);73 74 return GetSP() == rhs.GetSP();75}76 77bool SBWatchpoint::operator!=(const SBWatchpoint &rhs) const {78 LLDB_INSTRUMENT_VA(this, rhs);79 80 return !(*this == rhs);81}82 83SBError 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().Clone());90 }91 return sb_error;92}93 94int32_t SBWatchpoint::GetHardwareIndex() {95 LLDB_INSTRUMENT_VA(this);96 97 // For processes using gdb remote protocol,98 // we cannot determine the hardware breakpoint99 // index reliably; providing possibly correct100 // guesses is not useful to anyone.101 return -1;102}103 104addr_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 119size_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 134void 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 else147 process_sp->DisableWatchpoint(watchpoint_sp, notify);148 } else {149 watchpoint_sp->SetEnabled(enabled, notify);150 }151 }152}153 154bool 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 } else163 return false;164}165 166uint32_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 180uint32_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 } else189 return 0;190}191 192void 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 203const 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 215void 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 226bool 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 } else239 strm.PutCString("No value");240 241 return true;242}243 244void SBWatchpoint::Clear() {245 LLDB_INSTRUMENT_VA(this);246 247 m_opaque_wp.reset();248}249 250lldb::WatchpointSP SBWatchpoint::GetSP() const {251 LLDB_INSTRUMENT_VA(this);252 253 return m_opaque_wp.lock();254}255 256void SBWatchpoint::SetSP(const lldb::WatchpointSP &sp) {257 LLDB_INSTRUMENT_VA(this, sp);258 259 m_opaque_wp = sp;260}261 262bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) {263 LLDB_INSTRUMENT_VA(event);264 265 return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) !=266 nullptr;267}268 269WatchpointEventType270SBWatchpoint::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 279SBWatchpoint 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 289lldb::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 302WatchpointValueKind 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 316const 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 ConstString326 // so that the C string we return has a sufficiently long327 // lifetime. Note this a memory leak but should be fairly328 // low impact.329 return ConstString(watchpoint_sp->GetWatchSpec()).AsCString();330}331 332bool 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 345bool 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