• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef PANDA_RUNTIME_DEBUG_DEBUG_INTERFACE_H
16 #define PANDA_RUNTIME_DEBUG_DEBUG_INTERFACE_H
17 
18 #include <cstdint>
19 #include <list>
20 #include <optional>
21 #include <string>
22 #include <string_view>
23 #include <vector>
24 
25 #include "libpandabase/macros.h"
26 #include "libpandabase/utils/expected.h"
27 #include "libpandafile/file.h"
28 #include "runtime/include/mem/panda_containers.h"
29 #include "runtime/include/thread.h"
30 #include "runtime/include/tooling/pt_location.h"
31 #include "runtime/include/tooling/pt_macros.h"
32 #include "runtime/include/tooling/pt_object.h"
33 #include "runtime/include/tooling/pt_property.h"
34 #include "runtime/include/tooling/pt_thread.h"
35 #include "runtime/include/tooling/pt_value.h"
36 #include "runtime/include/tooling/vreg_value.h"
37 #include "runtime/interpreter/frame.h"
38 #include "runtime/include/tooling/pt_lang_extension.h"
39 
40 namespace panda::tooling {
41 class PtLangExt;
42 
43 class Error {
44 public:
45     enum class Type {
46         BREAKPOINT_NOT_FOUND,
47         BREAKPOINT_ALREADY_EXISTS,
48         ENTRY_POINT_RESOLVE_ERROR,
49         FRAME_NOT_FOUND,
50         NO_MORE_FRAMES,
51         OPAQUE_FRAME,
52         INVALID_BREAKPOINT,
53         INVALID_ENTRY_POINT,
54         METHOD_NOT_FOUND,
55         PANDA_FILE_LOAD_ERROR,
56         THREAD_NOT_FOUND,
57         THREAD_NOT_SUSPENDED,
58         INVALID_REGISTER,
59         INVALID_VALUE,
60         INVALID_EXPRESSION,
61         PROPERTY_ACCESS_WATCH_NOT_FOUND,
62         INVALID_PROPERTY_ACCESS_WATCH,
63         PROPERTY_MODIFY_WATCH_NOT_FOUND,
64         INVALID_PROPERTY_MODIFY_WATCH,
65         DEPRECATED,
66     };
67 
Error(Type type,std::string msg)68     Error(Type type, std::string msg) : type_(type), msg_(std::move(msg)) {}
69 
GetType()70     Type GetType() const
71     {
72         return type_;
73     }
74 
GetMessage()75     std::string GetMessage() const
76     {
77         return msg_;
78     }
79 
80     ~Error() = default;
81 
82     DEFAULT_COPY_SEMANTIC(Error);
83     DEFAULT_MOVE_SEMANTIC(Error);
84 
85 private:
86     Type type_;
87     std::string msg_;
88 };
89 
90 class PtFrame {
91 public:
92     PtFrame() = default;
93 
94     virtual bool IsInterpreterFrame() const = 0;
95 
96     virtual Method *GetMethod() const = 0;
97 
98     virtual uint64_t GetVReg(size_t i) const = 0;
99 
100     virtual size_t GetVRegNum() const = 0;
101 
102     virtual uint64_t GetArgument(size_t i) const = 0;
103 
104     virtual size_t GetArgumentNum() const = 0;
105 
106     virtual uint64_t GetAccumulator() const = 0;
107 
108     virtual panda_file::File::EntityId GetMethodId() const = 0;
109 
110     virtual uint32_t GetBytecodeOffset() const = 0;
111 
112     virtual std::string GetPandaFile() const = 0;
113 
114     // mock API
115     virtual uint32_t GetFrameId() const = 0;
116 
117     virtual ~PtFrame() = default;
118 
119     NO_COPY_SEMANTIC(PtFrame);
120     NO_MOVE_SEMANTIC(PtFrame);
121 };
122 
123 struct PtStepRange {
124     uint32_t start_bc_offset {0};
125     uint32_t end_bc_offset {0};
126 };
127 
128 // * * * * *
129 // Mock API helpers
130 // TODO(maksenov): cleanup
131 // * * * * *
132 
133 using ExceptionID = panda_file::File::EntityId;
134 using ExecutionContextId = panda_file::File::EntityId;
135 using threadGroup = uint32_t;
136 
137 using ExpressionWrapper = std::string;
138 using ExceptionWrapper = std::string;
139 
140 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
141 struct ThreadInfo {
142     char *name;
143     size_t name_length;
144     int32_t priority;
145     bool is_daemon;
146     threadGroup thread_group;
147 };
148 
149 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
150 struct PandaClassDefinition {
151     PtClass klass;
152     uint32_t class_byte_count;
153     const unsigned char *class_bytes;
154 };
155 
156 enum PauseReason {
157     AMBIGUOUS,
158     ASSERT,
159     DEBUGCOMMAND,
160     DOM,
161     EVENTLISTENER,
162     EXCEPTION,
163     INSTRUMENTATION,
164     OOM,
165     OTHER,
166     PROMISEREJECTION,
167     XHR,
168     BREAK_ON_START
169 };
170 
171 struct ExecutionContextWrapper {
172     ExecutionContextId id;
173     std::string origin;
174     std::string name;
175 };
176 
177 enum class PtHookType {
178     PT_HOOK_TYPE_BREAKPOINT,
179     PT_HOOK_TYPE_LOAD_MODULE,
180     PT_HOOK_TYPE_PAUSED,
181     PT_HOOK_TYPE_EXCEPTION,
182     PT_HOOK_TYPE_EXCEPTION_CATCH,
183     PT_HOOK_TYPE_PROPERTY_ACCESS,
184     PT_HOOK_TYPE_PROPERTY_MODIFICATION,
185     PT_HOOK_TYPE_FRAME_POP,
186     PT_HOOK_TYPE_GARBAGE_COLLECTION_START,
187     PT_HOOK_TYPE_GARBAGE_COLLECTION_FINISH,
188     PT_HOOK_TYPE_METHOD_ENTRY,
189     PT_HOOK_TYPE_METHOD_EXIT,
190     PT_HOOK_TYPE_SINGLE_STEP,
191     PT_HOOK_TYPE_THREAD_START,
192     PT_HOOK_TYPE_THREAD_END,
193     PT_HOOK_TYPE_VM_DEATH,
194     PT_HOOK_TYPE_VM_INITIALIZATION,
195     PT_HOOK_TYPE_VM_START,
196     PT_HOOK_TYPE_EXCEPTION_REVOKED,
197     PT_HOOK_TYPE_EXECUTION_CONTEXT_CREATEED,
198     PT_HOOK_TYPE_EXECUTION_CONTEXT_DESTROYED,
199     PT_HOOK_TYPE_EXECUTION_CONTEXTS_CLEARED,
200     PT_HOOK_TYPE_INSPECT_REQUESTED,
201     PT_HOOK_TYPE_CLASS_LOAD,
202     PT_HOOK_TYPE_CLASS_PREPARE,
203     PT_HOOK_TYPE_MONITOR_WAIT,
204     PT_HOOK_TYPE_MONITOR_WAITED,
205     PT_HOOK_TYPE_MONITOR_CONTENDED_ENTER,
206     PT_HOOK_TYPE_MONITOR_CONTENDED_ENTERED,
207     PT_HOOK_TYPE_OBJECT_ALLOC,
208     // The count of hooks. Don't move
209     PT_HOOK_TYPE_COUNT
210 };
211 
212 // * * * * *
213 // Mock API helpers ends
214 // * * * * *
215 
216 class PtHooks {
217 public:
218     PtHooks() = default;
219 
220     /**
221      * \brief Method is called by the runtime when breakpoint hits. Thread where breakpoint hits is stopped until
222      * continue or step event will be received
223      * @param thread Identifier of the thread where breakpoint hits. Now the callback is called in the same
224      * thread
225      * @param method Method
226      * @param location Breakpoint location
227      */
Breakpoint(PtThread,Method *,const PtLocation &)228     virtual void Breakpoint(PtThread /* thread */, Method * /* method */, const PtLocation & /* location */) {}
229 
230     /**
231      * \brief Method is called by the runtime when panda file is loaded
232      * @param pandaFileName Path to panda file that is loaded
233      */
LoadModule(std::string_view)234     virtual void LoadModule(std::string_view /* pandaFileName */) {}
235 
236     /**
237      * \brief Method is called by the runtime when managed thread is attached to it
238      * @param thread The attached thread
239      */
ThreadStart(PtThread)240     virtual void ThreadStart(PtThread /* thread */) {}
241 
242     /**
243      * \brief Method is called by the runtime when managed thread is detached
244      * @param thread The detached thread
245      */
ThreadEnd(PtThread)246     virtual void ThreadEnd(PtThread /* thread */) {}
247 
248     /**
249      * \brief Method is called by the runtime when virtual machine start initialization
250      */
VmStart()251     virtual void VmStart() {}
252 
253     /**
254      * \brief Method is called by the runtime when virtual machine finish initialization
255      * @param thread The initial thread
256      */
VmInitialization(PtThread)257     virtual void VmInitialization(PtThread /* thread */) {}
258 
259     /**
260      * \brief Method is called by the runtime when virtual machine death
261      */
VmDeath()262     virtual void VmDeath() {}
263 
264     /**
265      * \brief Method is called by the runtime when a class is first loaded
266      * @param thread Thread loading the class
267      * @param klass Class being loaded
268      */
ClassLoad(PtThread,BaseClass *)269     virtual void ClassLoad(PtThread /* thread */, BaseClass * /* klass */) {}
270 
271     /**
272      * \brief Method is called by the runtime when class preparation is complete
273      * @param thread Thread generating the class prepare
274      * @param klass Class being prepared
275      */
ClassPrepare(PtThread,BaseClass *)276     virtual void ClassPrepare(PtThread /* thread */, BaseClass * /* klass */) {}
277 
278     /**
279      * \brief Method is called by the runtime when a thread is about to wait on an object
280      * @param thread The thread about to wait
281      * @param object Reference to the monitor
282      * @param timeout The number of milliseconds the thread will wait
283      */
MonitorWait(PtThread,ObjectHeader *,int64_t)284     virtual void MonitorWait(PtThread /* thread */, ObjectHeader * /* object */, int64_t /* timeout */) {}
285 
286     /**
287      * \brief Method is called by the runtime when a thread finishes waiting on an object
288      * @param thread The thread about to wait
289      * @param object Reference to the monitor
290      * @param timedOut True if the monitor timed out
291      */
MonitorWaited(PtThread,ObjectHeader *,bool)292     virtual void MonitorWaited(PtThread /* thread */, ObjectHeader * /* object */, bool /* timedOut */) {}
293 
294     /**
295      * \brief Method is called by the runtime when a thread is attempting to enter a monitor already acquired by another
296      * thread
297      * @param thread The thread about to wait
298      * @param object Reference to the monitor
299      */
MonitorContendedEnter(PtThread,ObjectHeader *)300     virtual void MonitorContendedEnter(PtThread /* thread */, ObjectHeader * /* object */) {}
301 
302     /**
303      * \brief Method is called by the runtime when a thread enters a monitor after waiting for it to be released by
304      * another thread
305      * @param thread The thread about to wait
306      * @param object Reference to the monitor
307      */
MonitorContendedEntered(PtThread,ObjectHeader *)308     virtual void MonitorContendedEntered(PtThread /* thread */, ObjectHeader * /* object */) {}
309 
Exception(PtThread,Method *,const PtLocation &,ObjectHeader *,Method *,const PtLocation &)310     virtual void Exception(PtThread /* thread */, Method * /* method */, const PtLocation & /* location */,
311                            ObjectHeader * /* exceptionObject */, Method * /* catchMethod */,
312                            const PtLocation & /* catchLocation */)
313     {
314     }
315 
ExceptionCatch(PtThread,Method *,const PtLocation &,ObjectHeader *)316     virtual void ExceptionCatch(PtThread /* thread */, Method * /* catchMethod */, const PtLocation & /* location */,
317                                 ObjectHeader * /* exceptionObject */)
318     {
319     }
320 
PropertyAccess(PtThread,Method *,const PtLocation &,ObjectHeader *,PtProperty)321     virtual void PropertyAccess(PtThread /* thread */, Method * /* catchMethod */, const PtLocation & /* location */,
322                                 ObjectHeader * /* object */, PtProperty /* property */)
323     {
324     }
325 
PropertyModification(PtThread,Method *,const PtLocation &,ObjectHeader *,PtProperty,VRegValue)326     virtual void PropertyModification(PtThread /* thread */, Method * /* method */, const PtLocation & /* location */,
327                                       ObjectHeader * /* object */, PtProperty /* property */, VRegValue /* newValue */)
328     {
329     }
330 
FramePop(PtThread,Method *,bool)331     virtual void FramePop(PtThread /* thread */, Method * /* method */, bool /* wasPoppedByException */) {}
332 
GarbageCollectionFinish()333     virtual void GarbageCollectionFinish() {}
334 
GarbageCollectionStart()335     virtual void GarbageCollectionStart() {}
336 
ObjectAlloc(BaseClass *,ObjectHeader *,PtThread,size_t)337     virtual void ObjectAlloc(BaseClass * /* klass */, ObjectHeader * /* object */, PtThread /* thread */,
338                              size_t /* size */)
339     {
340     }
341 
MethodEntry(PtThread,Method *)342     virtual void MethodEntry(PtThread /* thread */, Method * /* method */) {}
343 
MethodExit(PtThread,Method *,bool,VRegValue)344     virtual void MethodExit(PtThread /* thread */, Method * /* method */, bool /* wasPoppedByException */,
345                             VRegValue /* returnValue */)
346     {
347     }
348 
SingleStep(PtThread,Method *,const PtLocation &)349     virtual void SingleStep(PtThread /* thread */, Method * /* method */, const PtLocation & /* location */) {}
350 
351     // * * * * *
352     // Deprecated hooks
353     // * * * * *
354 
Paused(PauseReason)355     virtual void Paused(PauseReason /* reason */) {}
Breakpoint(PtThread,const PtLocation &)356     virtual void Breakpoint(PtThread /* thread */, const PtLocation & /* location */) {}
Exception(PtThread,const PtLocation &,PtObject,const PtLocation &)357     virtual void Exception(PtThread /* thread */, const PtLocation & /* location */, PtObject /* exceptionObject */,
358                            const PtLocation & /* catchLocation */)
359     {
360     }
ExceptionCatch(PtThread,const PtLocation &,PtObject)361     virtual void ExceptionCatch(PtThread /* thread */, const PtLocation & /* location */,
362                                 PtObject /* exceptionObject */)
363     {
364     }
FramePop(PtThread,PtMethod,bool)365     virtual void FramePop(PtThread /* thread */, PtMethod /* method */, bool /* wasPoppedByException */) {}
MethodEntry(PtThread,PtMethod)366     virtual void MethodEntry(PtThread /* thread */, PtMethod /* method */) {}
367 
MethodExit(PtThread,PtMethod,bool,PtValue)368     virtual void MethodExit(PtThread /* thread */, PtMethod /* method */, bool /* wasPoppedByException */,
369                             PtValue /* returnValue */)
370     {
371     }
PropertyAccess(PtThread,const PtLocation &,PtObject,PtProperty)372     virtual void PropertyAccess(PtThread /* thread */, const PtLocation & /* location */, PtObject /* object */,
373                                 PtProperty /* property */)
374     {
375     }
PropertyModification(PtThread,const PtLocation &,PtObject,PtProperty,PtValue)376     virtual void PropertyModification(PtThread /* thread */, const PtLocation & /* location */, PtObject /* object */,
377                                       PtProperty /* property */, PtValue /* newValue */)
378     {
379     }
MonitorWait(PtThread,PtObject,int64_t)380     virtual void MonitorWait(PtThread /* thread */, PtObject /* object */, int64_t /* timeout */) {}
MonitorWaited(PtThread,PtObject,bool)381     virtual void MonitorWaited(PtThread /* thread */, PtObject /* object */, bool /* timedOut */) {}
MonitorContendedEnter(PtThread,PtObject)382     virtual void MonitorContendedEnter(PtThread /* thread */, PtObject /* object */) {}
MonitorContendedEntered(PtThread,PtObject)383     virtual void MonitorContendedEntered(PtThread /* thread */, PtObject /* object */) {}
ObjectAlloc(PtClass,PtObject,PtThread,size_t)384     virtual void ObjectAlloc(PtClass /* klass */, PtObject /* object */, PtThread /* thread */, size_t /* size */) {}
SingleStep(PtThread,const PtLocation &)385     virtual void SingleStep(PtThread /* thread */, const PtLocation & /* location */) {}
ClassLoad(PtThread,PtClass)386     virtual void ClassLoad(PtThread /* thread */, PtClass /* klass */) {}
ClassPrepare(PtThread,PtClass)387     virtual void ClassPrepare(PtThread /* thread */, PtClass /* klass */) {}
388 
389     // NOLINTNEXTLINE(performance-unnecessary-value-param)
ExceptionRevoked(ExceptionWrapper,ExceptionID)390     virtual void ExceptionRevoked(ExceptionWrapper /* reason */, ExceptionID /* exceptionId */) {}
391 
392     // NOLINTNEXTLINE(performance-unnecessary-value-param)
ExecutionContextCreated(ExecutionContextWrapper)393     virtual void ExecutionContextCreated(ExecutionContextWrapper /* context */) {}
394 
395     // NOLINTNEXTLINE(performance-unnecessary-value-param)
ExecutionContextDestroyed(ExecutionContextWrapper)396     virtual void ExecutionContextDestroyed(ExecutionContextWrapper /* context */) {}
397 
ExecutionContextsCleared()398     virtual void ExecutionContextsCleared() {}
399 
InspectRequested(PtObject,PtObject)400     virtual void InspectRequested(PtObject /* object */, PtObject /* hints */) {}
401 
402     // * * * * *
403     // Deprecated hooks end
404     // * * * * *
405 
406     virtual ~PtHooks() = default;
407 
408     NO_COPY_SEMANTIC(PtHooks);
409     NO_MOVE_SEMANTIC(PtHooks);
410 };
411 
412 class DebugInterface {
413 public:
414     DebugInterface() = default;
415 
416     /**
417      * \brief Register debug hooks in the runtime
418      * @param hooks Pointer to object that implements PtHooks interface
419      * @return Error if any errors occur
420      */
421     virtual std::optional<Error> RegisterHooks(PtHooks *hooks) = 0;
422 
423     /**
424      * \brief Unregister debug hooks in the runtime
425      * @return Error if any errors occur
426      */
427     virtual std::optional<Error> UnregisterHooks() = 0;
428 
429     /**
430      * \brief Enable all debug hooks in the runtime
431      * @return Error if any errors occur
432      */
433     virtual std::optional<Error> EnableAllGlobalHook() = 0;
434 
435     /**
436      * \brief Disable all debug hooks in the runtime
437      * @return Error if any errors occur
438      */
439     virtual std::optional<Error> DisableAllGlobalHook() = 0;
440 
441     /**
442      * \brief Set notification to hook (enable/disable).
443      * @param thread If thread is NONE, the notification is enabled or disabled globally
444      * @param enable Enable or disable notifications (true - enable, false - disable)
445      * @param hook_type Type of hook that must be enabled or disabled
446      * @return Error if any errors occur
447      */
448     virtual std::optional<Error> SetNotification(PtThread thread, bool enable, PtHookType hookType) = 0;
449 
450     /**
451      * \brief Set breakpoint to \param location
452      * @param location Breakpoint location
453      * @return Error if any errors occur
454      */
455     virtual std::optional<Error> SetBreakpoint(const PtLocation &location) = 0;
456 
457     /**
458      * \brief Remove breakpoint from \param location
459      * @param location Breakpoint location
460      * @return Error if any errors occur
461      */
462     virtual std::optional<Error> RemoveBreakpoint(const PtLocation &location) = 0;
463 
464     /**
465      * \brief Get Frame
466      * @param thread Identifier of the thread
467      * @return Frame object that implements PtFrame or Error if any errors occur
468      */
469     virtual Expected<std::unique_ptr<PtFrame>, Error> GetCurrentFrame(PtThread thread) const = 0;
470 
471     /**
472      * \brief Enumerates managed frames in the thread \param threadId
473      * @param thread Identifier of the thread
474      * @param callback Callback that is called for each frame. Should return true to continue and false to stop
475      * enumerating
476      * @return Error if any errors occur
477      */
478     virtual std::optional<Error> EnumerateFrames(PtThread thread,
479                                                  std::function<bool(const PtFrame &)> callback) const = 0;
480 
481     /**
482      * \brief Suspend thread
483      * @param thread Identifier of the thread
484      * @return Error if any errors occur
485      */
486     virtual std::optional<Error> SuspendThread(PtThread thread) const = 0;
487 
488     /**
489      * \brief Resume thread
490      * @param thread Identifier of the thread
491      * @return Error if any errors occur
492      */
493     virtual std::optional<Error> ResumeThread(PtThread thread) const = 0;
494 
495     virtual ~DebugInterface() = default;
496 
497     virtual PtLangExt *GetLangExtension() const = 0;
498 
499     virtual Expected<PtMethod, Error> GetPtMethod(const PtLocation &location) const = 0;
500 
501     virtual std::optional<Error> GetThreadList(PandaVector<PtThread> *threadList) const = 0;
502 
SetVariable(PtThread,uint32_t,int32_t,const VRegValue &)503     virtual std::optional<Error> SetVariable(PtThread /* thread */, uint32_t /* frameDepth */, int32_t /* regNumber */,
504                                              const VRegValue & /* value */) const
505     {
506         return {};
507     }
508 
GetVariable(PtThread,uint32_t,int32_t,VRegValue *)509     virtual std::optional<Error> GetVariable(PtThread /* thread */, uint32_t /* frameDepth */, int32_t /* regNumber */,
510                                              VRegValue * /* value */) const
511     {
512         return {};
513     }
514 
515     virtual std::optional<Error> GetProperty(PtObject thisObject, PtProperty property, PtValue *value) const = 0;
516 
517     virtual std::optional<Error> SetProperty(PtObject thisObject, PtProperty property, const PtValue &value) const = 0;
518 
519     virtual std::optional<Error> EvaluateExpression(PtThread thread, uint32_t frameNumber, ExpressionWrapper expr,
520                                                     PtValue *result) const = 0;
521 
522     virtual std::optional<Error> GetThreadInfo(PtThread thread, ThreadInfo *infoPtr) const = 0;
523 
524     virtual std::optional<Error> RestartFrame(PtThread thread, uint32_t frameNumber) const = 0;
525 
526     virtual std::optional<Error> SetAsyncCallStackDepth(uint32_t maxDepth) const = 0;
527 
528     virtual std::optional<Error> AwaitPromise(PtObject promiseObject, PtValue *result) const = 0;
529 
530     virtual std::optional<Error> CallFunctionOn(PtObject object, PtMethod method, const PandaVector<PtValue> &arguments,
531                                                 PtValue *result) const = 0;
532 
533     virtual std::optional<Error> GetProperties(uint32_t *countPtr, char ***propertyPtr) const = 0;
534 
535     virtual std::optional<Error> NotifyFramePop(PtThread thread, uint32_t depth) const = 0;
536 
GetThisVariableByFrame(PtThread,uint32_t,ObjectHeader **)537     virtual std::optional<Error> GetThisVariableByFrame(PtThread /* thread */, uint32_t /* frameDepth */,
538                                                         ObjectHeader ** /* this_ptr */)
539     {
540         return {};
541     }
542 
SetPropertyAccessWatch(BaseClass *,PtProperty)543     virtual std::optional<Error> SetPropertyAccessWatch(BaseClass * /* klass */, PtProperty /* property */)
544     {
545         return {};
546     }
547 
ClearPropertyAccessWatch(BaseClass *,PtProperty)548     virtual std::optional<Error> ClearPropertyAccessWatch(BaseClass * /* klass */, PtProperty /* property */)
549     {
550         return {};
551     }
552 
SetPropertyModificationWatch(BaseClass *,PtProperty)553     virtual std::optional<Error> SetPropertyModificationWatch(BaseClass * /* klass */, PtProperty /* property */)
554     {
555         return {};
556     }
557 
ClearPropertyModificationWatch(BaseClass *,PtProperty)558     virtual std::optional<Error> ClearPropertyModificationWatch(BaseClass * /* klass */, PtProperty /* property */)
559     {
560         return {};
561     }
562 
563     // * * * * *
564     // Deprecated API
565     // * * * * *
566     virtual std::optional<Error> GetThisVariableByFrame(PtThread thread, uint32_t frameDepth, PtValue *value) = 0;
567     virtual std::optional<Error> SetPropertyAccessWatch(PtClass klass, PtProperty property) = 0;
568     virtual std::optional<Error> ClearPropertyAccessWatch(PtClass klass, PtProperty property) = 0;
569     virtual std::optional<Error> SetPropertyModificationWatch(PtClass klass, PtProperty property) = 0;
570     virtual std::optional<Error> ClearPropertyModificationWatch(PtClass klass, PtProperty property) = 0;
571     virtual std::optional<Error> RetransformClasses(int classCount, const PtClass *classes) const = 0;
572     virtual std::optional<Error> RedefineClasses(int classCount, const PandaClassDefinition *classes) const = 0;
573     virtual std::optional<Error> SetVariable(PtThread thread, uint32_t frameDepth, int32_t regNumber,
574                                              const PtValue &value) const = 0;
575     virtual std::optional<Error> GetVariable(PtThread thread, uint32_t frameDepth, int32_t regNumber,
576                                              PtValue *value) const = 0;
577 
578     // * * * * *
579     // Deprecated API ends
580     // * * * * *
581 
582     NO_COPY_SEMANTIC(DebugInterface);
583     NO_MOVE_SEMANTIC(DebugInterface);
584 };
585 }  // namespace panda::tooling
586 
587 #endif  // PANDA_RUNTIME_DEBUG_DEBUG_INTERFACE_H
588