diff options
| author | 2024-01-16 00:09:00 +0000 | |
|---|---|---|
| committer | 2024-01-16 00:09:00 +0000 | |
| commit | 90ab89a0b0174f8df559b79dc06a03479d959f93 (patch) | |
| tree | 3d11a790e44945e309f0e68f5332b33b42e72bbb /src/core/debugger/debugger.cpp | |
| parent | Fix typos in arrays.xml (diff) | |
| parent | Merge pull request #12681 from t895/stick-toggles (diff) | |
| download | yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.gz yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.xz yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.zip | |
Merge remote-tracking branch 'origin/master' into typos3
Diffstat (limited to 'src/core/debugger/debugger.cpp')
| -rw-r--r-- | src/core/debugger/debugger.cpp | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 0e270eb50..e86aae846 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp | |||
| @@ -114,7 +114,7 @@ public: | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | Kernel::KThread* GetActiveThread() override { | 116 | Kernel::KThread* GetActiveThread() override { |
| 117 | return state->active_thread; | 117 | return state->active_thread.GetPointerUnsafe(); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | private: | 120 | private: |
| @@ -147,11 +147,14 @@ private: | |||
| 147 | 147 | ||
| 148 | std::scoped_lock lk{connection_lock}; | 148 | std::scoped_lock lk{connection_lock}; |
| 149 | 149 | ||
| 150 | // Find the process we are going to debug. | ||
| 151 | SetDebugProcess(); | ||
| 152 | |||
| 150 | // Ensure everything is stopped. | 153 | // Ensure everything is stopped. |
| 151 | PauseEmulation(); | 154 | PauseEmulation(); |
| 152 | 155 | ||
| 153 | // Set up the new frontend. | 156 | // Set up the new frontend. |
| 154 | frontend = std::make_unique<GDBStub>(*this, system); | 157 | frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe()); |
| 155 | 158 | ||
| 156 | // Set the new state. This will tear down any existing state. | 159 | // Set the new state. This will tear down any existing state. |
| 157 | state = ConnectionState{ | 160 | state = ConnectionState{ |
| @@ -194,15 +197,20 @@ private: | |||
| 194 | UpdateActiveThread(); | 197 | UpdateActiveThread(); |
| 195 | 198 | ||
| 196 | if (state->info.type == SignalType::Watchpoint) { | 199 | if (state->info.type == SignalType::Watchpoint) { |
| 197 | frontend->Watchpoint(state->active_thread, *state->info.watchpoint); | 200 | frontend->Watchpoint(std::addressof(*state->active_thread), |
| 201 | *state->info.watchpoint); | ||
| 198 | } else { | 202 | } else { |
| 199 | frontend->Stopped(state->active_thread); | 203 | frontend->Stopped(std::addressof(*state->active_thread)); |
| 200 | } | 204 | } |
| 201 | 205 | ||
| 202 | break; | 206 | break; |
| 203 | case SignalType::ShuttingDown: | 207 | case SignalType::ShuttingDown: |
| 204 | frontend->ShuttingDown(); | 208 | frontend->ShuttingDown(); |
| 205 | 209 | ||
| 210 | // Release members. | ||
| 211 | state->active_thread.Reset(nullptr); | ||
| 212 | debug_process.Reset(nullptr); | ||
| 213 | |||
| 206 | // Wait for emulation to shut down gracefully now. | 214 | // Wait for emulation to shut down gracefully now. |
| 207 | state->signal_pipe.close(); | 215 | state->signal_pipe.close(); |
| 208 | state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); | 216 | state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); |
| @@ -222,7 +230,7 @@ private: | |||
| 222 | stopped = true; | 230 | stopped = true; |
| 223 | PauseEmulation(); | 231 | PauseEmulation(); |
| 224 | UpdateActiveThread(); | 232 | UpdateActiveThread(); |
| 225 | frontend->Stopped(state->active_thread); | 233 | frontend->Stopped(state->active_thread.GetPointerUnsafe()); |
| 226 | break; | 234 | break; |
| 227 | } | 235 | } |
| 228 | case DebuggerAction::Continue: | 236 | case DebuggerAction::Continue: |
| @@ -232,7 +240,7 @@ private: | |||
| 232 | MarkResumed([&] { | 240 | MarkResumed([&] { |
| 233 | state->active_thread->SetStepState(Kernel::StepState::StepPending); | 241 | state->active_thread->SetStepState(Kernel::StepState::StepPending); |
| 234 | state->active_thread->Resume(Kernel::SuspendType::Debug); | 242 | state->active_thread->Resume(Kernel::SuspendType::Debug); |
| 235 | ResumeEmulation(state->active_thread); | 243 | ResumeEmulation(state->active_thread.GetPointerUnsafe()); |
| 236 | }); | 244 | }); |
| 237 | break; | 245 | break; |
| 238 | case DebuggerAction::StepThreadLocked: { | 246 | case DebuggerAction::StepThreadLocked: { |
| @@ -255,6 +263,7 @@ private: | |||
| 255 | } | 263 | } |
| 256 | 264 | ||
| 257 | void PauseEmulation() { | 265 | void PauseEmulation() { |
| 266 | Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||
| 258 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; | 267 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; |
| 259 | 268 | ||
| 260 | // Put all threads to sleep on next scheduler round. | 269 | // Put all threads to sleep on next scheduler round. |
| @@ -264,6 +273,9 @@ private: | |||
| 264 | } | 273 | } |
| 265 | 274 | ||
| 266 | void ResumeEmulation(Kernel::KThread* except = nullptr) { | 275 | void ResumeEmulation(Kernel::KThread* except = nullptr) { |
| 276 | Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||
| 277 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||
| 278 | |||
| 267 | // Wake up all threads. | 279 | // Wake up all threads. |
| 268 | for (auto& thread : ThreadList()) { | 280 | for (auto& thread : ThreadList()) { |
| 269 | if (std::addressof(thread) == except) { | 281 | if (std::addressof(thread) == except) { |
| @@ -277,15 +289,16 @@ private: | |||
| 277 | 289 | ||
| 278 | template <typename Callback> | 290 | template <typename Callback> |
| 279 | void MarkResumed(Callback&& cb) { | 291 | void MarkResumed(Callback&& cb) { |
| 280 | Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||
| 281 | stopped = false; | 292 | stopped = false; |
| 282 | cb(); | 293 | cb(); |
| 283 | } | 294 | } |
| 284 | 295 | ||
| 285 | void UpdateActiveThread() { | 296 | void UpdateActiveThread() { |
| 297 | Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||
| 298 | |||
| 286 | auto& threads{ThreadList()}; | 299 | auto& threads{ThreadList()}; |
| 287 | for (auto& thread : threads) { | 300 | for (auto& thread : threads) { |
| 288 | if (std::addressof(thread) == state->active_thread) { | 301 | if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) { |
| 289 | // Thread is still alive, no need to update. | 302 | // Thread is still alive, no need to update. |
| 290 | return; | 303 | return; |
| 291 | } | 304 | } |
| @@ -293,12 +306,18 @@ private: | |||
| 293 | state->active_thread = std::addressof(threads.front()); | 306 | state->active_thread = std::addressof(threads.front()); |
| 294 | } | 307 | } |
| 295 | 308 | ||
| 309 | private: | ||
| 310 | void SetDebugProcess() { | ||
| 311 | debug_process = std::move(system.Kernel().GetProcessList().back()); | ||
| 312 | } | ||
| 313 | |||
| 296 | Kernel::KProcess::ThreadList& ThreadList() { | 314 | Kernel::KProcess::ThreadList& ThreadList() { |
| 297 | return system.ApplicationProcess()->GetThreadList(); | 315 | return debug_process->GetThreadList(); |
| 298 | } | 316 | } |
| 299 | 317 | ||
| 300 | private: | 318 | private: |
| 301 | System& system; | 319 | System& system; |
| 320 | Kernel::KScopedAutoObject<Kernel::KProcess> debug_process; | ||
| 302 | std::unique_ptr<DebuggerFrontend> frontend; | 321 | std::unique_ptr<DebuggerFrontend> frontend; |
| 303 | 322 | ||
| 304 | boost::asio::io_context io_context; | 323 | boost::asio::io_context io_context; |
| @@ -310,7 +329,7 @@ private: | |||
| 310 | boost::process::async_pipe signal_pipe; | 329 | boost::process::async_pipe signal_pipe; |
| 311 | 330 | ||
| 312 | SignalInfo info; | 331 | SignalInfo info; |
| 313 | Kernel::KThread* active_thread; | 332 | Kernel::KScopedAutoObject<Kernel::KThread> active_thread; |
| 314 | std::array<u8, 4096> client_data; | 333 | std::array<u8, 4096> client_data; |
| 315 | bool pipe_data; | 334 | bool pipe_data; |
| 316 | }; | 335 | }; |