diff options
| author | 2016-04-08 16:03:40 -0400 | |
|---|---|---|
| committer | 2016-04-08 16:03:40 -0400 | |
| commit | a4c5d8fd50e32545494a4ac158892310dfe98489 (patch) | |
| tree | 7d7ac94d1f93e6664c28e078fae6f321d1e3f83b /src/core/gdbstub/gdbstub.cpp | |
| parent | update the code of AM service! (#1623) (diff) | |
| parent | Default to settings from ini for gdbstub (diff) | |
| download | yuzu-a4c5d8fd50e32545494a4ac158892310dfe98489.tar.gz yuzu-a4c5d8fd50e32545494a4ac158892310dfe98489.tar.xz yuzu-a4c5d8fd50e32545494a4ac158892310dfe98489.zip | |
Merge pull request #1644 from polaris-/gdb-fixes
Adopted WinterMute's gdbstub changes
Diffstat (limited to 'src/core/gdbstub/gdbstub.cpp')
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 108 |
1 files changed, 85 insertions, 23 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 3a2445241..c1a7ec5bf 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -60,6 +60,59 @@ const u32 R15_REGISTER = 15; | |||
| 60 | const u32 CPSR_REGISTER = 25; | 60 | const u32 CPSR_REGISTER = 25; |
| 61 | const u32 FPSCR_REGISTER = 58; | 61 | const u32 FPSCR_REGISTER = 58; |
| 62 | 62 | ||
| 63 | // For sample XML files see the GDB source /gdb/features | ||
| 64 | // GDB also wants the l character at the start | ||
| 65 | // This XML defines what the registers are for this specific ARM device | ||
| 66 | static const char* target_xml = | ||
| 67 | R"(l<?xml version="1.0"?> | ||
| 68 | <!DOCTYPE target SYSTEM "gdb-target.dtd"> | ||
| 69 | <target version="1.0"> | ||
| 70 | <feature name="org.gnu.gdb.arm.core"> | ||
| 71 | <reg name="r0" bitsize="32"/> | ||
| 72 | <reg name="r1" bitsize="32"/> | ||
| 73 | <reg name="r2" bitsize="32"/> | ||
| 74 | <reg name="r3" bitsize="32"/> | ||
| 75 | <reg name="r4" bitsize="32"/> | ||
| 76 | <reg name="r5" bitsize="32"/> | ||
| 77 | <reg name="r6" bitsize="32"/> | ||
| 78 | <reg name="r7" bitsize="32"/> | ||
| 79 | <reg name="r8" bitsize="32"/> | ||
| 80 | <reg name="r9" bitsize="32"/> | ||
| 81 | <reg name="r10" bitsize="32"/> | ||
| 82 | <reg name="r11" bitsize="32"/> | ||
| 83 | <reg name="r12" bitsize="32"/> | ||
| 84 | <reg name="sp" bitsize="32" type="data_ptr"/> | ||
| 85 | <reg name="lr" bitsize="32"/> | ||
| 86 | <reg name="pc" bitsize="32" type="code_ptr"/> | ||
| 87 | |||
| 88 | <!-- The CPSR is register 25, rather than register 16, because | ||
| 89 | the FPA registers historically were placed between the PC | ||
| 90 | and the CPSR in the "g" packet. --> | ||
| 91 | |||
| 92 | <reg name="cpsr" bitsize="32" regnum="25"/> | ||
| 93 | </feature> | ||
| 94 | <feature name="org.gnu.gdb.arm.vfp"> | ||
| 95 | <reg name="d0" bitsize="64" type="float"/> | ||
| 96 | <reg name="d1" bitsize="64" type="float"/> | ||
| 97 | <reg name="d2" bitsize="64" type="float"/> | ||
| 98 | <reg name="d3" bitsize="64" type="float"/> | ||
| 99 | <reg name="d4" bitsize="64" type="float"/> | ||
| 100 | <reg name="d5" bitsize="64" type="float"/> | ||
| 101 | <reg name="d6" bitsize="64" type="float"/> | ||
| 102 | <reg name="d7" bitsize="64" type="float"/> | ||
| 103 | <reg name="d8" bitsize="64" type="float"/> | ||
| 104 | <reg name="d9" bitsize="64" type="float"/> | ||
| 105 | <reg name="d10" bitsize="64" type="float"/> | ||
| 106 | <reg name="d11" bitsize="64" type="float"/> | ||
| 107 | <reg name="d12" bitsize="64" type="float"/> | ||
| 108 | <reg name="d13" bitsize="64" type="float"/> | ||
| 109 | <reg name="d14" bitsize="64" type="float"/> | ||
| 110 | <reg name="d15" bitsize="64" type="float"/> | ||
| 111 | <reg name="fpscr" bitsize="32" type="int" group="float"/> | ||
| 112 | </feature> | ||
| 113 | </target> | ||
| 114 | )"; | ||
| 115 | |||
| 63 | namespace GDBStub { | 116 | namespace GDBStub { |
| 64 | 117 | ||
| 65 | static int gdbserver_socket = -1; | 118 | static int gdbserver_socket = -1; |
| @@ -211,7 +264,7 @@ static u8 ReadByte() { | |||
| 211 | } | 264 | } |
| 212 | 265 | ||
| 213 | /// Calculate the checksum of the current command buffer. | 266 | /// Calculate the checksum of the current command buffer. |
| 214 | static u8 CalculateChecksum(u8 *buffer, u32 length) { | 267 | static u8 CalculateChecksum(u8* buffer, u32 length) { |
| 215 | return static_cast<u8>(std::accumulate(buffer, buffer + length, 0, std::plus<u8>())); | 268 | return static_cast<u8>(std::accumulate(buffer, buffer + length, 0, std::plus<u8>())); |
| 216 | } | 269 | } |
| 217 | 270 | ||
| @@ -353,8 +406,15 @@ static void SendReply(const char* reply) { | |||
| 353 | static void HandleQuery() { | 406 | static void HandleQuery() { |
| 354 | LOG_DEBUG(Debug_GDBStub, "gdb: query '%s'\n", command_buffer + 1); | 407 | LOG_DEBUG(Debug_GDBStub, "gdb: query '%s'\n", command_buffer + 1); |
| 355 | 408 | ||
| 356 | if (!strcmp(reinterpret_cast<const char*>(command_buffer + 1), "TStatus")) { | 409 | const char* query = reinterpret_cast<const char*>(command_buffer + 1); |
| 410 | |||
| 411 | if (strcmp(query, "TStatus") == 0 ) { | ||
| 357 | SendReply("T0"); | 412 | SendReply("T0"); |
| 413 | } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) { | ||
| 414 | // PacketSize needs to be large enough for target xml | ||
| 415 | SendReply("PacketSize=800;qXfer:features:read+"); | ||
| 416 | } else if (strncmp(query, "Xfer:features:read:target.xml:", strlen("Xfer:features:read:target.xml:")) == 0) { | ||
| 417 | SendReply(target_xml); | ||
| 358 | } else { | 418 | } else { |
| 359 | SendReply(""); | 419 | SendReply(""); |
| 360 | } | 420 | } |
| @@ -491,29 +551,25 @@ static void ReadRegisters() { | |||
| 491 | memset(buffer, 0, sizeof(buffer)); | 551 | memset(buffer, 0, sizeof(buffer)); |
| 492 | 552 | ||
| 493 | u8* bufptr = buffer; | 553 | u8* bufptr = buffer; |
| 494 | for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { | 554 | |
| 495 | if (reg <= R15_REGISTER) { | 555 | for (int reg = 0; reg <= R15_REGISTER; reg++) { |
| 496 | IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg)); | 556 | IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetReg(reg)); |
| 497 | } else if (reg == CPSR_REGISTER) { | ||
| 498 | IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR()); | ||
| 499 | } else if (reg == CPSR_REGISTER - 1) { | ||
| 500 | // Dummy FPA register, ignore | ||
| 501 | IntToGdbHex(bufptr + i * CHAR_BIT, 0); | ||
| 502 | } else if (reg < CPSR_REGISTER) { | ||
| 503 | // Dummy FPA registers, ignore | ||
| 504 | IntToGdbHex(bufptr + i * CHAR_BIT, 0); | ||
| 505 | IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0); | ||
| 506 | IntToGdbHex(bufptr + (i + 2) * CHAR_BIT, 0); | ||
| 507 | i += 2; | ||
| 508 | } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { | ||
| 509 | IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CPSR_REGISTER - 1)); | ||
| 510 | IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0); | ||
| 511 | i++; | ||
| 512 | } else if (reg == FPSCR_REGISTER) { | ||
| 513 | IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); | ||
| 514 | } | ||
| 515 | } | 557 | } |
| 516 | 558 | ||
| 559 | bufptr += (16 * CHAR_BIT); | ||
| 560 | |||
| 561 | IntToGdbHex(bufptr, Core::g_app_core->GetCPSR()); | ||
| 562 | |||
| 563 | bufptr += CHAR_BIT; | ||
| 564 | |||
| 565 | for (int reg = 0; reg <= 31; reg++) { | ||
| 566 | IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetVFPReg(reg)); | ||
| 567 | } | ||
| 568 | |||
| 569 | bufptr += (32 * CHAR_BIT); | ||
| 570 | |||
| 571 | IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); | ||
| 572 | |||
| 517 | SendReply(reinterpret_cast<char*>(buffer)); | 573 | SendReply(reinterpret_cast<char*>(buffer)); |
| 518 | } | 574 | } |
| 519 | 575 | ||
| @@ -885,6 +941,12 @@ void Init(u16 port) { | |||
| 885 | LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); | 941 | LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); |
| 886 | } | 942 | } |
| 887 | 943 | ||
| 944 | // Set socket to SO_REUSEADDR so it can always bind on the same port | ||
| 945 | int reuse_enabled = 1; | ||
| 946 | if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, sizeof(reuse_enabled)) < 0) { | ||
| 947 | LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); | ||
| 948 | } | ||
| 949 | |||
| 888 | const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server); | 950 | const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server); |
| 889 | socklen_t server_addrlen = sizeof(saddr_server); | 951 | socklen_t server_addrlen = sizeof(saddr_server); |
| 890 | if (bind(tmpsock, server_addr, server_addrlen) < 0) { | 952 | if (bind(tmpsock, server_addr, server_addrlen) < 0) { |