1 //===-- WatchpointOptions.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Breakpoint/WatchpointOptions.h"
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"
20 using namespace lldb_private
;
22 bool WatchpointOptions::NullCallback(void *baton
,
23 StoppointCallbackContext
*context
,
24 lldb::user_id_t watch_id
) {
28 // WatchpointOptions constructor
29 WatchpointOptions::WatchpointOptions()
30 : m_callback(WatchpointOptions::NullCallback
) {}
32 // WatchpointOptions copy constructor
33 WatchpointOptions::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
);
40 // WatchpointOptions assignment operator
41 const WatchpointOptions
&WatchpointOptions::
42 operator=(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
);
52 WatchpointOptions::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
;
58 WatchpointOptions
*ret_val
= new WatchpointOptions(orig
);
60 orig
.SetCallback(orig_callback
, orig_callback_baton_sp
, orig_is_sync
);
66 WatchpointOptions::~WatchpointOptions() = default;
69 void 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
;
77 void WatchpointOptions::ClearCallback() {
78 m_callback
= WatchpointOptions::NullCallback
;
79 m_callback_is_synchronous
= false;
80 m_callback_baton_sp
.reset();
83 Baton
*WatchpointOptions::GetBaton() { return m_callback_baton_sp
.get(); }
85 const Baton
*WatchpointOptions::GetBaton() const {
86 return m_callback_baton_sp
.get();
89 bool 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()
99 bool WatchpointOptions::HasCallback() {
100 return m_callback
!= WatchpointOptions::NullCallback
;
103 const ThreadSpec
*WatchpointOptions::GetThreadSpecNoCreate() const {
104 return m_thread_spec_up
.get();
107 ThreadSpec
*WatchpointOptions::GetThreadSpec() {
108 if (m_thread_spec_up
== nullptr)
109 m_thread_spec_up
= std::make_unique
<ThreadSpec
>();
111 return m_thread_spec_up
.get();
114 void WatchpointOptions::SetThreadID(lldb::tid_t thread_id
) {
115 GetThreadSpec()->SetTID(thread_id
);
118 void WatchpointOptions::GetCallbackDescription(
119 Stream
*s
, lldb::DescriptionLevel level
) const {
120 if (m_callback_baton_sp
.get()) {
122 m_callback_baton_sp
->GetDescription(s
->AsRawOstream(), level
,
123 s
->GetIndentLevel());
127 void WatchpointOptions::GetDescription(Stream
*s
,
128 lldb::DescriptionLevel level
) const {
129 // Figure out if there are any options not at their default value, and only
130 // print anything if there are:
132 if ((GetThreadSpecNoCreate() != nullptr &&
133 GetThreadSpecNoCreate()->HasSpecification())) {
134 if (level
== lldb::eDescriptionLevelVerbose
) {
138 s
->PutCString("Watchpoint Options:\n");
142 s
->PutCString(" Options: ");
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
) {
154 GetCallbackDescription(s
, level
);
157 void WatchpointOptions::CommandBaton::GetDescription(
158 llvm::raw_ostream
&s
, lldb::DescriptionLevel level
,
159 unsigned indentation
) const {
160 const CommandData
*data
= getItem();
162 if (level
== eDescriptionLevelBrief
) {
163 s
<< ", commands = %s"
164 << ((data
&& data
->user_source
.GetSize() > 0) ? "yes" : "no");
169 s
.indent(indentation
);
170 s
<< "watchpoint commands:\n";
173 if (data
&& data
->user_source
.GetSize() > 0) {
174 for (const std::string
&line
: data
->user_source
) {
175 s
.indent(indentation
);
179 s
<< "No commands.\n";