• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #ifndef PANDA_RUNTIME_INCLUDE_TOOLING_DEBUG_INTERFACE_H_
17 #define PANDA_RUNTIME_INCLUDE_TOOLING_DEBUG_INTERFACE_H_
18 
19 #include <cstdint>
20 #include <list>
21 #include <optional>
22 #include <string>
23 #include <string_view>
24 #include <vector>
25 
26 #include "libpandabase/macros.h"
27 #include "libpandabase/utils/expected.h"
28 #include "libpandafile/file.h"
29 #include "runtime/include/mem/panda_containers.h"
30 #include "runtime/include/thread.h"
31 #include "runtime/include/tooling/pt_class.h"
32 #include "runtime/include/tooling/pt_location.h"
33 #include "runtime/include/tooling/pt_method.h"
34 #include "runtime/include/tooling/pt_object.h"
35 #include "runtime/include/tooling/pt_property.h"
36 #include "runtime/include/tooling/pt_thread.h"
37 #include "runtime/include/tooling/pt_value.h"
38 #include "runtime/interpreter/frame.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     };
66 
Error(Type type,std::string msg)67     Error(Type type, std::string msg) : type_(type), msg_(std::move(msg)) {}
68 
GetType()69     Type GetType() const
70     {
71         return type_;
72     }
73 
GetMessage()74     std::string GetMessage() const
75     {
76         return msg_;
77     }
78 
79     ~Error() = default;
80 
81     DEFAULT_COPY_SEMANTIC(Error);
82     DEFAULT_MOVE_SEMANTIC(Error);
83 
84 private:
85     Type type_;
86     std::string msg_;
87 };
88 
89 class PtFrame {
90 public:
91     PtFrame() = default;
92 
93     virtual bool IsInterpreterFrame() const = 0;
94 
95     virtual PtMethod GetPtMethod() const = 0;
96 
97     virtual uint64_t GetVReg(size_t i) const = 0;
98 
99     virtual size_t GetVRegNum() const = 0;
100 
101     virtual uint64_t GetArgument(size_t i) const = 0;
102 
103     virtual size_t GetArgumentNum() const = 0;
104 
105     virtual uint64_t GetAccumulator() const = 0;
106 
107     virtual panda_file::File::EntityId GetMethodId() const = 0;
108 
109     virtual uint32_t GetBytecodeOffset() const = 0;
110 
111     virtual std::string GetPandaFile() const = 0;
112 
113     // mock API
114     virtual uint32_t GetFrameId() const = 0;
115 
116     virtual ~PtFrame() = default;
117 
118     NO_COPY_SEMANTIC(PtFrame);
119     NO_MOVE_SEMANTIC(PtFrame);
120 };
121 
122 struct PtStepRange {
123     uint32_t start_bc_offset {0};
124     uint32_t end_bc_offset {0};
125 };
126 
127 // * * * * *
128 // Mock API helpers
129 // * * * * *
130 
131 using ExceptionID = panda_file::File::EntityId;
132 using ExecutionContextId = panda_file::File::EntityId;
133 using threadGroup = uint32_t;
134 
135 using ExpressionWrapper = std::string;
136 using ExceptionWrapper = std::string;
137 
138 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
139 struct ThreadInfo {
140     char *name;
141     size_t name_lenght;
142     int32_t priority;
143     bool is_daemon;
144     threadGroup thread_group;
145     PtObject context_class_loader;
146 };
147 
148 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
149 struct PandaClassDefinition {
150     PtClass klass;
151     uint32_t class_byte_count;
152     const unsigned char *class_bytes;
153 };
154 
155 enum PauseReason {
156     AMBIGUOUS,
157     ASSERT,
158     DEBUGCOMMAND,
159     DOM,
160     EVENTLISTENER,
161     EXCEPTION,
162     INSTRUMENTATION,
163     OOM,
164     OTHER,
165     PROMISEREJECTION,
166     XHR,
167     BREAK_ON_START
168 };
169 
170 struct ExecutionContextWrapper {
171     ExecutionContextId id;
172     std::string origin;
173     std::string name;
174 };
175 
176 enum class PtHookType {
177     PT_HOOK_TYPE_BREAKPOINT,
178     PT_HOOK_TYPE_LOAD_MODULE,
179     PT_HOOK_TYPE_PAUSED,
180     PT_HOOK_TYPE_EXCEPTION,
181     PT_HOOK_TYPE_EXCEPTION_CATCH,
182     PT_HOOK_TYPE_PROPERTY_ACCESS,
183     PT_HOOK_TYPE_PROPERTY_MODIFICATION,
184     PT_HOOK_TYPE_FRAME_POP,
185     PT_HOOK_TYPE_GARBAGE_COLLECTION_START,
186     PT_HOOK_TYPE_GARBAGE_COLLECTION_FINISH,
187     PT_HOOK_TYPE_METHOD_ENTRY,
188     PT_HOOK_TYPE_METHOD_EXIT,
189     PT_HOOK_TYPE_SINGLE_STEP,
190     PT_HOOK_TYPE_THREAD_START,
191     PT_HOOK_TYPE_THREAD_END,
192     PT_HOOK_TYPE_VM_DEATH,
193     PT_HOOK_TYPE_VM_INITIALIZATION,
194     PT_HOOK_TYPE_VM_START,
195     PT_HOOK_TYPE_EXCEPTION_REVOKED,
196     PT_HOOK_TYPE_EXECUTION_CONTEXT_CREATEED,
197     PT_HOOK_TYPE_EXECUTION_CONTEXT_DESTROYED,
198     PT_HOOK_TYPE_EXECUTION_CONTEXTS_CLEARED,
199     PT_HOOK_TYPE_INSPECT_REQUESTED,
200     PT_HOOK_TYPE_CLASS_LOAD,
201     PT_HOOK_TYPE_CLASS_PREPARE,
202     PT_HOOK_TYPE_MONITOR_WAIT,
203     PT_HOOK_TYPE_MONITOR_WAITED,
204     PT_HOOK_TYPE_MONITOR_CONTENDED_ENTER,
205     PT_HOOK_TYPE_MONITOR_CONTENDED_ENTERED,
206     PT_HOOK_TYPE_OBJECT_ALLOC,
207     // The count of hooks. Don't move
208     PT_HOOK_TYPE_COUNT
209 };
210 
211 // * * * * *
212 // Mock API helpers ends
213 // * * * * *
214 
215 class PtHooks {
216 public:
217     PtHooks() = default;
218 
219     /**
220      * \brief Method is called by the runtime when breakpoint hits. Thread where breakpoint hits is stopped until
221      * continue or step event will be received
222      * @param thread Identifier of the thread where breakpoint hits. Now the callback is called in the same
223      * thread
224      * @param location Breakpoint location
225      */
226     virtual void Breakpoint(PtThread thread, const PtLocation &location) = 0;
227 
228     /**
229      * \brief Method is called by the runtime when panda file is loaded
230      * @param pandaFileName Path to panda file that is loaded
231      */
232     virtual void LoadModule(std::string_view pandaFileName) = 0;
233 
234     /**
235      * \brief Method is called by the runtime when managed thread is attached to it
236      * @param thread The attached thread
237      */
238     virtual void ThreadStart(PtThread thread) = 0;
239 
240     /**
241      * \brief Method is called by the runtime when managed thread is detached
242      * @param thread The detached thread
243      */
244     virtual void ThreadEnd(PtThread thread) = 0;
245 
246     /**
247      * \brief Method is called by the runtime when virtual machine start initialization
248      */
249     virtual void VmStart() = 0;
250 
251     /**
252      * \brief Method is called by the runtime when virtual machine finish initialization
253      * @param thread The initial thread
254      */
255     virtual void VmInitialization(PtThread thread) = 0;
256 
257     /**
258      * \brief Method is called by the runtime when virtual machine death
259      */
260     virtual void VmDeath() = 0;
261 
262     /**
263      * \brief Method is called by the runtime when a class is first loaded
264      * @param thread Thread loading the class
265      * @param klass Class being loaded
266      */
267     virtual void ClassLoad(PtThread thread, PtClass klass) = 0;
268 
269     /**
270      * \brief Method is called by the runtime when class preparation is complete
271      * @param thread Thread generating the class prepare
272      * @param klass Class being prepared
273      */
274     virtual void ClassPrepare(PtThread thread, PtClass klass) = 0;
275 
276     /**
277      * \brief Method is called by the runtime when a thread is about to wait on an object
278      * @param thread The thread about to wait
279      * @param object Reference to the monitor
280      * @param timeout The number of milliseconds the thread will wait
281      */
282     virtual void MonitorWait(PtThread thread, PtObject object, int64_t timeout) = 0;
283 
284     /**
285      * \brief Method is called by the runtime when a thread finishes waiting on an object
286      * @param thread The thread about to wait
287      * @param object Reference to the monitor
288      * @param timedOut True if the monitor timed out
289      */
290     virtual void MonitorWaited(PtThread thread, PtObject object, bool timedOut) = 0;
291 
292     /**
293      * \brief Method is called by the runtime when a thread is attempting to enter a monitor already acquired by another
294      * thread
295      * @param thread The thread about to wait
296      * @param object Reference to the monitor
297      */
298     virtual void MonitorContendedEnter(PtThread thread, PtObject object) = 0;
299 
300     /**
301      * \brief Method is called by the runtime when a thread enters a monitor after waiting for it to be released by
302      * another thread
303      * @param thread The thread about to wait
304      * @param object Reference to the monitor
305      */
306     virtual void MonitorContendedEntered(PtThread thread, PtObject object) = 0;
307 
308     // * * * * *
309     // mock API for panda debugger events
310     // * * * * *
311 
312     virtual void Paused(PauseReason reason) = 0;
313 
314     virtual void Exception(PtThread thread, const PtLocation &location, PtObject exceptionObject,
315                            const PtLocation &catchLocation) = 0;
316 
317     virtual void ExceptionCatch(PtThread thread, const PtLocation &location, PtObject exceptionObject) = 0;
318 
319     virtual void PropertyAccess(PtThread thread, const PtLocation &location, PtObject object, PtProperty property) = 0;
320 
321     virtual void PropertyModification(PtThread thread, const PtLocation &location, PtObject object, PtProperty property,
322                                       PtValue newValue) = 0;
323 
324     virtual void FramePop(PtThread thread, PtMethod method, bool wasPoppedByException) = 0;
325 
326     virtual void GarbageCollectionFinish() = 0;
327 
328     virtual void GarbageCollectionStart() = 0;
329 
330     virtual void ObjectAlloc(PtClass klass, PtObject object, PtThread thread, size_t size) = 0;
331 
332     virtual void MethodEntry(PtThread thread, PtMethod method) = 0;
333 
334     virtual void MethodExit(PtThread thread, PtMethod method, bool wasPoppedByException, PtValue returnValue) = 0;
335 
336     virtual void SingleStep(PtThread thread, const PtLocation &location) = 0;
337 
338     virtual void ExceptionRevoked(ExceptionWrapper reason, ExceptionID exceptionId) = 0;
339 
340     virtual void ExecutionContextCreated(ExecutionContextWrapper context) = 0;
341 
342     virtual void ExecutionContextDestroyed(ExecutionContextWrapper context) = 0;
343 
344     virtual void ExecutionContextsCleared() = 0;
345 
346     virtual void InspectRequested(PtObject object, PtObject hints) = 0;
347 
348     // * * * * *
349     // mock API ends
350     // * * * * *
351 
352     virtual ~PtHooks() = default;
353 
354     NO_COPY_SEMANTIC(PtHooks);
355     NO_MOVE_SEMANTIC(PtHooks);
356 };
357 
358 class DebugInterface {
359 public:
360     DebugInterface() = default;
361 
362     /**
363      * \brief Register debug hooks in the runtime
364      * @param hooks Pointer to object that implements PtHooks interface
365      * @return Error if any errors occur
366      */
367     virtual std::optional<Error> RegisterHooks(PtHooks *hooks) = 0;
368 
369     /**
370      * \brief Unregister debug hooks in the runtime
371      * @return Error if any errors occur
372      */
373     virtual std::optional<Error> UnregisterHooks() = 0;
374 
375     /**
376      * \brief Enable all debug hooks in the runtime
377      * @return Error if any errors occur
378      */
379     virtual std::optional<Error> EnableAllGlobalHook() = 0;
380 
381     /**
382      * \brief Disable all debug hooks in the runtime
383      * @return Error if any errors occur
384      */
385     virtual std::optional<Error> DisableAllGlobalHook() = 0;
386 
387     /**
388      * \brief Set notification to hook (enable/disable).
389      * @param thread If thread is NONE, the notification is enabled or disabled globally
390      * @param enable Enable or disable notifications (true - enable, false - disable)
391      * @param hook_type Type of hook that must be enabled or disabled
392      * @return Error if any errors occur
393      */
394     virtual std::optional<Error> SetNotification(PtThread thread, bool enable, PtHookType hookType) = 0;
395 
396     /**
397      * \brief Set breakpoint to \param location
398      * @param location Breakpoint location
399      * @return Error if any errors occur
400      */
401     virtual std::optional<Error> SetBreakpoint(const PtLocation &location) = 0;
402 
403     /**
404      * \brief Remove breakpoint from \param location
405      * @param location Breakpoint location
406      * @return Error if any errors occur
407      */
408     virtual std::optional<Error> RemoveBreakpoint(const PtLocation &location) = 0;
409 
410     /**
411      * \brief Get Frame
412      * @param thread Identifier of the thread
413      * @return Frame object that implements PtFrame or Error if any errors occur
414      */
415     virtual Expected<std::unique_ptr<PtFrame>, Error> GetCurrentFrame(PtThread thread) const = 0;
416 
417     /**
418      * \brief Enumerates managed frames in the thread \param threadId
419      * @param thread Identifier of the thread
420      * @param callback Callback that is called for each frame. Should return true to continue and false to stop
421      * enumerating
422      * @return Error if any errors occur
423      */
424     virtual std::optional<Error> EnumerateFrames(PtThread thread,
425                                                  std::function<bool(const PtFrame &)> callback) const = 0;
426 
427     /**
428      * \brief Suspend thread
429      * @param thread Identifier of the thread
430      * @return Error if any errors occur
431      */
432     virtual std::optional<Error> SuspendThread(PtThread thread) const = 0;
433 
434     /**
435      * \brief Resume thread
436      * @param thread Identifier of the thread
437      * @return Error if any errors occur
438      */
439     virtual std::optional<Error> ResumeThread(PtThread thread) const = 0;
440 
441     virtual ~DebugInterface() = default;
442 
443     virtual PtLangExt *GetLangExtension() const = 0;
444 
445     virtual Expected<PtMethod, Error> GetPtMethod(const PtLocation &location) const = 0;
446 
447     /*
448      * Mock API for debug interphase starts:
449      *
450      * add get_thread_list
451      * what variables and IDs we can't get
452      */
453     virtual std::optional<Error> GetThreadList(PandaVector<PtThread> *threadList) const = 0;
454 
455     virtual std::optional<Error> SetVariable(PtThread thread, uint32_t frameDepth, int32_t regNumber,
456                                              const PtValue &value) const = 0;
457 
458     virtual std::optional<Error> GetVariable(PtThread thread, uint32_t frameDepth, int32_t regNumber,
459                                              PtValue *value) const = 0;
460 
461     virtual std::optional<Error> GetProperty(PtObject thisObject, PtProperty property, PtValue *value) const = 0;
462 
463     virtual std::optional<Error> SetProperty(PtObject thisObject, PtProperty property, const PtValue &value) const = 0;
464 
465     virtual std::optional<Error> EvaluateExpression(PtThread thread, uint32_t frameNumber, ExpressionWrapper expr,
466                                                     PtValue *result) const = 0;
467 
468     virtual std::optional<Error> RetransformClasses(int classCount, const PtClass *classes) const = 0;
469 
470     virtual std::optional<Error> RedefineClasses(int classCount, const PandaClassDefinition *classes) const = 0;
471 
472     virtual std::optional<Error> GetThreadInfo(PtThread thread, ThreadInfo *infoPtr) const = 0;
473 
474     virtual std::optional<Error> RestartFrame(PtThread thread, uint32_t frameNumber) const = 0;
475 
476     virtual std::optional<Error> SetAsyncCallStackDepth(uint32_t maxDepth) const = 0;
477 
478     virtual std::optional<Error> AwaitPromise(PtObject promiseObject, PtValue *result) const = 0;
479 
480     virtual std::optional<Error> CallFunctionOn(PtObject object, PtMethod method, const PandaVector<PtValue> &arguments,
481                                                 PtValue *result) const = 0;
482 
483     virtual std::optional<Error> GetProperties(uint32_t *countPtr, char ***propertyPtr) const = 0;
484 
485     virtual std::optional<Error> NotifyFramePop(PtThread thread, uint32_t depth) const = 0;
486 
487     virtual std::optional<Error> SetPropertyAccessWatch(PtClass klass, PtProperty property) = 0;
488 
489     virtual std::optional<Error> ClearPropertyAccessWatch(PtClass klass, PtProperty property) = 0;
490 
491     virtual std::optional<Error> SetPropertyModificationWatch(PtClass klass, PtProperty property) = 0;
492 
493     virtual std::optional<Error> GetThisVariableByFrame(PtThread thread, uint32_t frameDepth, PtValue *value) = 0;
494 
495     virtual std::optional<Error> ClearPropertyModificationWatch(PtClass klass, PtProperty property) = 0;
496 
497     // * * * * *
498     // Mock API ends
499     // * * * * *
500 
501     NO_COPY_SEMANTIC(DebugInterface);
502     NO_MOVE_SEMANTIC(DebugInterface);
503 };
504 
505 }  // namespace panda::tooling
506 
507 #endif  // PANDA_RUNTIME_INCLUDE_TOOLING_DEBUG_INTERFACE_H_
508