1dda28197Spatrick //===-- WatchpointOptions.cpp ---------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Breakpoint/WatchpointOptions.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Breakpoint/StoppointCallbackContext.h"
12061da546Spatrick #include "lldb/Core/Value.h"
13061da546Spatrick #include "lldb/Target/Process.h"
14061da546Spatrick #include "lldb/Target/Target.h"
15061da546Spatrick #include "lldb/Target/ThreadSpec.h"
16061da546Spatrick #include "lldb/Utility/Stream.h"
17061da546Spatrick #include "lldb/Utility/StringList.h"
18061da546Spatrick
19061da546Spatrick using namespace lldb;
20061da546Spatrick using namespace lldb_private;
21061da546Spatrick
NullCallback(void * baton,StoppointCallbackContext * context,lldb::user_id_t watch_id)22061da546Spatrick bool WatchpointOptions::NullCallback(void *baton,
23061da546Spatrick StoppointCallbackContext *context,
24061da546Spatrick lldb::user_id_t watch_id) {
25061da546Spatrick return true;
26061da546Spatrick }
27061da546Spatrick
28061da546Spatrick // WatchpointOptions constructor
WatchpointOptions()29061da546Spatrick WatchpointOptions::WatchpointOptions()
30*f6aab3d8Srobert : m_callback(WatchpointOptions::NullCallback) {}
31061da546Spatrick
32061da546Spatrick // WatchpointOptions copy constructor
WatchpointOptions(const WatchpointOptions & rhs)33061da546Spatrick WatchpointOptions::WatchpointOptions(const WatchpointOptions &rhs)
34061da546Spatrick : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
35*f6aab3d8Srobert m_callback_is_synchronous(rhs.m_callback_is_synchronous) {
36061da546Spatrick if (rhs.m_thread_spec_up != nullptr)
37dda28197Spatrick m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
38061da546Spatrick }
39061da546Spatrick
40061da546Spatrick // WatchpointOptions assignment operator
41061da546Spatrick const WatchpointOptions &WatchpointOptions::
operator =(const WatchpointOptions & rhs)42061da546Spatrick operator=(const WatchpointOptions &rhs) {
43061da546Spatrick m_callback = rhs.m_callback;
44061da546Spatrick m_callback_baton_sp = rhs.m_callback_baton_sp;
45061da546Spatrick m_callback_is_synchronous = rhs.m_callback_is_synchronous;
46061da546Spatrick if (rhs.m_thread_spec_up != nullptr)
47dda28197Spatrick m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
48061da546Spatrick return *this;
49061da546Spatrick }
50061da546Spatrick
51061da546Spatrick WatchpointOptions *
CopyOptionsNoCallback(WatchpointOptions & orig)52061da546Spatrick WatchpointOptions::CopyOptionsNoCallback(WatchpointOptions &orig) {
53061da546Spatrick WatchpointHitCallback orig_callback = orig.m_callback;
54061da546Spatrick lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
55061da546Spatrick bool orig_is_sync = orig.m_callback_is_synchronous;
56061da546Spatrick
57061da546Spatrick orig.ClearCallback();
58061da546Spatrick WatchpointOptions *ret_val = new WatchpointOptions(orig);
59061da546Spatrick
60061da546Spatrick orig.SetCallback(orig_callback, orig_callback_baton_sp, orig_is_sync);
61061da546Spatrick
62061da546Spatrick return ret_val;
63061da546Spatrick }
64061da546Spatrick
65061da546Spatrick // Destructor
66061da546Spatrick WatchpointOptions::~WatchpointOptions() = default;
67061da546Spatrick
68061da546Spatrick // Callbacks
SetCallback(WatchpointHitCallback callback,const BatonSP & callback_baton_sp,bool callback_is_synchronous)69061da546Spatrick void WatchpointOptions::SetCallback(WatchpointHitCallback callback,
70061da546Spatrick const BatonSP &callback_baton_sp,
71061da546Spatrick bool callback_is_synchronous) {
72061da546Spatrick m_callback_is_synchronous = callback_is_synchronous;
73061da546Spatrick m_callback = callback;
74061da546Spatrick m_callback_baton_sp = callback_baton_sp;
75061da546Spatrick }
76061da546Spatrick
ClearCallback()77061da546Spatrick void WatchpointOptions::ClearCallback() {
78061da546Spatrick m_callback = WatchpointOptions::NullCallback;
79061da546Spatrick m_callback_is_synchronous = false;
80061da546Spatrick m_callback_baton_sp.reset();
81061da546Spatrick }
82061da546Spatrick
GetBaton()83061da546Spatrick Baton *WatchpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
84061da546Spatrick
GetBaton() const85061da546Spatrick const Baton *WatchpointOptions::GetBaton() const {
86061da546Spatrick return m_callback_baton_sp.get();
87061da546Spatrick }
88061da546Spatrick
InvokeCallback(StoppointCallbackContext * context,lldb::user_id_t watch_id)89061da546Spatrick bool WatchpointOptions::InvokeCallback(StoppointCallbackContext *context,
90061da546Spatrick lldb::user_id_t watch_id) {
91061da546Spatrick if (m_callback && context->is_synchronous == IsCallbackSynchronous()) {
92061da546Spatrick return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
93061da546Spatrick : nullptr,
94061da546Spatrick context, watch_id);
95061da546Spatrick } else
96061da546Spatrick return true;
97061da546Spatrick }
98061da546Spatrick
HasCallback()99061da546Spatrick bool WatchpointOptions::HasCallback() {
100061da546Spatrick return m_callback != WatchpointOptions::NullCallback;
101061da546Spatrick }
102061da546Spatrick
GetThreadSpecNoCreate() const103061da546Spatrick const ThreadSpec *WatchpointOptions::GetThreadSpecNoCreate() const {
104061da546Spatrick return m_thread_spec_up.get();
105061da546Spatrick }
106061da546Spatrick
GetThreadSpec()107061da546Spatrick ThreadSpec *WatchpointOptions::GetThreadSpec() {
108061da546Spatrick if (m_thread_spec_up == nullptr)
109dda28197Spatrick m_thread_spec_up = std::make_unique<ThreadSpec>();
110061da546Spatrick
111061da546Spatrick return m_thread_spec_up.get();
112061da546Spatrick }
113061da546Spatrick
SetThreadID(lldb::tid_t thread_id)114061da546Spatrick void WatchpointOptions::SetThreadID(lldb::tid_t thread_id) {
115061da546Spatrick GetThreadSpec()->SetTID(thread_id);
116061da546Spatrick }
117061da546Spatrick
GetCallbackDescription(Stream * s,lldb::DescriptionLevel level) const118061da546Spatrick void WatchpointOptions::GetCallbackDescription(
119061da546Spatrick Stream *s, lldb::DescriptionLevel level) const {
120061da546Spatrick if (m_callback_baton_sp.get()) {
121061da546Spatrick s->EOL();
122061da546Spatrick m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
123061da546Spatrick s->GetIndentLevel());
124061da546Spatrick }
125061da546Spatrick }
126061da546Spatrick
GetDescription(Stream * s,lldb::DescriptionLevel level) const127061da546Spatrick void WatchpointOptions::GetDescription(Stream *s,
128061da546Spatrick lldb::DescriptionLevel level) const {
129061da546Spatrick // Figure out if there are any options not at their default value, and only
130061da546Spatrick // print anything if there are:
131061da546Spatrick
132061da546Spatrick if ((GetThreadSpecNoCreate() != nullptr &&
133061da546Spatrick GetThreadSpecNoCreate()->HasSpecification())) {
134061da546Spatrick if (level == lldb::eDescriptionLevelVerbose) {
135061da546Spatrick s->EOL();
136061da546Spatrick s->IndentMore();
137061da546Spatrick s->Indent();
138061da546Spatrick s->PutCString("Watchpoint Options:\n");
139061da546Spatrick s->IndentMore();
140061da546Spatrick s->Indent();
141061da546Spatrick } else
142061da546Spatrick s->PutCString(" Options: ");
143061da546Spatrick
144061da546Spatrick if (m_thread_spec_up)
145061da546Spatrick m_thread_spec_up->GetDescription(s, level);
146061da546Spatrick else if (level == eDescriptionLevelBrief)
147061da546Spatrick s->PutCString("thread spec: no ");
148061da546Spatrick if (level == lldb::eDescriptionLevelFull) {
149061da546Spatrick s->IndentLess();
150061da546Spatrick s->IndentMore();
151061da546Spatrick }
152061da546Spatrick }
153061da546Spatrick
154061da546Spatrick GetCallbackDescription(s, level);
155061da546Spatrick }
156061da546Spatrick
GetDescription(llvm::raw_ostream & s,lldb::DescriptionLevel level,unsigned indentation) const157061da546Spatrick void WatchpointOptions::CommandBaton::GetDescription(
158061da546Spatrick llvm::raw_ostream &s, lldb::DescriptionLevel level,
159061da546Spatrick unsigned indentation) const {
160061da546Spatrick const CommandData *data = getItem();
161061da546Spatrick
162061da546Spatrick if (level == eDescriptionLevelBrief) {
163061da546Spatrick s << ", commands = %s"
164061da546Spatrick << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
165061da546Spatrick return;
166061da546Spatrick }
167061da546Spatrick
168061da546Spatrick indentation += 2;
169061da546Spatrick s.indent(indentation);
170061da546Spatrick s << "watchpoint commands:\n";
171061da546Spatrick
172061da546Spatrick indentation += 2;
173061da546Spatrick if (data && data->user_source.GetSize() > 0) {
174061da546Spatrick for (const std::string &line : data->user_source) {
175061da546Spatrick s.indent(indentation);
176061da546Spatrick s << line << "\n";
177061da546Spatrick }
178061da546Spatrick } else
179061da546Spatrick s << "No commands.\n";
180061da546Spatrick }
181