1 /** 2 * Copyright (c) 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 16 #ifndef PANDA_TOOLING_INSPECTOR_DEBUGGABLE_THREAD_H 17 #define PANDA_TOOLING_INSPECTOR_DEBUGGABLE_THREAD_H 18 19 #include "runtime/tooling/debugger.h" 20 #include "runtime/tooling/inspector/object_repository.h" 21 #include "runtime/tooling/inspector/thread_state.h" 22 #include "runtime/tooling/inspector/types/numeric_id.h" 23 #include "runtime/tooling/inspector/types/pause_on_exceptions_state.h" 24 25 namespace panda::tooling::inspector { 26 class DebuggableThread { 27 public: 28 DebuggableThread( 29 ManagedThread *thread, 30 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *)> &&preSuspend, 31 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *)> &&postSuspend, 32 std::function<void()> &&preWaitSuspension, std::function<void()> &&postWaitSuspension, 33 std::function<void()> &&preResume, std::function<void()> &&postResume); 34 ~DebuggableThread() = default; 35 36 NO_COPY_SEMANTIC(DebuggableThread); 37 NO_MOVE_SEMANTIC(DebuggableThread); 38 39 /// The following methods should be called on the server thread 40 41 // Resets the state on a new connection 42 void Reset(); 43 44 // Tells a newly created thread to pause on the next step 45 void BreakOnStart(); 46 47 // Continues execution of a paused thread 48 void Continue(); 49 50 // Continues execution of a paused thread until it reaches one of the locations 51 void ContinueTo(std::unordered_set<PtLocation, HashLocation> locations); 52 53 // Tells a paused thread to perform a step into 54 void StepInto(std::unordered_set<PtLocation, HashLocation> locations); 55 56 // Tells a paused thread to perform a step over 57 void StepOver(std::unordered_set<PtLocation, HashLocation> locations); 58 59 // Tells a paused thread to perform a step out 60 void StepOut(); 61 62 // Makes a paused thread to resume and suspend back (does nothing for running threads). 63 // Used to notify about thread's state when processing `runIfWaitingForDebugger` 64 void Touch(); 65 66 // Tells a running thread to pause on the next step 67 void Pause(); 68 69 // Enables or disables stops on breakpoints 70 void SetBreakpointsActive(bool active); 71 72 // Sets a breakpoint on the locations. Returns the breakpoint ID 73 BreakpointId SetBreakpoint(const std::vector<PtLocation> &locations); 74 75 // Removes the breakpoint by ID 76 void RemoveBreakpoint(BreakpointId id); 77 78 // Tells when stops should be made on exceptions 79 void SetPauseOnExceptions(PauseOnExceptionsState state); 80 81 // Executes a request to object repository on a paused thread (does nothing for running threads) 82 bool RequestToObjectRepository(std::function<void(ObjectRepository &)> request); 83 84 /// The following methods should be called on an application thread 85 86 // Notification that an exception was thrown. Pauses the thread if necessary 87 void OnException(bool uncaught); 88 89 // Notification that an "interesting" frame was popped 90 void OnFramePop(); 91 92 // Notification that a new frame was pushed. Returns true if we want to be notified about the frame is popped 93 // (i.e. the frame is "interesting"), false otherwise 94 bool OnMethodEntry(); 95 96 // Notification that a next step will be performed. Pauses the thread if necessary 97 void OnSingleStep(const PtLocation &location); 98 99 // Notification that a call to console was performed. Returns its arguments presented as remote objects 100 std::vector<RemoteObject> OnConsoleCall(const PandaVector<TypedValue> &arguments); 101 102 private: 103 // Suspends a paused thread. Should be called on an application thread 104 void Suspend(ObjectRepository &objectRepository, const std::vector<BreakpointId> &hitBreakpoints, 105 ObjectHeader *exception) REQUIRES(mutex_); 106 107 // Marks a paused thread as not suspended. Should be called on the server thread 108 void Resume() REQUIRES(mutex_); 109 110 ManagedThread *thread_; 111 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *)> preSuspend_; 112 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *)> postSuspend_; 113 std::function<void()> preWaitSuspension_; 114 std::function<void()> postWaitSuspension_; 115 std::function<void()> preResume_; 116 std::function<void()> postResume_; 117 118 os::memory::Mutex mutex_; 119 ThreadState state_ GUARDED_BY(mutex_); GUARDED_BY(mutex_)120 bool suspended_ GUARDED_BY(mutex_) {false}; 121 std::optional<std::function<void(ObjectRepository &)>> request_ GUARDED_BY(mutex_); 122 os::memory::ConditionVariable requestDone_ GUARDED_BY(mutex_); 123 }; 124 } // namespace panda::tooling::inspector 125 126 #endif // PANDA_TOOLING_INSPECTOR_DEBUGGABLE_THREAD_H 127