@@ -83,6 +83,94 @@ void Watchpoint::SetCallback(WatchpointHitCallback callback,
83
83
SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
84
84
}
85
85
86
+ bool Watchpoint::SetupVariableWatchpointDisabler (StackFrameSP frame_sp) const {
87
+ if (!frame_sp)
88
+ return false ;
89
+
90
+ ThreadSP thread_sp = frame_sp->GetThread ();
91
+ if (!thread_sp)
92
+ return false ;
93
+
94
+ uint32_t return_frame_index =
95
+ thread_sp->GetSelectedFrameIndex (DoNoSelectMostRelevantFrame) + 1 ;
96
+ if (return_frame_index >= LLDB_INVALID_FRAME_ID)
97
+ return false ;
98
+
99
+ StackFrameSP return_frame_sp (
100
+ thread_sp->GetStackFrameAtIndex (return_frame_index));
101
+ if (!return_frame_sp)
102
+ return false ;
103
+
104
+ ExecutionContext exe_ctx (return_frame_sp);
105
+ TargetSP target_sp = exe_ctx.GetTargetSP ();
106
+ if (!target_sp)
107
+ return false ;
108
+
109
+ Address return_address (return_frame_sp->GetFrameCodeAddress ());
110
+ lldb::addr_t return_addr = return_address.GetLoadAddress (target_sp.get ());
111
+ if (return_addr == LLDB_INVALID_ADDRESS)
112
+ return false ;
113
+
114
+ BreakpointSP bp_sp = target_sp->CreateBreakpoint (
115
+ return_addr, /* internal=*/ true , /* request_hardware=*/ false );
116
+ if (!bp_sp || !bp_sp->HasResolvedLocations ())
117
+ return false ;
118
+
119
+ auto wvc_up = std::make_unique<WatchpointVariableContext>(GetID (), exe_ctx);
120
+ auto baton_sp = std::make_shared<WatchpointVariableBaton>(std::move (wvc_up));
121
+ bp_sp->SetCallback (VariableWatchpointDisabler, baton_sp);
122
+ bp_sp->SetOneShot (true );
123
+ bp_sp->SetBreakpointKind (" variable watchpoint disabler" );
124
+ return true ;
125
+ }
126
+
127
+ bool Watchpoint::VariableWatchpointDisabler (void *baton,
128
+ StoppointCallbackContext *context,
129
+ user_id_t break_id,
130
+ user_id_t break_loc_id) {
131
+ assert (baton && " null baton" );
132
+ if (!baton || !context)
133
+ return false ;
134
+
135
+ Log *log = GetLog (LLDBLog::Watchpoints);
136
+
137
+ WatchpointVariableContext *wvc =
138
+ static_cast <WatchpointVariableContext *>(baton);
139
+
140
+ LLDB_LOGF (log , " called by breakpoint %" PRIu64 " .%" PRIu64, break_id,
141
+ break_loc_id);
142
+
143
+ if (wvc->watch_id == LLDB_INVALID_WATCH_ID)
144
+ return false ;
145
+
146
+ TargetSP target_sp = context->exe_ctx_ref .GetTargetSP ();
147
+ if (!target_sp)
148
+ return false ;
149
+
150
+ ProcessSP process_sp = target_sp->GetProcessSP ();
151
+ if (!process_sp)
152
+ return false ;
153
+
154
+ WatchpointSP watch_sp =
155
+ target_sp->GetWatchpointList ().FindByID (wvc->watch_id );
156
+ if (!watch_sp)
157
+ return false ;
158
+
159
+ if (wvc->exe_ctx == context->exe_ctx_ref ) {
160
+ LLDB_LOGF (log ,
161
+ " callback for watchpoint %" PRId32
162
+ " matched internal breakpoint execution context" ,
163
+ watch_sp->GetID ());
164
+ process_sp->DisableWatchpoint (watch_sp.get ());
165
+ return false ;
166
+ }
167
+ LLDB_LOGF (log ,
168
+ " callback for watchpoint %" PRId32
169
+ " didn't match internal breakpoint execution context" ,
170
+ watch_sp->GetID ());
171
+ return false ;
172
+ }
173
+
86
174
void Watchpoint::ClearCallback () {
87
175
m_options.ClearCallback ();
88
176
SendWatchpointChangedEvent (eWatchpointEventTypeCommandChanged);
0 commit comments