diff options
Diffstat (limited to 'src/core/debugger/debugger.cpp')
| -rw-r--r-- | src/core/debugger/debugger.cpp | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 7774ffdef..edf991d71 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp | |||
| @@ -42,6 +42,16 @@ static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) { | |||
| 42 | return received_data; | 42 | return received_data; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | enum class SignalType { | ||
| 46 | Stopped, | ||
| 47 | ShuttingDown, | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct SignalInfo { | ||
| 51 | SignalType type; | ||
| 52 | Kernel::KThread* thread; | ||
| 53 | }; | ||
| 54 | |||
| 45 | namespace Core { | 55 | namespace Core { |
| 46 | 56 | ||
| 47 | class DebuggerImpl : public DebuggerBackend { | 57 | class DebuggerImpl : public DebuggerBackend { |
| @@ -56,7 +66,7 @@ public: | |||
| 56 | ShutdownServer(); | 66 | ShutdownServer(); |
| 57 | } | 67 | } |
| 58 | 68 | ||
| 59 | bool NotifyThreadStopped(Kernel::KThread* thread) { | 69 | bool SignalDebugger(SignalInfo signal_info) { |
| 60 | std::scoped_lock lk{connection_lock}; | 70 | std::scoped_lock lk{connection_lock}; |
| 61 | 71 | ||
| 62 | if (stopped) { | 72 | if (stopped) { |
| @@ -64,9 +74,13 @@ public: | |||
| 64 | // It should be ignored. | 74 | // It should be ignored. |
| 65 | return false; | 75 | return false; |
| 66 | } | 76 | } |
| 77 | |||
| 78 | // Set up the state. | ||
| 67 | stopped = true; | 79 | stopped = true; |
| 80 | info = signal_info; | ||
| 68 | 81 | ||
| 69 | boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread))); | 82 | // Write a single byte into the pipe to wake up the debug interface. |
| 83 | boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped))); | ||
| 70 | return true; | 84 | return true; |
| 71 | } | 85 | } |
| 72 | 86 | ||
| @@ -124,7 +138,7 @@ private: | |||
| 124 | Common::SetCurrentThreadName("yuzu:Debugger"); | 138 | Common::SetCurrentThreadName("yuzu:Debugger"); |
| 125 | 139 | ||
| 126 | // Set up the client signals for new data. | 140 | // Set up the client signals for new data. |
| 127 | AsyncReceiveInto(signal_pipe, active_thread, [&](auto d) { PipeData(d); }); | 141 | AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); }); |
| 128 | AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); | 142 | AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); |
| 129 | 143 | ||
| 130 | // Stop the emulated CPU. | 144 | // Stop the emulated CPU. |
| @@ -142,9 +156,28 @@ private: | |||
| 142 | } | 156 | } |
| 143 | 157 | ||
| 144 | void PipeData(std::span<const u8> data) { | 158 | void PipeData(std::span<const u8> data) { |
| 145 | AllCoreStop(); | 159 | switch (info.type) { |
| 146 | UpdateActiveThread(); | 160 | case SignalType::Stopped: |
| 147 | frontend->Stopped(active_thread); | 161 | // Stop emulation. |
| 162 | AllCoreStop(); | ||
| 163 | |||
| 164 | // Notify the client. | ||
| 165 | active_thread = info.thread; | ||
| 166 | UpdateActiveThread(); | ||
| 167 | frontend->Stopped(active_thread); | ||
| 168 | |||
| 169 | break; | ||
| 170 | case SignalType::ShuttingDown: | ||
| 171 | frontend->ShuttingDown(); | ||
| 172 | |||
| 173 | // Wait for emulation to shut down gracefully now. | ||
| 174 | suspend.reset(); | ||
| 175 | signal_pipe.close(); | ||
| 176 | client_socket.shutdown(boost::asio::socket_base::shutdown_both); | ||
| 177 | LOG_INFO(Debug_GDBStub, "Shut down server"); | ||
| 178 | |||
| 179 | break; | ||
| 180 | } | ||
| 148 | } | 181 | } |
| 149 | 182 | ||
| 150 | void ClientData(std::span<const u8> data) { | 183 | void ClientData(std::span<const u8> data) { |
| @@ -246,7 +279,9 @@ private: | |||
| 246 | boost::asio::ip::tcp::socket client_socket; | 279 | boost::asio::ip::tcp::socket client_socket; |
| 247 | std::optional<std::unique_lock<std::mutex>> suspend; | 280 | std::optional<std::unique_lock<std::mutex>> suspend; |
| 248 | 281 | ||
| 282 | SignalInfo info; | ||
| 249 | Kernel::KThread* active_thread; | 283 | Kernel::KThread* active_thread; |
| 284 | bool pipe_data; | ||
| 250 | bool stopped; | 285 | bool stopped; |
| 251 | 286 | ||
| 252 | std::array<u8, 4096> client_data; | 287 | std::array<u8, 4096> client_data; |
| @@ -263,7 +298,13 @@ Debugger::Debugger(Core::System& system, u16 port) { | |||
| 263 | Debugger::~Debugger() = default; | 298 | Debugger::~Debugger() = default; |
| 264 | 299 | ||
| 265 | bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { | 300 | bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { |
| 266 | return impl && impl->NotifyThreadStopped(thread); | 301 | return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread}); |
| 302 | } | ||
| 303 | |||
| 304 | void Debugger::NotifyShutdown() { | ||
| 305 | if (impl) { | ||
| 306 | impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr}); | ||
| 307 | } | ||
| 267 | } | 308 | } |
| 268 | 309 | ||
| 269 | } // namespace Core | 310 | } // namespace Core |