gdb_server.cpp (14170B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> and contributors. 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "gdb_server.h" 5 #include "bus.h" 6 #include "cpu_core.h" 7 #include "cpu_core_private.h" 8 #include "system.h" 9 10 #include "common/assert.h" 11 #include "common/log.h" 12 #include "common/small_string.h" 13 #include "common/string_util.h" 14 15 #include "util/sockets.h" 16 17 #include <functional> 18 #include <iomanip> 19 #include <map> 20 #include <optional> 21 #include <sstream> 22 #include <string> 23 24 Log_SetChannel(GDBProtocol); 25 26 namespace GDBProtocol { 27 static bool IsPacketInterrupt(std::string_view data); 28 static bool IsPacketContinue(std::string_view data); 29 30 static bool IsPacketComplete(std::string_view data); 31 static std::string ProcessPacket(std::string_view data); 32 } // namespace GDBProtocol 33 34 namespace GDBProtocol { 35 36 static u8* GetMemoryPointer(PhysicalMemoryAddress address, u32 length) 37 { 38 auto region = Bus::GetMemoryRegionForAddress(address); 39 if (region) 40 { 41 u8* data = GetMemoryRegionPointer(*region); 42 if (data && (address + length <= GetMemoryRegionEnd(*region))) 43 { 44 return data + (address - GetMemoryRegionStart(*region)); 45 } 46 } 47 48 return nullptr; 49 } 50 51 static u8 ComputeChecksum(std::string_view str) 52 { 53 u8 checksum = 0; 54 for (char c : str) 55 { 56 checksum = (checksum + c) % 256; 57 } 58 return checksum; 59 } 60 61 static std::optional<std::string_view> DeserializePacket(std::string_view in) 62 { 63 if ((in.size() < 4) || (in[0] != '$') || (in[in.size() - 3] != '#')) 64 { 65 return std::nullopt; 66 } 67 std::string_view data = in.substr(1, in.size() - 4); 68 69 u8 packetChecksum = StringUtil::FromChars<u8>(in.substr(in.size() - 2, 2), 16).value_or(0); 70 u8 computedChecksum = ComputeChecksum(data); 71 72 if (packetChecksum == computedChecksum) 73 { 74 return {data}; 75 } 76 else 77 { 78 return std::nullopt; 79 } 80 } 81 82 static std::string SerializePacket(std::string_view in) 83 { 84 std::stringstream ss; 85 ss << '$' << in << '#' << TinyString::from_format("{:02x}", ComputeChecksum(in)); 86 return ss.str(); 87 } 88 89 /// List of GDB remote protocol registers for MIPS III (excluding FP). 90 static const std::array<u32*, 38> REGISTERS{ 91 &CPU::g_state.regs.r[0], 92 &CPU::g_state.regs.r[1], 93 &CPU::g_state.regs.r[2], 94 &CPU::g_state.regs.r[3], 95 &CPU::g_state.regs.r[4], 96 &CPU::g_state.regs.r[5], 97 &CPU::g_state.regs.r[6], 98 &CPU::g_state.regs.r[7], 99 &CPU::g_state.regs.r[8], 100 &CPU::g_state.regs.r[9], 101 &CPU::g_state.regs.r[10], 102 &CPU::g_state.regs.r[11], 103 &CPU::g_state.regs.r[12], 104 &CPU::g_state.regs.r[13], 105 &CPU::g_state.regs.r[14], 106 &CPU::g_state.regs.r[15], 107 &CPU::g_state.regs.r[16], 108 &CPU::g_state.regs.r[17], 109 &CPU::g_state.regs.r[18], 110 &CPU::g_state.regs.r[19], 111 &CPU::g_state.regs.r[20], 112 &CPU::g_state.regs.r[21], 113 &CPU::g_state.regs.r[22], 114 &CPU::g_state.regs.r[23], 115 &CPU::g_state.regs.r[24], 116 &CPU::g_state.regs.r[25], 117 &CPU::g_state.regs.r[26], 118 &CPU::g_state.regs.r[27], 119 &CPU::g_state.regs.r[28], 120 &CPU::g_state.regs.r[29], 121 &CPU::g_state.regs.r[30], 122 &CPU::g_state.regs.r[31], 123 124 &CPU::g_state.cop0_regs.sr.bits, 125 &CPU::g_state.regs.lo, 126 &CPU::g_state.regs.hi, 127 &CPU::g_state.cop0_regs.BadVaddr, 128 &CPU::g_state.cop0_regs.cause.bits, 129 &CPU::g_state.pc, 130 }; 131 132 /// Number of registers in GDB remote protocol for MIPS III. 133 constexpr int NUM_GDB_REGISTERS = 73; 134 135 /// Get stop reason. 136 static std::optional<std::string> Cmd$_questionMark(std::string_view data) 137 { 138 return {"S02"}; 139 } 140 141 /// Get general registers. 142 static std::optional<std::string> Cmd$g(std::string_view data) 143 { 144 std::stringstream ss; 145 146 for (u32* reg : REGISTERS) 147 { 148 // Data is in host order (little endian). 149 ss << StringUtil::EncodeHex(reinterpret_cast<u8*>(reg), 4); 150 } 151 152 // Pad with dummy data (FP registers stuff). 153 for (int i = 0; i < NUM_GDB_REGISTERS - static_cast<int>(REGISTERS.size()); i++) 154 { 155 ss << "00000000"; 156 } 157 158 return {ss.str()}; 159 } 160 161 /// Set general registers. 162 static std::optional<std::string> Cmd$G(std::string_view data) 163 { 164 if (data.size() == NUM_GDB_REGISTERS * 8) 165 { 166 int offset = 0; 167 168 for (u32* reg : REGISTERS) 169 { 170 // Data is in host order (little endian). 171 auto value = StringUtil::DecodeHex({data.data() + offset, 8}); 172 if (value) 173 { 174 *reg = *reinterpret_cast<u32*>(&(*value)[0]); 175 } 176 offset += 8; 177 } 178 } 179 else 180 { 181 ERROR_LOG("Wrong payload size for 'G' command, expected {} got {}", NUM_GDB_REGISTERS * 8, data.size()); 182 } 183 184 return {""}; 185 } 186 187 /// Get memory. 188 static std::optional<std::string> Cmd$m(std::string_view data) 189 { 190 std::stringstream ss{std::string{data}}; 191 std::string dataAddress, dataLength; 192 193 std::getline(ss, dataAddress, ','); 194 std::getline(ss, dataLength, '\0'); 195 196 auto address = StringUtil::FromChars<VirtualMemoryAddress>(dataAddress, 16); 197 auto length = StringUtil::FromChars<u32>(dataLength, 16); 198 199 if (address && length) 200 { 201 PhysicalMemoryAddress phys_addr = *address & CPU::PHYSICAL_MEMORY_ADDRESS_MASK; 202 u32 phys_length = *length; 203 204 u8* ptr_data = GetMemoryPointer(phys_addr, phys_length); 205 if (ptr_data) 206 { 207 return {StringUtil::EncodeHex(ptr_data, phys_length)}; 208 } 209 } 210 return {"E00"}; 211 } 212 213 /// Set memory. 214 static std::optional<std::string> Cmd$M(std::string_view data) 215 { 216 std::stringstream ss{std::string{data}}; 217 std::string dataAddress, dataLength, dataPayload; 218 219 std::getline(ss, dataAddress, ','); 220 std::getline(ss, dataLength, ':'); 221 std::getline(ss, dataPayload, '\0'); 222 223 auto address = StringUtil::FromChars<VirtualMemoryAddress>(dataAddress, 16); 224 auto length = StringUtil::FromChars<u32>(dataLength, 16); 225 auto payload = StringUtil::DecodeHex(dataPayload); 226 227 if (address && length && payload && (payload->size() == *length)) 228 { 229 u32 phys_addr = *address & CPU::PHYSICAL_MEMORY_ADDRESS_MASK; 230 u32 phys_length = *length; 231 232 u8* ptr_data = GetMemoryPointer(phys_addr, phys_length); 233 if (ptr_data) 234 { 235 memcpy(ptr_data, payload->data(), phys_length); 236 return {"OK"}; 237 } 238 } 239 240 return {"E00"}; 241 } 242 243 /// Remove hardware breakpoint. 244 static std::optional<std::string> Cmd$z1(std::string_view data) 245 { 246 auto address = StringUtil::FromChars<VirtualMemoryAddress>(data, 16); 247 if (address) 248 { 249 CPU::RemoveBreakpoint(CPU::BreakpointType::Execute, *address); 250 return {"OK"}; 251 } 252 else 253 { 254 return std::nullopt; 255 } 256 } 257 258 /// Insert hardware breakpoint. 259 static std::optional<std::string> Cmd$Z1(std::string_view data) 260 { 261 auto address = StringUtil::FromChars<VirtualMemoryAddress>(data, 16); 262 if (address) 263 { 264 CPU::AddBreakpoint(CPU::BreakpointType::Execute, *address, false); 265 return {"OK"}; 266 } 267 else 268 { 269 return std::nullopt; 270 } 271 } 272 273 static std::optional<std::string> Cmd$vMustReplyEmpty(std::string_view data) 274 { 275 return {""}; 276 } 277 278 static std::optional<std::string> Cmd$qSupported(std::string_view data) 279 { 280 return {""}; 281 } 282 283 /// List of all GDB remote protocol packets supported by us. 284 static const std::map<const char*, std::function<std::optional<std::string>(std::string_view)>> COMMANDS{ 285 {"?", Cmd$_questionMark}, 286 {"g", Cmd$g}, 287 {"G", Cmd$G}, 288 {"m", Cmd$m}, 289 {"M", Cmd$M}, 290 {"z0,", Cmd$z1}, 291 {"Z0,", Cmd$Z1}, 292 {"z1,", Cmd$z1}, 293 {"Z1,", Cmd$Z1}, 294 {"vMustReplyEmpty", Cmd$vMustReplyEmpty}, 295 {"qSupported", Cmd$qSupported}, 296 }; 297 298 bool IsPacketInterrupt(std::string_view data) 299 { 300 return (data.size() >= 1) && (data[data.size() - 1] == '\003'); 301 } 302 303 bool IsPacketContinue(std::string_view data) 304 { 305 return (data.size() >= 5) && (data.substr(data.size() - 5) == "$c#63"); 306 } 307 308 bool IsPacketComplete(std::string_view data) 309 { 310 return ((data.size() == 1) && (data[0] == '\003')) || ((data.size() > 3) && (*(data.end() - 3) == '#')); 311 } 312 313 std::string ProcessPacket(std::string_view data) 314 { 315 std::string_view trimmedData = data; 316 317 // Eat ACKs. 318 while (!trimmedData.empty() && (trimmedData[0] == '+' || trimmedData[0] == '-')) 319 { 320 if (trimmedData[0] == '-') 321 { 322 ERROR_LOG("Received negative ack"); 323 } 324 trimmedData = trimmedData.substr(1); 325 } 326 327 // Validate packet. 328 auto packet = DeserializePacket(trimmedData); 329 if (!packet) 330 { 331 ERROR_LOG("Malformed packet '{}'", trimmedData); 332 return "-"; 333 } 334 335 std::optional<std::string> reply = {""}; 336 337 // Try to invoke packet command. 338 bool processed = false; 339 for (const auto& command : COMMANDS) 340 { 341 if (packet->starts_with(command.first)) 342 { 343 DEBUG_LOG("Processing command '{}'", command.first); 344 345 // Invoke command, remove command name from payload. 346 reply = command.second(packet->substr(strlen(command.first))); 347 processed = true; 348 break; 349 } 350 } 351 352 if (!processed) 353 WARNING_LOG("Failed to process packet '{}'", trimmedData); 354 355 return reply ? "+" + SerializePacket(*reply) : "+"; 356 } 357 358 } // namespace GDBProtocol 359 360 namespace GDBServer { 361 362 namespace { 363 class ClientSocket final : public BufferedStreamSocket 364 { 365 public: 366 ClientSocket(SocketMultiplexer& multiplexer, SocketDescriptor descriptor); 367 ~ClientSocket() override; 368 369 void OnSystemPaused(); 370 void OnSystemResumed(); 371 372 protected: 373 void OnConnected() override; 374 void OnDisconnected(const Error& error) override; 375 void OnRead() override; 376 377 private: 378 void SendPacket(std::string_view sv); 379 380 bool m_seen_resume = false; 381 }; 382 } // namespace 383 384 static std::shared_ptr<ListenSocket> s_gdb_listen_socket; 385 static std::vector<std::shared_ptr<ClientSocket>> s_gdb_clients; 386 } // namespace GDBServer 387 388 GDBServer::ClientSocket::ClientSocket(SocketMultiplexer& multiplexer, SocketDescriptor descriptor) 389 : BufferedStreamSocket(multiplexer, descriptor, 65536, 65536) 390 { 391 } 392 393 GDBServer::ClientSocket::~ClientSocket() = default; 394 395 void GDBServer::ClientSocket::OnConnected() 396 { 397 INFO_LOG("Client {} connected.", GetRemoteAddress().ToString()); 398 399 m_seen_resume = System::IsPaused(); 400 System::PauseSystem(true); 401 402 s_gdb_clients.push_back(std::static_pointer_cast<ClientSocket>(shared_from_this())); 403 } 404 405 void GDBServer::ClientSocket::OnDisconnected(const Error& error) 406 { 407 INFO_LOG("Client {} disconnected: {}", GetRemoteAddress().ToString(), error.GetDescription()); 408 409 const auto iter = std::find_if(s_gdb_clients.begin(), s_gdb_clients.end(), 410 [this](const std::shared_ptr<ClientSocket>& rhs) { return (rhs.get() == this); }); 411 if (iter == s_gdb_clients.end()) 412 { 413 ERROR_LOG("Unknown GDB client disconnected? This should never happen."); 414 return; 415 } 416 417 s_gdb_clients.erase(iter); 418 } 419 420 void GDBServer::ClientSocket::OnRead() 421 { 422 const std::span<const u8> buffer = AcquireReadBuffer(); 423 if (buffer.empty()) 424 return; 425 426 size_t buffer_offset = 0; 427 while (buffer_offset < buffer.size()) 428 { 429 size_t current_packet_size = 1; 430 bool packet_complete = false; 431 for (; (buffer_offset + current_packet_size) <= buffer.size(); current_packet_size++) 432 { 433 const std::string_view current_packet(reinterpret_cast<const char*>(buffer.data() + buffer_offset), 434 current_packet_size); 435 436 if (GDBProtocol::IsPacketInterrupt(current_packet)) 437 { 438 DEV_LOG("{} > Interrupt request", GetRemoteAddress().ToString()); 439 System::PauseSystem(true); 440 packet_complete = true; 441 break; 442 } 443 else if (GDBProtocol::IsPacketContinue(current_packet)) 444 { 445 DEV_LOG("{} > Continue request", GetRemoteAddress().ToString()); 446 System::PauseSystem(false); 447 packet_complete = true; 448 break; 449 } 450 else if (GDBProtocol::IsPacketComplete(current_packet)) 451 { 452 // TODO: Make this not copy. 453 DEV_LOG("{} > {}", GetRemoteAddress().ToString(), current_packet); 454 SendPacket(GDBProtocol::ProcessPacket(current_packet)); 455 packet_complete = true; 456 break; 457 } 458 } 459 460 if (!packet_complete) 461 { 462 WARNING_LOG("Incomplete packet, got {} bytes.", buffer.size() - buffer_offset); 463 break; 464 } 465 else 466 { 467 buffer_offset += current_packet_size; 468 } 469 } 470 471 ReleaseReadBuffer(buffer_offset); 472 } 473 474 void GDBServer::ClientSocket::SendPacket(std::string_view sv) 475 { 476 if (sv.empty()) 477 return; 478 479 WARNING_LOG("Write: {}", sv); 480 if (size_t written = Write(sv.data(), sv.length()); written != sv.length()) 481 ERROR_LOG("Only wrote {} of {} bytes.", written, sv.length()); 482 } 483 484 void GDBServer::ClientSocket::OnSystemPaused() 485 { 486 if (!m_seen_resume) 487 return; 488 489 m_seen_resume = false; 490 491 // Generate a stop reply packet, insert '?' command to generate it. 492 SendPacket(GDBProtocol::ProcessPacket("$?#3f")); 493 } 494 495 void GDBServer::ClientSocket::OnSystemResumed() 496 { 497 m_seen_resume = true; 498 499 // Send ack, in case GDB sent a continue request. 500 SendPacket("+"); 501 } 502 503 bool GDBServer::Initialize(u16 port) 504 { 505 Error error; 506 Assert(!s_gdb_listen_socket); 507 508 const std::optional<SocketAddress> address = 509 SocketAddress::Parse(SocketAddress::Type::IPv4, "127.0.0.1", port, &error); 510 if (!address.has_value()) 511 { 512 ERROR_LOG("Failed to parse address: {}", error.GetDescription()); 513 return false; 514 } 515 516 SocketMultiplexer* multiplexer = System::GetSocketMultiplexer(); 517 if (!multiplexer) 518 return false; 519 520 s_gdb_listen_socket = multiplexer->CreateListenSocket<ClientSocket>(address.value(), &error); 521 if (!s_gdb_listen_socket) 522 { 523 ERROR_LOG("Failed to create listen socket: {}", error.GetDescription()); 524 System::ReleaseSocketMultiplexer(); 525 return false; 526 } 527 528 INFO_LOG("GDB server is now listening on {}.", address->ToString()); 529 return true; 530 } 531 532 bool GDBServer::HasAnyClients() 533 { 534 return !s_gdb_clients.empty(); 535 } 536 537 void GDBServer::Shutdown() 538 { 539 if (!s_gdb_listen_socket) 540 return; 541 542 INFO_LOG("Disconnecting {} GDB clients...", s_gdb_clients.size()); 543 while (!s_gdb_clients.empty()) 544 { 545 // maintain a reference so we don't delete while in scope 546 std::shared_ptr<ClientSocket> client = s_gdb_clients.back(); 547 client->Close(); 548 } 549 550 INFO_LOG("Stopping GDB server."); 551 s_gdb_listen_socket->Close(); 552 s_gdb_listen_socket.reset(); 553 System::ReleaseSocketMultiplexer(); 554 } 555 556 void GDBServer::OnSystemPaused() 557 { 558 for (auto& it : s_gdb_clients) 559 it->OnSystemPaused(); 560 } 561 562 void GDBServer::OnSystemResumed() 563 { 564 for (auto& it : s_gdb_clients) 565 it->OnSystemResumed(); 566 }