181 lines · cpp
1//===-- WatchpointOptions.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/Breakpoint/WatchpointOptions.h"10 11#include "lldb/Breakpoint/StoppointCallbackContext.h"12#include "lldb/Core/Value.h"13#include "lldb/Target/Process.h"14#include "lldb/Target/Target.h"15#include "lldb/Target/ThreadSpec.h"16#include "lldb/Utility/Stream.h"17#include "lldb/Utility/StringList.h"18 19using namespace lldb;20using namespace lldb_private;21 22bool WatchpointOptions::NullCallback(void *baton,23 StoppointCallbackContext *context,24 lldb::user_id_t watch_id) {25 return true;26}27 28// WatchpointOptions constructor29WatchpointOptions::WatchpointOptions()30 : m_callback(WatchpointOptions::NullCallback) {}31 32// WatchpointOptions copy constructor33WatchpointOptions::WatchpointOptions(const WatchpointOptions &rhs)34 : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),35 m_callback_is_synchronous(rhs.m_callback_is_synchronous) {36 if (rhs.m_thread_spec_up != nullptr)37 m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);38}39 40// WatchpointOptions assignment operator41const WatchpointOptions &WatchpointOptions::42operator=(const WatchpointOptions &rhs) {43 m_callback = rhs.m_callback;44 m_callback_baton_sp = rhs.m_callback_baton_sp;45 m_callback_is_synchronous = rhs.m_callback_is_synchronous;46 if (rhs.m_thread_spec_up != nullptr)47 m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);48 return *this;49}50 51WatchpointOptions *52WatchpointOptions::CopyOptionsNoCallback(WatchpointOptions &orig) {53 WatchpointHitCallback orig_callback = orig.m_callback;54 lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;55 bool orig_is_sync = orig.m_callback_is_synchronous;56 57 orig.ClearCallback();58 WatchpointOptions *ret_val = new WatchpointOptions(orig);59 60 orig.SetCallback(orig_callback, orig_callback_baton_sp, orig_is_sync);61 62 return ret_val;63}64 65// Destructor66WatchpointOptions::~WatchpointOptions() = default;67 68// Callbacks69void WatchpointOptions::SetCallback(WatchpointHitCallback callback,70 const BatonSP &callback_baton_sp,71 bool callback_is_synchronous) {72 m_callback_is_synchronous = callback_is_synchronous;73 m_callback = callback;74 m_callback_baton_sp = callback_baton_sp;75}76 77void WatchpointOptions::ClearCallback() {78 m_callback = WatchpointOptions::NullCallback;79 m_callback_is_synchronous = false;80 m_callback_baton_sp.reset();81}82 83Baton *WatchpointOptions::GetBaton() { return m_callback_baton_sp.get(); }84 85const Baton *WatchpointOptions::GetBaton() const {86 return m_callback_baton_sp.get();87}88 89bool WatchpointOptions::InvokeCallback(StoppointCallbackContext *context,90 lldb::user_id_t watch_id) {91 if (m_callback && context->is_synchronous == IsCallbackSynchronous()) {92 return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()93 : nullptr,94 context, watch_id);95 }96 return true;97}98 99bool WatchpointOptions::HasCallback() {100 return m_callback != WatchpointOptions::NullCallback;101}102 103const ThreadSpec *WatchpointOptions::GetThreadSpecNoCreate() const {104 return m_thread_spec_up.get();105}106 107ThreadSpec *WatchpointOptions::GetThreadSpec() {108 if (m_thread_spec_up == nullptr)109 m_thread_spec_up = std::make_unique<ThreadSpec>();110 111 return m_thread_spec_up.get();112}113 114void WatchpointOptions::SetThreadID(lldb::tid_t thread_id) {115 GetThreadSpec()->SetTID(thread_id);116}117 118void WatchpointOptions::GetCallbackDescription(119 Stream *s, lldb::DescriptionLevel level) const {120 if (m_callback_baton_sp.get()) {121 s->EOL();122 m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,123 s->GetIndentLevel());124 }125}126 127void WatchpointOptions::GetDescription(Stream *s,128 lldb::DescriptionLevel level) const {129 // Figure out if there are any options not at their default value, and only130 // print anything if there are:131 132 if ((GetThreadSpecNoCreate() != nullptr &&133 GetThreadSpecNoCreate()->HasSpecification())) {134 if (level == lldb::eDescriptionLevelVerbose) {135 s->EOL();136 s->IndentMore();137 s->Indent();138 s->PutCString("Watchpoint Options:\n");139 s->IndentMore();140 s->Indent();141 } else142 s->PutCString(" Options: ");143 144 if (m_thread_spec_up)145 m_thread_spec_up->GetDescription(s, level);146 else if (level == eDescriptionLevelBrief)147 s->PutCString("thread spec: no ");148 if (level == lldb::eDescriptionLevelFull) {149 s->IndentLess();150 s->IndentMore();151 }152 }153 154 GetCallbackDescription(s, level);155}156 157void WatchpointOptions::CommandBaton::GetDescription(158 llvm::raw_ostream &s, lldb::DescriptionLevel level,159 unsigned indentation) const {160 const CommandData *data = getItem();161 162 if (level == eDescriptionLevelBrief) {163 s << ", commands = %s"164 << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");165 return;166 }167 168 indentation += 2;169 s.indent(indentation);170 s << "watchpoint commands:\n";171 172 indentation += 2;173 if (data && data->user_source.GetSize() > 0) {174 for (const std::string &line : data->user_source) {175 s.indent(indentation);176 s << line << "\n";177 }178 } else179 s << "No commands.\n";180}181