1 /** 2 * Copyright (c) 2022-2025 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 "common.h" 20 #include "debug_info_cache.h" 21 #include "include/managed_thread.h" 22 #include "include/tooling/pt_location.h" 23 24 #include "evaluation/evaluation_engine.h" 25 #include "object_repository.h" 26 #include "thread_state.h" 27 #include "types/numeric_id.h" 28 #include "types/pause_on_exceptions_state.h" 29 30 namespace ark::tooling::inspector { 31 /** 32 * @brief Application thread abstraction. 33 * Note that private inheritance is used in order not to expose evaluation-related state details. 34 */ 35 class DebuggableThread final : private PtThreadEvaluationEngine { 36 public: 37 struct SuspensionCallbacks final { 38 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *)> preSuspend; 39 std::function<void(ObjectRepository &, const std::vector<BreakpointId> &, ObjectHeader *, PauseReason)> 40 postSuspend; 41 std::function<void()> preWaitSuspension; 42 std::function<void()> postWaitSuspension; 43 std::function<void()> preResume; 44 std::function<void()> postResume; 45 }; 46 47 public: 48 DebuggableThread(ManagedThread *thread, DebugInterface *debugger, SuspensionCallbacks &&callbacks, 49 BreakpointStorage &bpStorage); 50 ~DebuggableThread() override = default; 51 52 NO_COPY_SEMANTIC(DebuggableThread); 53 NO_MOVE_SEMANTIC(DebuggableThread); 54 55 /// The following methods should be called on the server thread 56 57 // Resets the state on a new connection 58 void Reset(); 59 60 // Tells a newly created thread to pause on the next step 61 void BreakOnStart(); 62 63 // Continues execution of a paused thread 64 void Continue(); 65 66 // Continues execution of a paused thread until it reaches one of the locations 67 void ContinueTo(std::unordered_set<PtLocation, HashLocation> locations); 68 69 // Tells a paused thread to perform a step into 70 void StepInto(std::unordered_set<PtLocation, HashLocation> locations); 71 72 // Tells a paused thread to perform a step over 73 void StepOver(std::unordered_set<PtLocation, HashLocation> locations); 74 75 // Tells a paused thread to perform a step out 76 void StepOut(); 77 78 // Checks if application thread is currently paused. 79 // Used by server thread for validation before executing stepping requests. 80 bool IsPaused(); 81 82 // Makes a paused thread to resume and suspend back (does nothing for running threads). 83 // Used to notify about thread's state when processing `runIfWaitingForDebugger` 84 void Touch(); 85 86 // Tells a running thread to pause on the next step 87 void Pause(); 88 89 // Enables or disables skipping all pauses 90 void SetSkipAllPauses(bool skip); 91 92 // Enables or disables mixdebug && mixstack 93 void SetMixedDebugEnabled(bool mixedDebugEnabled); 94 95 // Tells when stops should be made on exceptions 96 void SetPauseOnExceptions(PauseOnExceptionsState state); 97 98 // Executes a request to object repository on a paused thread (does nothing for running threads) 99 bool RequestToObjectRepository(std::function<void(ObjectRepository &)> request); 100 101 /// The following methods should be called on an application thread 102 103 // Notification that an exception was thrown. Pauses the thread if necessary 104 void OnException(bool uncaught); 105 106 // Notification that an "interesting" frame was popped 107 void OnFramePop(); 108 109 // Notification that a new frame was pushed. Returns true if we want to be notified about the frame is popped 110 // (i.e. the frame is "interesting"), false otherwise 111 bool OnMethodEntry(); 112 113 // Notification that a next step will be performed. Pauses the thread if necessary 114 void OnSingleStep(const PtLocation &location, const char *sourceFile); 115 116 // Notification that a call to console was performed. Returns its arguments presented as remote objects 117 std::vector<RemoteObject> OnConsoleCall(const PandaVector<TypedValue> &arguments); 118 119 /** 120 * @brief Evaluates the given bytecode expression. 121 * @param frameNumber frame depth to evaluate expression in. 122 * @param bytecode fragment with expression. 123 * @returns pair of result (might be void) and optional exception objects OR error message 124 */ 125 Expected<std::pair<RemoteObject, std::optional<RemoteObject>>, std::string> EvaluateExpression( 126 uint32_t frameNumber, const ExpressionWrapper &bytecode); 127 128 private: 129 using PtThreadEvaluationEngine::EvaluateExpression; 130 131 // Suspends a paused thread. Should be called on an application thread 132 void Suspend(ObjectRepository &objectRepository, const std::vector<BreakpointId> &hitBreakpoints, 133 ObjectHeader *exception, PauseReason pauseReason) REQUIRES(mutex_); 134 135 // Marks a paused thread as not suspended. Should be called on the server thread 136 void Resume() REQUIRES(mutex_); 137 138 private: 139 SuspensionCallbacks callbacks_; 140 141 os::memory::Mutex mutex_; 142 ThreadState state_ GUARDED_BY(mutex_); GUARDED_BY(mutex_)143 bool suspended_ GUARDED_BY(mutex_) {false}; 144 std::optional<std::function<void(ObjectRepository &)>> request_ GUARDED_BY(mutex_); 145 os::memory::ConditionVariable requestDone_ GUARDED_BY(mutex_); 146 }; 147 } // namespace ark::tooling::inspector 148 149 #endif // PANDA_TOOLING_INSPECTOR_DEBUGGABLE_THREAD_H 150