From 7ab44f41ca9d1bb6eed0d997b295ebfca2389390 Mon Sep 17 00:00:00 2001 From: Xavi Del Campo Date: Mon, 20 Apr 2020 17:08:20 +0200 Subject: Support for multiple sockets --- libpcsxcore/socket.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'libpcsxcore/socket.h') diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h index 7ee0deb4..ef26de02 100644 --- a/libpcsxcore/socket.h +++ b/libpcsxcore/socket.h @@ -22,20 +22,20 @@ extern "C" { #endif -int StartServer(); -void StopServer(); +int StartServer(unsigned short port); +void StopServer(int s_socket); -void GetClient(); -void CloseClient(); +void GetClient(int s_socket, int *client_socket); +void CloseClient(int *client_socket); -int HasClient(); +int HasClient(int client_socket); -int ReadSocket(char * buffer, int len); -int RawReadSocket(char * buffer, int len); -void WriteSocket(char * buffer, int len); +int ReadSocket(int *client_socket, char * buffer, int len); +int RawReadSocket(int *client_socket, char * buffer, int len); +void WriteSocket(int *client_socket, char * buffer, int len); -void SetsBlock(); -void SetsNonblock(); +void SetsBlock(int s_socket); +void SetsNonblock(int s_socket); #ifdef __cplusplus } -- cgit v1.2.3 From 486666e7173a0ed72248329e960ffc03f79b8707 Mon Sep 17 00:00:00 2001 From: Xavi Del Campo Date: Sat, 2 May 2020 02:34:17 +0200 Subject: Introduced dynstr, other breaking changes --- CMakeLists.txt | 4 +- dynstr/CMakeLists.txt | 5 + libpcsxcore/CMakeLists.txt | 4 +- libpcsxcore/debug.c | 393 +++++++++++++++++++++++++-------------------- libpcsxcore/ppf.c | 18 ++- libpcsxcore/socket.c | 123 ++++++++------ libpcsxcore/socket.h | 20 ++- 7 files changed, 333 insertions(+), 234 deletions(-) create mode 100644 dynstr/CMakeLists.txt (limited to 'libpcsxcore/socket.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index c7f61cc3..4855ae14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,4 @@ add_subdirectory(libpcsxcore) add_subdirectory(gui) add_subdirectory(plugins) add_subdirectory(doc) - - - +add_subdirectory(dynstr) diff --git a/dynstr/CMakeLists.txt b/dynstr/CMakeLists.txt new file mode 100644 index 00000000..38313dbc --- /dev/null +++ b/dynstr/CMakeLists.txt @@ -0,0 +1,5 @@ +message(STATUS "* Configuring dynstr") + +set(SRCS dynstr/dynstr.c) +include_directories(dynstr/include) +add_library(dynstr STATIC ${SRCS}) diff --git a/libpcsxcore/CMakeLists.txt b/libpcsxcore/CMakeLists.txt index b8caef4c..827a8f0a 100644 --- a/libpcsxcore/CMakeLists.txt +++ b/libpcsxcore/CMakeLists.txt @@ -6,6 +6,8 @@ set_property(CACHE DYNAREC PROPERTY STRINGS auto x86_64 x86 ppc no) option(ENABLE_CCDDA "Enables compressed CDDA support." OFF) option(USE_LIBARCHIVE "Enables compressed data-tracks support." OFF) +include_directories(../dynstr/dynstr/include) + if (ENABLE_CCDDA) find_package(FFMPEG REQUIRED) include_directories(${FFMPEG_INCLUDE_DIRS}) @@ -114,4 +116,4 @@ endif() set(SRCS ${SRCS} ${DYNAREC_SRC}) add_library(pcsxcore STATIC ${SRCS}) -target_link_libraries(pcsxcore ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) +target_link_libraries(pcsxcore dynstr ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c index a4e9ab35..e2e2992f 100644 --- a/libpcsxcore/debug.c +++ b/libpcsxcore/debug.c @@ -19,6 +19,8 @@ #include "r3000a.h" #include "debug.h" #include "socket.h" +#include +#include /* PCSXR Debug console protocol description, version 1.0 @@ -134,7 +136,7 @@ Execution flow control commands (3xx): Soft (quick) resets. 399 Resets. - + Server outputs: ~~~~~~~~~~~~~~ @@ -236,6 +238,9 @@ static int step_over = 0; static u32 step_over_addr = 0; static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0; static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0; +static int server_socket, client_socket; +static char tbuf[513]; +static size_t ptr; static void ProcessCommands(); @@ -317,6 +322,11 @@ breakpoint_t *find_breakpoint(int number) { } void StartDebugger() { + enum + { + PORT_NUMBER = 12345 + }; + if (debugger_active) return; @@ -326,7 +336,9 @@ void StartDebugger() { return; } - if (StartServer() == -1) { + server_socket = StartServer(PORT_NUMBER); + + if (server_socket == -1) { SysPrintf("%s", _("Unable to start debug server.\n")); return; } @@ -337,7 +349,7 @@ void StartDebugger() { void StopDebugger() { if (debugger_active) { - StopServer(); + StopServer(server_socket); SysPrintf("%s", _("Debugger stopped.\n")); } @@ -361,6 +373,14 @@ void ResumeDebugger() { paused = 0; } +static void DebugHello(void) +{ + static const char hello[] = "000 PCSXR Version " PACKAGE_VERSION " - Debug console\r\n"; + + WriteSocket(client_socket, hello, sizeof hello); + ptr = 0; +} + void DebugVSync() { if (!debugger_active || resetting) return; @@ -375,7 +395,7 @@ void DebugVSync() { return; } - GetClient(); + client_socket = GetClient(server_socket); ProcessCommands(); } @@ -398,33 +418,42 @@ void ProcessDebug() { } if (!paused) { if(trace && printpc) { - char reply[256]; - sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(psxRegs.pc), psxRegs.pc)); - WriteSocket(reply, strlen(reply)); + struct dynstr reply; + + dynstr_init(&reply); + dynstr_append(&reply, "219 %s\r\n", disR3000AF(psxMemRead32(psxRegs.pc), psxRegs.pc)); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); } - + if(step_over) { if(psxRegs.pc == step_over_addr) { - char reply[256]; + struct dynstr reply; + + dynstr_init(&reply); step_over = 0; step_over_addr = 0; - sprintf(reply, "050 @%08X\r\n", psxRegs.pc); - WriteSocket(reply, strlen(reply)); + dynstr_append(&reply, "050 @%08X\r\n", psxRegs.pc); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); paused = 1; } } - + if(run_to) { if(psxRegs.pc == run_to_addr) { - char reply[256]; + struct dynstr reply; + run_to = 0; run_to_addr = 0; - sprintf(reply, "040 @%08X\r\n", psxRegs.pc); - WriteSocket(reply, strlen(reply)); + dynstr_init(&reply); + dynstr_append(&reply, "040 @%08X\r\n", psxRegs.pc); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); paused = 1; } } - + DebugCheckBP(psxRegs.pc, BE); } if (mapping_e) { @@ -437,7 +466,7 @@ void ProcessDebug() { } } while (paused) { - GetClient(); + client_socket = GetClient(server_socket); ProcessCommands(); GPU_updateLace(); SysUpdate(); @@ -446,14 +475,32 @@ void ProcessDebug() { static void ProcessCommands() { int code, i, dumping; - FILE *sfile; - char cmd[257], *arguments, *p, reply[10240], *save, *dump = NULL; + char cmd[348], *arguments, *p, *save, *dump = NULL; u32 reg, value, size = 0, address; breakpoint_t *bp; + size_t len = sizeof cmd; + struct dynstr reply; + + if (HasClient(client_socket)) + { + const enum read_socket_err err = ReadSocket(client_socket, cmd, &len); + + switch (err) + { + case READ_SOCKET_OK: + break; + + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + case READ_SOCKET_ERR_RECV: + /* Fall through. */ + case READ_SOCKET_SHUTDOWN: + /* Fall through. */ + default: + perror("recv() error"); + return; + } - if (!HasClient()) - return; - if (ReadSocket(cmd, 256) > 0) { arguments = NULL; if (strlen(cmd) <= 2) { code = 0; @@ -475,129 +522,126 @@ static void ProcessCommands() { dumping = 0; save = NULL; + dynstr_init(&reply); switch (code) { case 0x100: - sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments); + dynstr_append(&reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments); break; case 0x101: - sprintf(reply, "201 %s\r\n", PACKAGE_VERSION); + dynstr_append(&reply, "201 %s\r\n", PACKAGE_VERSION); break; case 0x102: - sprintf(reply, "202 1.0\r\n"); + dynstr_append(&reply, "202 1.0\r\n"); break; case 0x103: - sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); + dynstr_append(&reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); break; case 0x110: - sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc); + dynstr_append(&reply, "210 PC=%08X\r\n", psxRegs.pc); break; case 0x111: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 111 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s211 %02X(%2.2s)=%08X\r\n", reply, i, disRNameGPR[i], psxRegs.GPR.r[i]); + dynstr_append(&reply, "211 %02X(%2.2s)=%08X\r\n", reply, i, disRNameGPR[i], psxRegs.GPR.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "211 %02X(%2.2s)=%08X\r\n", code, disRNameGPR[code], psxRegs.GPR.r[code]); + dynstr_append(&reply, "211 %02X(%2.2s)=%08X\r\n", code, disRNameGPR[code], psxRegs.GPR.r[code]); } else { - sprintf(reply, "511 Invalid GPR register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid GPR register: %X\r\n", code); } } break; case 0x112: - sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + dynstr_append(&reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); break; case 0x113: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 113 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s213 %02X(%8.8s)=%08X\r\n", reply, i, disRNameCP0[i], psxRegs.CP0.r[i]); + dynstr_append(&reply, "213 %02X(%8.8s)=%08X\r\n", i, disRNameCP0[i], psxRegs.CP0.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "213 %02X(%8.8s)=%08X\r\n", code, disRNameCP0[code], psxRegs.CP0.r[code]); + dynstr_append(&reply, "213 %02X(%8.8s)=%08X\r\n", code, disRNameCP0[code], psxRegs.CP0.r[code]); } else { - sprintf(reply, "511 Invalid COP0 register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP0 register: %X\r\n", code); } } break; case 0x114: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 114 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s214 %02X(%6.6s)=%08X\r\n", reply, i, disRNameCP2C[i], psxRegs.CP2C.r[i]); + dynstr_append(&reply, "214 %02X(%6.6s)=%08X\r\n", i, disRNameCP2C[i], psxRegs.CP2C.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "214 %02X(%6.6s)=%08X\r\n", code, disRNameCP2C[code], psxRegs.CP2C.r[code]); + dynstr_append(&reply, "214 %02X(%6.6s)=%08X\r\n", code, disRNameCP2C[code], psxRegs.CP2C.r[code]); } else { - sprintf(reply, "511 Invalid COP2C register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP2C register: %X\r\n", code); } } break; case 0x115: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 111 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s215 %02X(%4.4s)=%08X\r\n", reply, i, disRNameCP2D[i], psxRegs.CP2D.r[i]); + dynstr_append(&reply, "215 %02X(%4.4s)=%08X\r\n", i, disRNameCP2D[i], psxRegs.CP2D.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "215 %02X(%4.4s)=%08X\r\n", code, disRNameCP2D[code], psxRegs.CP2D.r[code]); + dynstr_append(&reply, "215 %02X(%4.4s)=%08X\r\n", code, disRNameCP2D[code], psxRegs.CP2D.r[code]); } else { - sprintf(reply, "511 Invalid COP2D register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP2D register: %X\r\n", code); } } break; case 0x119: if (arguments) { if (sscanf(arguments, "%08X", &code) != 1) { - sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 119 command '%s'\r\n", cmd); break; } } if (!arguments) code = psxRegs.pc; - sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code)); + dynstr_append(&reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code)); break; case 0x121: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 121 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.GPR.r[reg] = value; - sprintf(reply, "221 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "221 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid GPR register: %02X\r\n", reg); } break; case 0x122: @@ -607,88 +651,88 @@ static void ProcessCommands() { reg = 32; } else { arguments[2] = 0; - sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments); + dynstr_append(&reply, "512 Invalid LO/HI register: '%s'\r\n", arguments); break; } if (sscanf(arguments + 3, "%08X", &value) != 1) { - sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 122 command '%s'\r\n", arguments); } else { psxRegs.GPR.r[reg] = value; - sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + dynstr_append(&reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); } break; case 0x123: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 123 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP0.r[reg] = value; - sprintf(reply, "223 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "223 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP0 register: %02X\r\n", reg); } break; case 0x124: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 124 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP2C.r[reg] = value; - sprintf(reply, "224 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "224 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP2C register: %02X\r\n", reg); } break; case 0x125: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 121 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP2D.r[reg] = value; - sprintf(reply, "225 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "225 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP2D register: %02X\r\n", reg); } break; case 0x130: if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { - sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 130 command '%s'\r\n", arguments); break; } if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { - sprintf(reply, "230 %08X@%08X\r\n", size, address); + dynstr_append(&reply, "230 %08X@%08X\r\n", size, address); dump = (char *) PSXM(address); dumping = 1; } else { - sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments); + dynstr_append(&reply, "513 Invalid address or range: '%s'\r\n", arguments); } break; case 0x140: if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { - sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 140 command '%s'\r\n", arguments); break; } if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { - sprintf(reply, "240 %08X@%08X\r\n", size, address); - RawReadSocket((char *)PSXM(address), size); + dynstr_append(&reply, "240 %08X@%08X\r\n", size, address); + RawReadSocket(client_socket, (char *)PSXM(address), size); } else { - sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments); + dynstr_append(&reply, "514 Invalid address or range: '%s'\r\n", arguments); } break; case 0x150: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 150 command '%s'\r\n", cmd); break; } } @@ -701,13 +745,13 @@ static void ProcessCommands() { } else { mapping_e = 0; } - sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped"); break; case 0x151: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 151 command '%s'\r\n", cmd); break; } } @@ -719,13 +763,13 @@ static void ProcessCommands() { } else { mapping_r8 = 0; } - sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x152: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 152 command '%s'\r\n", cmd); break; } } @@ -737,13 +781,13 @@ static void ProcessCommands() { } else { mapping_r16 = 0; } - sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x153: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 153 command '%s'\r\n", cmd); break; } } @@ -755,13 +799,13 @@ static void ProcessCommands() { } else { mapping_r32 = 0; } - sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x154: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 154 command '%s'\r\n", cmd); break; } } @@ -773,13 +817,13 @@ static void ProcessCommands() { } else { mapping_w8 = 0; } - sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x155: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 155 command '%s'\r\n", cmd); break; } } @@ -791,13 +835,13 @@ static void ProcessCommands() { } else { mapping_w16 = 0; } - sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x156: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 156 command '%s'\r\n", cmd); break; } } @@ -809,13 +853,13 @@ static void ProcessCommands() { } else { mapping_w32 = 0; } - sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x160: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 160 command '%s'\r\n", cmd); break; } } @@ -824,13 +868,13 @@ static void ProcessCommands() { } else { breakmp_e = 0; } - sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped"); break; case 0x161: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 161 command '%s'\r\n", cmd); break; } } @@ -839,13 +883,13 @@ static void ProcessCommands() { } else { breakmp_r8 = 0; } - sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x162: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 162 command '%s'\r\n", cmd); break; } } @@ -854,13 +898,13 @@ static void ProcessCommands() { } else { breakmp_r16 = 0; } - sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x163: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 163 command '%s'\r\n", cmd); break; } } @@ -869,13 +913,13 @@ static void ProcessCommands() { } else { breakmp_r32 = 0; } - sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x164: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 164 command '%s'\r\n", cmd); break; } } @@ -884,13 +928,13 @@ static void ProcessCommands() { } else { breakmp_w8 = 0; } - sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x165: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 165 command '%s'\r\n", cmd); break; } } @@ -899,13 +943,13 @@ static void ProcessCommands() { } else { breakmp_w16 = 0; } - sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x166: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 166 command '%s'\r\n", cmd); break; } } @@ -914,30 +958,37 @@ static void ProcessCommands() { } else { breakmp_w32 = 0; } - sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x170: - sfile = fopen("flow.idc", "wb"); - fprintf(sfile, "#include \r\n\r\n"); - fprintf(sfile, "static main(void) {\r\n"); - for (i = 0; i < 0x00200000; i++) { - if (IsMapMarked(i, MAP_EXEC_JAL)) { - fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i); + { + { + FILE *const sfile = fopen("flow.idc", "wb"); + fprintf(sfile, "#include \r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC_JAL)) { + fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i); + } } + fprintf(sfile, "}\r\n"); + fclose(sfile); } - fprintf(sfile, "}\r\n"); - fclose(sfile); - sfile = fopen("markcode.idc", "wb"); - fprintf(sfile, "#include \r\n\r\n"); - fprintf(sfile, "static main(void) {\r\n"); - for (i = 0; i < 0x00200000; i++) { - if (IsMapMarked(i, MAP_EXEC)) { - fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i); + + { + FILE *const sfile = fopen("markcode.idc", "wb"); + fprintf(sfile, "#include \r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC)) { + fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i); + } } + fprintf(sfile, "}\r\n"); + fclose(sfile); + dynstr_append(&reply, "270 flow.idc and markcode.idc dumped\r\n"); } - fprintf(sfile, "}\r\n"); - fclose(sfile); - sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n"); + } break; case 0x300: p = arguments; @@ -946,18 +997,17 @@ static void ProcessCommands() { } if (p == arguments) { if (first) { - reply[0] = 0; for (bp = first; bp; bp = next_breakpoint(bp)) { - sprintf(reply, "%s400 %X@%08X-%s\r\n", reply, bp->number, bp->address, breakpoint_type_names[bp->type]); + dynstr_append(&reply, "%s400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); } } else { - sprintf(reply, "530 No breakpoint\r\n"); + dynstr_append(&reply, "530 No breakpoint\r\n"); } } else { if ((bp = find_breakpoint(code))) { - sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); + dynstr_append(&reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); } else { - sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + dynstr_append(&reply, "530 Invalid breakpoint number: %X\r\n", code); } } break; @@ -968,107 +1018,107 @@ static void ProcessCommands() { } if (p == arguments) { while (first != NULL) delete_breakpoint(first); - sprintf(reply, "401 All breakpoints deleted.\r\n"); + dynstr_append(&reply, "401 All breakpoints deleted.\r\n"); } else { if ((bp = find_breakpoint(code))) { delete_breakpoint(bp); - sprintf(reply, "401 Breakpoint %X deleted.\r\n", code); + dynstr_append(&reply, "401 Breakpoint %X deleted.\r\n", code); } else { - sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + dynstr_append(&reply, "530 Invalid breakpoint number: %X\r\n", code); } } break; case 0x310: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 310 command '%s'\r\n", arguments); break; } -// if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { -// sprintf(reply, "531 Invalid address %08X\r\n", address); -// break; -// } + // if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + // dynstr_append(&reply, "531 Invalid address %08X\r\n", address); + // break; + // } code = add_breakpoint(BE, address); - sprintf(reply, "410 %X\r\n", code); + dynstr_append(&reply, "410 %X\r\n", code); break; case 0x320: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 320 command '%s'\r\n", arguments); break; } if ((address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR1, address); - sprintf(reply, "420 %X\r\n", code); + dynstr_append(&reply, "420 %X\r\n", code); break; case 0x321: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 321 command '%s'\r\n", arguments); break; } if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR2, address); - sprintf(reply, "421 %X\r\n", code); + dynstr_append(&reply, "421 %X\r\n", code); break; case 0x322: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 322 command '%s'\r\n", arguments); break; } if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR4, address); - sprintf(reply, "422 %X\r\n", code); + dynstr_append(&reply, "422 %X\r\n", code); break; case 0x330: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 330 command '%s'\r\n", arguments); break; } if ((address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW1, address); - sprintf(reply, "430 %X\r\n", code); + dynstr_append(&reply, "430 %X\r\n", code); break; case 0x331: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 331 command '%s'\r\n", arguments); break; } if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW2, address); - sprintf(reply, "431 %X\r\n", code); + dynstr_append(&reply, "431 %X\r\n", code); break; case 0x332: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 332 command '%s'\r\n", arguments); break; } if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW4, address); - sprintf(reply, "432 %X\r\n", code); + dynstr_append(&reply, "432 %X\r\n", code); break; case 0x390: paused = 1; - sprintf(reply, "490 Paused\r\n"); + dynstr_append(&reply, "490 Paused\r\n"); break; case 0x391: paused = 0; - sprintf(reply, "491 Resumed\r\n"); + dynstr_append(&reply, "491 Resumed\r\n"); break; case 0x395: p = arguments; @@ -1079,7 +1129,7 @@ static void ProcessCommands() { trace = 1; } paused = 0; - sprintf(reply, "495 Tracing\r\n"); + dynstr_append(&reply, "495 Tracing\r\n"); break; case 0x396: p = arguments; @@ -1089,19 +1139,19 @@ static void ProcessCommands() { if (p == arguments) { printpc = !printpc; } - sprintf(reply, "496 Printing %s\r\n", printpc ? "enabled" : "disabled"); + dynstr_append(&reply, "496 Printing %s\r\n", printpc ? "enabled" : "disabled"); break; case 0x398: paused = 0; trace = 0; reset = 2; - sprintf(reply, "498 Soft resetting\r\n"); + dynstr_append(&reply, "498 Soft resetting\r\n"); break; case 0x399: paused = 0; trace = 0; reset = 1; - sprintf(reply, "499 Resetting\r\n"); + dynstr_append(&reply, "499 Resetting\r\n"); break; case 0x3A0: // run to @@ -1112,10 +1162,10 @@ static void ProcessCommands() { paused = 0; } if (p == arguments) { - sprintf(reply, "500 Malformed 3A0 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 3A0 command '%s'\r\n", arguments); break; } - sprintf(reply, "4A0 run to addr %08X\r\n", run_to_addr); + dynstr_append(&reply, "4A0 run to addr %08X\r\n", run_to_addr); break; case 0x3A1: // step over (jal) @@ -1125,8 +1175,8 @@ static void ProcessCommands() { step_over = 1; step_over_addr = psxRegs.pc + 8; paused = 0; - - sprintf(reply, "4A1 step over addr %08X\r\n", psxRegs.pc); + + dynstr_append(&reply, "4A1 step over addr %08X\r\n", psxRegs.pc); } else { trace = 1; @@ -1135,13 +1185,14 @@ static void ProcessCommands() { } break; default: - sprintf(reply, "500 Unknown command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Unknown command '%s'\r\n", cmd); break; } - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); if (dumping) { - WriteSocket(dump, size); + WriteSocket(client_socket, dump, size); } if (save) { @@ -1156,11 +1207,11 @@ void DebugCheckBP(u32 address, enum breakpoint_types type) { if (!debugger_active || reset) return; - + for (bp = first; bp; bp = next_breakpoint(bp)) { if ((bp->type == type) && (bp->address == address)) { sprintf(reply, "030 %X@%08X\r\n", bp->number, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; return; } @@ -1168,49 +1219,49 @@ void DebugCheckBP(u32 address, enum breakpoint_types type) { if (breakmp_e && type == BE) { if (!IsMapMarked(address, MAP_EXEC)) { sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r8 && type == BR1) { if (!IsMapMarked(address, MAP_R8)) { sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r16 && type == BR2) { if (!IsMapMarked(address, MAP_R16)) { sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r32 && type == BR4) { if (!IsMapMarked(address, MAP_R32)) { sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w8 && type == BW1) { if (!IsMapMarked(address, MAP_W8)) { sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w16 && type == BW2) { if (!IsMapMarked(address, MAP_W16)) { sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w32 && type == BW4) { if (!IsMapMarked(address, MAP_W32)) { sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } diff --git a/libpcsxcore/ppf.c b/libpcsxcore/ppf.c index 3d2f9f30..a5d0eca8 100644 --- a/libpcsxcore/ppf.c +++ b/libpcsxcore/ppf.c @@ -23,6 +23,7 @@ #include "psxcommon.h" #include "ppf.h" #include "cdrom.h" +#include typedef struct tagPPF_DATA { s32 addr; @@ -184,7 +185,7 @@ void BuildPPFCache() { char method, undo = 0, blockcheck = 0; int dizlen = 0, dizyn; unsigned char ppfmem[512]; - char szPPF[MAXPATHLEN]; + struct dynstr szPPF; int count, seekpos, pos; u32 anz; // use 32-bit to avoid stupid overflows s32 ladr, off, anx; @@ -207,9 +208,10 @@ void BuildPPFCache() { buffer[10] = CdromId[8]; buffer[11] = '\0'; - sprintf(szPPF, "%s/%s", Config.PatchesDir, buffer); - - ppffile = fopen(szPPF, "rb"); + dynstr_init(&szPPF); + dynstr_append(&szPPF, "%s/%s", Config.PatchesDir, buffer); + ppffile = fopen(szPPF.str, "rb"); + dynstr_free(&szPPF); if (ppffile == NULL) return; memset(buffer, 0, 5); @@ -297,7 +299,7 @@ void BuildPPFCache() { } // now do the data reading - do { + do { fseek(ppffile, seekpos, SEEK_SET); fread(&pos, 4, 1, ppffile); pos = SWAP32(pos); @@ -305,7 +307,7 @@ void BuildPPFCache() { if (method == 2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here) anz = fgetc(ppffile); - fread(ppfmem, anz, 1, ppffile); + fread(ppfmem, anz, 1, ppffile); ladr = pos / CD_FRAMESIZE_RAW; off = pos % CD_FRAMESIZE_RAW; @@ -391,8 +393,8 @@ boolean CheckSBI(const u8 *time) { // both BCD format for (lcv = 0; lcv < sbicount; lcv++) { - if (time[0] == sbitime[lcv][0] && - time[1] == sbitime[lcv][1] && + if (time[0] == sbitime[lcv][0] && + time[1] == sbitime[lcv][1] && time[2] == sbitime[lcv][2]) return TRUE; } diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c index d5bafcf2..d50bd22d 100644 --- a/libpcsxcore/socket.c +++ b/libpcsxcore/socket.c @@ -32,9 +32,6 @@ #include #endif -static char tbuf[513]; -static int ptr = 0; - int StartServer(unsigned short port) { struct in_addr localhostaddr; struct sockaddr_in localsocketaddr; @@ -77,7 +74,7 @@ int StartServer(unsigned short port) { if (listen(ret, 1) != 0) return -1; - return 0; + return ret; } void StopServer(int s_socket) { @@ -91,68 +88,102 @@ void StopServer(int s_socket) { #endif } -void GetClient(int s_socket, int *client_socket) { - int new_socket; - char hello[256]; - - new_socket = accept(s_socket, 0, 0); +int GetClient(int s_socket) { + int new_socket = accept(s_socket, NULL, NULL); #ifdef _WIN32 if (new_socket == INVALID_SOCKET) - return; + return -1; #else if (new_socket == -1) - return; + return -1; #endif - if (*client_socket) - CloseClient(*client_socket); - *client_socket = new_socket; #ifndef _WIN32 { int flags; - flags = fcntl(*client_socket, F_GETFL, 0); - fcntl(*client_socket, F_SETFL, flags | O_NONBLOCK); + flags = fcntl(new_socket, F_GETFL, 0); + fcntl(new_socket, F_SETFL, flags | O_NONBLOCK); + return new_socket; } #endif - - /* TODO: Move to debug.c */ - sprintf(hello, "000 PCSXR Version %s - Debug console\r\n", PACKAGE_VERSION); - WriteSocket(client_socket, hello, strlen(hello)); - ptr = 0; } -void CloseClient(int *client_socket) { - if (*client_socket) { +void CloseClient(int client_socket) { + if (client_socket) { #ifdef _WIN32 shutdown(client_socket, SD_BOTH); closesocket(client_socket); #else - shutdown(*client_socket, SHUT_RDWR); - close(*client_socket); + shutdown(client_socket, SHUT_RDWR); + close(client_socket); #endif - *client_socket = 0; } } int HasClient(int client_socket) { - return client_socket ? 1 : 0; + return client_socket > 0; } -int ReadSocket(int *client_socket, char * buffer, int len) { - int r; - char * endl; +#ifdef _WIN32 - if (!*client_socket) - return -1; +static enum read_socket_err ReadSocketOS(SOCKET client_socket, char *buf, size_t *const len) +{ + const int res = recv(client_socket, buf, len, 0); - r = recv(*client_socket, tbuf + ptr, 512 - ptr, 0); + switch (res) + { + case SOCKET_ERROR: + return READ_SOCKET_ERR_RECV; - if (r == 0) { - *client_socket = 0; - if (!ptr) - return 0; + case 0: + return READ_SOCKET_SHUTDOWN; + + default: + *len = res; + + break; } + + return READ_SOCKET_OK; +} + +#elif defined(_POSIX_VERSION) + +static enum read_socket_err ReadSocketOS(int client_socket, char *buf, size_t *const len) +{ + const ssize_t res = recv(client_socket, buf, *len, 0); + + switch (res) + { + case -1: + fprintf(stderr, "READ_SOCKET_ERR_RECV, recv(%d, %p, %zu, %d)\n", client_socket, buf, *len, 0); + return READ_SOCKET_ERR_RECV; + + case 0: + fprintf(stderr, "READ_SOCKET_SHUTDOWN\n"); + return READ_SOCKET_SHUTDOWN; + + default: + printf("received %zu/%zu bytes\n", res, *len); + *len = res; + break; + } + + return READ_SOCKET_OK; +} + +#endif /* _WIN32 */ + +enum read_socket_err ReadSocket(int client_socket, char *buf, size_t *const len) { + char * endl; + + if (!client_socket || !buf || !len || !*len) + return READ_SOCKET_ERR_INVALID_ARG; + + return ReadSocketOS(client_socket, buf, len); + +#if 0 #ifdef _WIN32 if (r == SOCKET_ERROR) #else @@ -183,15 +214,15 @@ int ReadSocket(int *client_socket, char * buffer, int len) { } buffer[r] = 0; - - return r; +#endif } -int RawReadSocket(int *client_socket, char * buffer, int len) { +int RawReadSocket(int client_socket, char *buffer, size_t len) { +#if 0 int r = 0; int mlen = len < ptr ? len : ptr; - if (!*client_socket) + if (!client_socket) return -1; if (ptr) { @@ -201,10 +232,9 @@ int RawReadSocket(int *client_socket, char * buffer, int len) { } if (len - mlen) - r = recv(*client_socket, buffer + mlen, len - mlen, 0); + r = recv(client_socket, buffer + mlen, len - mlen, 0); if (r == 0) { - *client_socket = 0; if (!ptr) return 0; } @@ -222,13 +252,14 @@ int RawReadSocket(int *client_socket, char * buffer, int len) { r += mlen; return r; +#endif } -void WriteSocket(int *client_socket, char * buffer, int len) { - if (!*client_socket) +void WriteSocket(int client_socket, const char *buffer, size_t len) { + if (!client_socket) return; - send(*client_socket, buffer, len, 0); + send(client_socket, buffer, len, 0); } void SetsBlock(int s_socket) { diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h index ef26de02..10d3c2fe 100644 --- a/libpcsxcore/socket.h +++ b/libpcsxcore/socket.h @@ -22,17 +22,27 @@ extern "C" { #endif +#include + +enum read_socket_err +{ + READ_SOCKET_OK, + READ_SOCKET_ERR_INVALID_ARG, + READ_SOCKET_ERR_RECV, + READ_SOCKET_SHUTDOWN +}; + int StartServer(unsigned short port); void StopServer(int s_socket); -void GetClient(int s_socket, int *client_socket); -void CloseClient(int *client_socket); +int GetClient(int s_socket); +void CloseClient(int client_socket); int HasClient(int client_socket); -int ReadSocket(int *client_socket, char * buffer, int len); -int RawReadSocket(int *client_socket, char * buffer, int len); -void WriteSocket(int *client_socket, char * buffer, int len); +enum read_socket_err ReadSocket(int client_socket, char *buffer, size_t *len); +int RawReadSocket(int client_socket, char *buffer, size_t len); +void WriteSocket(int client_socket, const char *buffer, size_t len); void SetsBlock(int s_socket); void SetsNonblock(int s_socket); -- cgit v1.2.3 From 850010a96b6cbc3eae03edd891e50325e017b678 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sat, 23 May 2020 18:06:48 +0200 Subject: Replaced in-house gdb stub by MIT-licensed implementation Imported from a fork of https://github.com/mborgerson/gdbstub --- .gitmodules | 3 + CMakeLists.txt | 1 + gdbstub/CMakeLists.txt | 5 ++ gdbstub/gdbstub | 1 + gdbstub/gdbstub_sys.c | 132 +++++++++++++++++++++++++++++++++++++++++++ gdbstub/gdbstub_sys.h | 58 +++++++++++++++++++ gui/ConfDlg.c | 6 +- gui/LnxMain.c | 10 ++-- libpcsxcore/CMakeLists.txt | 3 +- libpcsxcore/debug.c | 2 +- libpcsxcore/gdb_server.c | 128 ----------------------------------------- libpcsxcore/gdb_server.h | 10 ---- libpcsxcore/psxcommon.h | 1 - libpcsxcore/psxcounters.c | 3 +- libpcsxcore/psxinterpreter.c | 3 +- libpcsxcore/socket.c | 4 +- libpcsxcore/socket.h | 2 +- win32/gui/WndMain.c | 1 - 18 files changed, 215 insertions(+), 158 deletions(-) create mode 100644 gdbstub/CMakeLists.txt create mode 160000 gdbstub/gdbstub create mode 100644 gdbstub/gdbstub_sys.c create mode 100644 gdbstub/gdbstub_sys.h delete mode 100644 libpcsxcore/gdb_server.c delete mode 100644 libpcsxcore/gdb_server.h (limited to 'libpcsxcore/socket.h') diff --git a/.gitmodules b/.gitmodules index a178facc..75dee188 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "dynstr/dynstr"] path = dynstr/dynstr url = https://github.com/XaviDCR92/dynstr +[submodule "gdbstub/gdbstub"] + path = gdbstub/gdbstub + url = https://github.com/XaviDCR92/gdbstub diff --git a/CMakeLists.txt b/CMakeLists.txt index 4855ae14..f4b4c4a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,3 +52,4 @@ add_subdirectory(gui) add_subdirectory(plugins) add_subdirectory(doc) add_subdirectory(dynstr) +add_subdirectory(gdbstub) diff --git a/gdbstub/CMakeLists.txt b/gdbstub/CMakeLists.txt new file mode 100644 index 00000000..a3f0624a --- /dev/null +++ b/gdbstub/CMakeLists.txt @@ -0,0 +1,5 @@ +message(STATUS "* Configuring gdbstub") + +set(SRCS gdbstub/gdbstub.c gdbstub_sys.c) +include_directories(gdbstub .) +add_library(gdbstub STATIC ${SRCS}) diff --git a/gdbstub/gdbstub b/gdbstub/gdbstub new file mode 160000 index 00000000..b00d0f81 --- /dev/null +++ b/gdbstub/gdbstub @@ -0,0 +1 @@ +Subproject commit b00d0f815b3996a13ce87a4d9d6d7038353e77e6 diff --git a/gdbstub/gdbstub_sys.c b/gdbstub/gdbstub_sys.c new file mode 100644 index 00000000..bfba9bf7 --- /dev/null +++ b/gdbstub/gdbstub_sys.c @@ -0,0 +1,132 @@ +#include "gdbstub_sys.h" +#include "gdbstub.h" +#include "libpcsxcore/socket.h" +#include "libpcsxcore/r3000a.h" +#include + +static int server_socket, client_socket; + +static void update_regs(struct dbg_state *const dbg_state) +{ + dbg_state->registers[DBG_CPU_MIPS_I_REG_ZERO] = 0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_AT] = psxRegs.GPR.n.at; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_V0] = psxRegs.GPR.n.v0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_V1] = psxRegs.GPR.n.v1; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_A0] = psxRegs.GPR.n.a0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A1] = psxRegs.GPR.n.a1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A2] = psxRegs.GPR.n.a2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A3] = psxRegs.GPR.n.a3; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_T0] = psxRegs.GPR.n.t0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T1] = psxRegs.GPR.n.t1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T2] = psxRegs.GPR.n.t2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T3] = psxRegs.GPR.n.t3; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T4] = psxRegs.GPR.n.t4; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T5] = psxRegs.GPR.n.t5; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T6] = psxRegs.GPR.n.t6; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T7] = psxRegs.GPR.n.t7; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_S0] = psxRegs.GPR.n.s0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S1] = psxRegs.GPR.n.s1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S2] = psxRegs.GPR.n.s2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S3] = psxRegs.GPR.n.s3; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S4] = psxRegs.GPR.n.s4; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S5] = psxRegs.GPR.n.s5; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S6] = psxRegs.GPR.n.s6; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S7] = psxRegs.GPR.n.s7; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_T8] = psxRegs.GPR.n.t8; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T9] = psxRegs.GPR.n.t9; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_K0] = psxRegs.GPR.n.k0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_K1] = psxRegs.GPR.n.k1; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_GP] = psxRegs.GPR.n.gp; + dbg_state->registers[DBG_CPU_MIPS_I_REG_SP] = psxRegs.GPR.n.sp; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S8] = psxRegs.GPR.n.s8; + dbg_state->registers[DBG_CPU_MIPS_I_REG_RA] = psxRegs.GPR.n.ra; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_SR] = psxRegs.CP0.n.Status; + dbg_state->registers[DBG_CPU_MIPS_I_REG_LO] = psxRegs.GPR.r[32]; + dbg_state->registers[DBG_CPU_MIPS_I_REG_HI] = psxRegs.GPR.r[33]; + dbg_state->registers[DBG_CPU_MIPS_I_REG_BAD] = psxRegs.CP0.n.BadVAddr; + dbg_state->registers[DBG_CPU_MIPS_I_REG_CAUSE] = psxRegs.CP0.n.Cause; + dbg_state->registers[DBG_CPU_MIPS_I_REG_PC] = psxRegs.pc; +} + +void dbg_sys_process(void) +{ + static struct dbg_state dbg_state; + update_regs(&dbg_state); + dbg_main(&dbg_state); +} + +int dbg_sys_getc(void) +{ + while (1) { + char packet; + size_t len = sizeof packet; + const enum read_socket_err err = ReadSocket(client_socket, &packet, &len); + + switch (err) { + case READ_SOCKET_OK: + return packet; + + case READ_SOCKET_SHUTDOWN: + client_socket = 0; + return EOF; + + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + case READ_SOCKET_ERR_RECV: + /* Fall through. */ + + default: + break; + } + } +} + +int dbg_sys_putchar(int ch) +{ + WriteSocket(client_socket, (const char *)&ch, sizeof (char)); +} + +int dbg_sys_mem_readb(address addr, char *val) +{ + *val = psxMemRead8(addr); + return 0; +} + +int dbg_sys_mem_writeb(address addr, char val) +{ + psxMemWrite8(addr, val); + return 0; +} + +int dbg_sys_continue(void) +{ + return 0; +} + +int dbg_sys_step(void) +{ + return 0; +} + +void dbg_start(void) +{ + const unsigned short port = 3333; + + if (server_socket > 0) + StopServer(server_socket); + + server_socket = StartServer(port); + + if (server_socket > 0) + printf("GDB server started on port %hu.\n", port); + else + fprintf(stderr, "Could not start GDB server\n"); +} diff --git a/gdbstub/gdbstub_sys.h b/gdbstub/gdbstub_sys.h new file mode 100644 index 00000000..84bae1fa --- /dev/null +++ b/gdbstub/gdbstub_sys.h @@ -0,0 +1,58 @@ +#ifndef GDBSTUB_SYS_H +#define GDBSTUB_SYS_H + +typedef unsigned int address; + +enum DBG_REGISTER { + DBG_CPU_MIPS_I_REG_ZERO, + DBG_CPU_MIPS_I_REG_AT, + DBG_CPU_MIPS_I_REG_V0, + DBG_CPU_MIPS_I_REG_V1, + DBG_CPU_MIPS_I_REG_A0, + DBG_CPU_MIPS_I_REG_A1, + DBG_CPU_MIPS_I_REG_A2, + DBG_CPU_MIPS_I_REG_A3, + DBG_CPU_MIPS_I_REG_T0, + DBG_CPU_MIPS_I_REG_T1, + DBG_CPU_MIPS_I_REG_T2, + DBG_CPU_MIPS_I_REG_T3, + DBG_CPU_MIPS_I_REG_T4, + DBG_CPU_MIPS_I_REG_T5, + DBG_CPU_MIPS_I_REG_T6, + DBG_CPU_MIPS_I_REG_T7, + DBG_CPU_MIPS_I_REG_S0, + DBG_CPU_MIPS_I_REG_S1, + DBG_CPU_MIPS_I_REG_S2, + DBG_CPU_MIPS_I_REG_S3, + DBG_CPU_MIPS_I_REG_S4, + DBG_CPU_MIPS_I_REG_S5, + DBG_CPU_MIPS_I_REG_S6, + DBG_CPU_MIPS_I_REG_S7, + DBG_CPU_MIPS_I_REG_T8, + DBG_CPU_MIPS_I_REG_T9, + DBG_CPU_MIPS_I_REG_K0, + DBG_CPU_MIPS_I_REG_K1, + DBG_CPU_MIPS_I_REG_GP, + DBG_CPU_MIPS_I_REG_SP, + DBG_CPU_MIPS_I_REG_S8, + DBG_CPU_MIPS_I_REG_RA, + DBG_CPU_MIPS_I_REG_SR, + DBG_CPU_MIPS_I_REG_LO, + DBG_CPU_MIPS_I_REG_HI, + DBG_CPU_MIPS_I_REG_BAD, + DBG_CPU_MIPS_I_REG_CAUSE, + DBG_CPU_MIPS_I_REG_PC, + DBG_CPU_NUM_REGISTERS +}; + +typedef unsigned int reg; + +struct dbg_state { + int signum; + reg registers[DBG_CPU_NUM_REGISTERS]; +}; + +void dbg_start(void); +void dbg_sys_process(void); + +#endif /* GDBSTUB_SYS_H */ diff --git a/gui/ConfDlg.c b/gui/ConfDlg.c index 2e16be08..f41dd9ed 100644 --- a/gui/ConfDlg.c +++ b/gui/ConfDlg.c @@ -32,6 +32,7 @@ #include "ConfDlg.h" #include "../libpcsxcore/plugins.h" +#include "../gdbstub/gdbstub_sys.h" static void OnBiosPath_Changed(GtkWidget *wdg, gpointer data); static void OnConf_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data); @@ -929,9 +930,8 @@ void OnCpu_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) { else StopDebugger(); } - if (Config.GdbServer) { - GdbStartServer(); - } + if (Config.GdbServer) + dbg_start(); t = Config.Cpu; Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_Cpu"))); diff --git a/gui/LnxMain.c b/gui/LnxMain.c index 19187836..12aeb5fc 100644 --- a/gui/LnxMain.c +++ b/gui/LnxMain.c @@ -32,6 +32,7 @@ #include #include #include "../libpcsxcore/sio.h" +#include "../gdbstub/gdbstub_sys.h" #include "Linux.h" #include "ConfDlg.h" @@ -490,13 +491,10 @@ int SysInit() { LoadMcds(Config.Mcd1, Config.Mcd2); /* TODO Do we need to have this here, or in the calling main() function?? */ - if (Config.Debug) { + if (Config.Debug) StartDebugger(); - } - - if (Config.GdbServer) { - GdbStartServer(); - } + else if (Config.GdbServer) + dbg_start(); return 0; } diff --git a/libpcsxcore/CMakeLists.txt b/libpcsxcore/CMakeLists.txt index 04633ce1..0be1e4ac 100644 --- a/libpcsxcore/CMakeLists.txt +++ b/libpcsxcore/CMakeLists.txt @@ -98,7 +98,6 @@ set(SRCS psxbios.c pgxp_gte.c pgxp_mem.c pgxp_value.c - gdb_server.c ) set(LIBS "-lm") @@ -117,4 +116,4 @@ endif() set(SRCS ${SRCS} ${DYNAREC_SRC}) add_library(pcsxcore STATIC ${SRCS}) -target_link_libraries(pcsxcore dynstr ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) +target_link_libraries(pcsxcore dynstr gdbstub ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c index 972343d4..463df73b 100644 --- a/libpcsxcore/debug.c +++ b/libpcsxcore/debug.c @@ -474,7 +474,7 @@ void ProcessDebug() { MarkMap(_Rd_, MAP_EXEC_JAL); } } - while (paused || GdbServerRunning()) { + while (paused) { if (client_socket < 1) { diff --git a/libpcsxcore/gdb_server.c b/libpcsxcore/gdb_server.c deleted file mode 100644 index 7f7ea2ca..00000000 --- a/libpcsxcore/gdb_server.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "socket.h" -#include "psxcommon.h" -#include "misc.h" -#include "system.h" -#include "dynstr.h" -#include -#include -#include - -static int server_socket, client_socket; -static int debugger_active, resetting, reset, paused, ack_expected; - -enum { PACKET_SIZE = 256 }; - -void GdbStartServer(void) -{ - enum { PORT = 3333 }; - - if (server_socket > 0) { - GdbStopServer(); - } - - server_socket = StartServer(PORT); - - if (server_socket > 0) { - printf("GDB server started on port %hu\n", PORT); - debugger_active = 1; - } - else - { - fprintf(stderr, "Could not start GDB server\n"); - } -} - -int GdbServerRunning(void) -{ - return server_socket > 0; -} - -void GdbStopServer(void) -{ -} - -static void ack(struct dynstr *const reply) -{ - dynstr_append(reply, "OK"); -} - -static void nack(struct dynstr *const reply, const int err) -{ - dynstr_append(reply, "E %02X", err); -} - -static void HandlePacket(char *const packet, const size_t len) -{ - struct dynstr reply; - const char *c = packet; - - dynstr_init(&reply); - - if (strstr(packet, "qSupported")) { - dynstr_append(&reply, "PacketSize=%x;swbreak+;hwbreak+", PACKET_SIZE - 1); - } - else { - fprintf(stderr, "Unexpected packet \"%s\"\n", packet); - return; - } - - printf("gdb <- \"%s\"\n", reply.str); - WriteSocket(client_socket, reply.str, reply.len); - dynstr_free(&reply); -} - -static void ProcessCommands(void) -{ - if (HasClient(client_socket)) { - char packet[PACKET_SIZE]; - size_t len = sizeof packet; - const enum read_socket_err err = ReadSocket(client_socket, packet, &len); - - switch (err) - { - case READ_SOCKET_OK: - if (len && len < sizeof packet) { - /* gdb apparently does not send null-terminated strings. */ - packet[len] = '\0'; - printf("gdb -> \"%s\"\n", packet); - HandlePacket(packet, len); - } - break; - - case READ_SOCKET_ERR_INVALID_ARG: - /* Fall through. */ - case READ_SOCKET_ERR_RECV: - /* Fall through. */ - case READ_SOCKET_SHUTDOWN: - /* Fall through. */ - default: - return; - } - } -} - -void GdbServerProcessDebug(void) -{ - ProcessCommands(); -} - -void GdbServerVSync(void) -{ - if (!debugger_active || resetting) - return; - - if (reset) { - resetting = 1; - SysReset(); - if (reset == 2) - LoadCdrom(); - reset = resetting = 0; - return; - } - - if (client_socket < 1) { - client_socket = GetClient(server_socket); - } - - ProcessCommands(); -} diff --git a/libpcsxcore/gdb_server.h b/libpcsxcore/gdb_server.h deleted file mode 100644 index d0e925a6..00000000 --- a/libpcsxcore/gdb_server.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef GDB_SERVER_H -#define GDB_SERVER_H - -void GdbStartServer(void); -void GdbStopServer(void); -void GdbServerProcessDebug(void); -void GdbServerVSync(void); -int GdbServerRunning(void); - -#endif /* GDB_SERVER_H */ diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h index babdff96..c6deaa9f 100644 --- a/libpcsxcore/psxcommon.h +++ b/libpcsxcore/psxcommon.h @@ -70,7 +70,6 @@ typedef uint8_t boolean; // Local includes #include "system.h" #include "debug.h" -#include "gdb_server.h" #if defined (__linux__) || defined (__MACOSX__) #define strnicmp strncasecmp diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index 46f9947e..9203d62d 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -323,8 +323,7 @@ void psxRcntUpdate() } } - DebugVSync(); - GdbServerVSync(); + if (Config.Debug) DebugVSync(); } /******************************************************************************/ diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 685c9abf..a2bc0e1d 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -28,6 +28,7 @@ #include "pgxp_debug.h" #include "pgxp_cpu.h" #include "pgxp_gte.h" +#include "../gdbstub/gdbstub_sys.h" static int branch = 0; static int branch2 = 0; @@ -1204,7 +1205,7 @@ static inline void execI() { debugI(); - if (Config.GdbServer) GdbServerProcessDebug(); + if (Config.GdbServer) dbg_sys_process(); else if (Config.Debug) ProcessDebug(); psxRegs.pc += 4; diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c index 1faffd3d..51aefdf7 100644 --- a/libpcsxcore/socket.c +++ b/libpcsxcore/socket.c @@ -252,8 +252,8 @@ int RawReadSocket(int client_socket, char *buffer, size_t len) { #endif } -void WriteSocket(int client_socket, const char *buffer, size_t len) { - if (!client_socket) +void WriteSocket(int client_socket, const void *buffer, size_t len) { + if (client_socket <= 0) return; if (send(client_socket, buffer, len, 0) == -1) { diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h index 10d3c2fe..531a6485 100644 --- a/libpcsxcore/socket.h +++ b/libpcsxcore/socket.h @@ -42,7 +42,7 @@ int HasClient(int client_socket); enum read_socket_err ReadSocket(int client_socket, char *buffer, size_t *len); int RawReadSocket(int client_socket, char *buffer, size_t len); -void WriteSocket(int client_socket, const char *buffer, size_t len); +void WriteSocket(int client_socket, const void *buffer, size_t len); void SetsBlock(int s_socket); void SetsNonblock(int s_socket); diff --git a/win32/gui/WndMain.c b/win32/gui/WndMain.c index 5d16debc..374b1877 100644 --- a/win32/gui/WndMain.c +++ b/win32/gui/WndMain.c @@ -34,7 +34,6 @@ #include "sio.h" #include "misc.h" #include "cheat.h" -#include "gdb_server.h" #ifdef __MINGW32__ #ifndef LVM_GETSELECTIONMARK -- cgit v1.2.3 From cb2d7f800a9fc276b96fd0927fa6d8ec9f5a31c8 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Fri, 29 May 2020 00:05:08 +0200 Subject: Implemented port-specific wrappers and logic for gdb stub --- gdbstub/gdbstub | 2 +- gdbstub/gdbstub_sys.c | 274 ++++++++++++++++++++++++++++++++++++++++--- gdbstub/gdbstub_sys.h | 30 ++++- gui/LnxMain.c | 7 ++ libpcsxcore/debug.c | 4 +- libpcsxcore/psxinterpreter.c | 64 +++++++++- libpcsxcore/socket.c | 3 +- libpcsxcore/socket.h | 2 +- win32/gui/WndMain.c | 7 +- 9 files changed, 363 insertions(+), 30 deletions(-) (limited to 'libpcsxcore/socket.h') diff --git a/gdbstub/gdbstub b/gdbstub/gdbstub index b00d0f81..8ce6abf8 160000 --- a/gdbstub/gdbstub +++ b/gdbstub/gdbstub @@ -1 +1 @@ -Subproject commit b00d0f815b3996a13ce87a4d9d6d7038353e77e6 +Subproject commit 8ce6abf8d32291ad66a3724123a9a583b9a3bb4b diff --git a/gdbstub/gdbstub_sys.c b/gdbstub/gdbstub_sys.c index bfba9bf7..7773de67 100644 --- a/gdbstub/gdbstub_sys.c +++ b/gdbstub/gdbstub_sys.c @@ -3,8 +3,24 @@ #include "libpcsxcore/socket.h" #include "libpcsxcore/r3000a.h" #include +#include +#include + +#ifdef _POSIX_VERSION +#include +#include +#include +#include +#include + +static pthread_t thread; +static mqd_t in_queue, out_queue; +#endif static int server_socket, client_socket; +static enum { + PAUSED, +} state; static void update_regs(struct dbg_state *const dbg_state) { @@ -56,13 +72,6 @@ static void update_regs(struct dbg_state *const dbg_state) dbg_state->registers[DBG_CPU_MIPS_I_REG_PC] = psxRegs.pc; } -void dbg_sys_process(void) -{ - static struct dbg_state dbg_state; - update_regs(&dbg_state); - dbg_main(&dbg_state); -} - int dbg_sys_getc(void) { while (1) { @@ -74,15 +83,22 @@ int dbg_sys_getc(void) case READ_SOCKET_OK: return packet; - case READ_SOCKET_SHUTDOWN: + case READ_SOCKET_SHUTDOWN: { + struct msg msg; + + printf("gdb shutdown\n"); client_socket = 0; + msg.type = MSG_TYPE_SHUTDOWN; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) + perror("dbg_sys_getc() mq_send()"); return EOF; + } case READ_SOCKET_ERR_INVALID_ARG: /* Fall through. */ case READ_SOCKET_ERR_RECV: /* Fall through. */ - default: break; } @@ -106,27 +122,247 @@ int dbg_sys_mem_writeb(address addr, char val) return 0; } +#ifdef _POSIX_VERSION +static int wait_hit_or_break(struct msg *msg) +{ + do { + int ret = mq_receive(in_queue, (char *)msg, sizeof *msg, 0); + + if (ret < 0 && errno == EAGAIN) { + /* Breakpoint has not been hit yet, look for incoming messages from gdb. */ + char packet; + size_t len = sizeof packet; + const enum read_socket_err err = ReadSocket(client_socket, &packet, &len); + + switch (err) { + case READ_SOCKET_OK: + if (len && packet == 0x03) + return 0; + + break; + + case READ_SOCKET_SHUTDOWN: + printf("gdb shutdown\n"); + client_socket = 0; + msg->type = MSG_TYPE_SHUTDOWN; + + if (mq_send(out_queue, (const char *)msg, sizeof *msg, 0)) + perror("wait_hit_or_break() mq_send()"); + + return EOF; + + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + case READ_SOCKET_ERR_RECV: + /* Fall through. */ + default: + break; + } + } + else if (msg->type != MSG_TYPE_HIT) { + fprintf(stderr, "unexpected msg.type %d\n", msg->type); + return 1; + } + else + return 0; + } while (1); + + return 1; +} +#endif + +#ifdef _POSIX_VERSION int dbg_sys_continue(void) { - return 0; + struct msg msg; + + msg.type = MSG_TYPE_CONTINUE; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_continue(): mq_send()"); + return 1; + } + + return wait_hit_or_break(&msg); } +#endif +#ifdef _POSIX_VERSION int dbg_sys_step(void) { + struct msg msg; + + msg.type = MSG_TYPE_STEP; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_step(): mq_send()"); + } + + return wait_hit_or_break(&msg); +} +#endif + +#ifdef _POSIX_VERSION +static int wait_ack(struct msg *msg) +{ + int ret; + + do { + ret = mq_receive(in_queue, (char *)msg, sizeof *msg, 0); + } while (ret < 0 && errno == EAGAIN); + + if (msg->type != MSG_TYPE_ACK) { + fprintf(stderr, "unexpected msg.type %d\n", msg->type); + return 1; + } + return 0; } +#endif -void dbg_start(void) +#ifdef _POSIX_VERSION +int dbg_sys_breakpoint(address addr) +{ + struct msg msg; + + msg.type = MSG_TYPE_BREAKPOINT; + msg.data.breakpoint.addr = addr; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_breakpoint(): mq_send()"); + } + + return wait_ack(&msg); +} +#endif + +#ifdef _POSIX_VERSION +int dbg_sys_del_breakpoint(address addr) { - const unsigned short port = 3333; + struct msg msg; - if (server_socket > 0) - StopServer(server_socket); + msg.type = MSG_TYPE_REMOVE_BREAKPOINT; - server_socket = StartServer(port); + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_breakpoint(): mq_send()"); + } + + return wait_ack(&msg); +} +#endif - if (server_socket > 0) - printf("GDB server started on port %hu.\n", port); - else - fprintf(stderr, "Could not start GDB server\n"); +#ifdef _POSIX_VERSION +static int queue_create(void) +{ + struct mq_attr attr; + + attr.mq_msgsize = sizeof (struct msg); + attr.mq_flags = 0; + attr.mq_maxmsg = 4; + + mq_unlink("/pcsxrin"); + in_queue = mq_open("/pcsxrin", O_CREAT | O_RDWR | O_EXCL | O_NONBLOCK, 0600, &attr); + + mq_unlink("/pcsxrout"); + out_queue = mq_open("/pcsxrout", O_CREAT | O_RDWR | O_EXCL, 0600, &attr); + + if ((out_queue < 0) || (in_queue < 0)) { + perror("mq_open()"); + return 1; + } + + return 0; +} +#endif + +static int exit_loop; + +static void *loop(void *const args) +{ + struct dbg_state dbg_state = {0}; + + SetsBlock(server_socket); + + if ((client_socket = GetClient(server_socket, 1)) < 0) { + fprintf(stderr, "GetClient() failed\n"); + return NULL; + } + + SetsNonblock(client_socket); + + printf("Accepted gdb connection\n"); + + while (!exit_loop) { + update_regs(&dbg_state); + dbg_main(&dbg_state); + } + + return NULL; +} + +#ifdef _POSIX_VERSION +static void start_thread(void) +{ + if (pthread_create(&thread, NULL, loop, NULL)) + perror("could not start gdb server thread"); +} +#endif + +#ifdef _POSIX_VERSION +static void stop_thread(void) +{ + if (pthread_join(thread, NULL)) + perror("pthread_join()"); + + mq_unlink("/pcsxrin"); + mq_unlink("/pcsxrout"); +} +#endif + +#ifdef _POSIX_VERSION +void gdbstub_sys_recv(struct msg *msg) +{ + const ssize_t sz = mq_receive(out_queue, (char *)msg, sizeof *msg, 0); + + if (sz < 0) + perror("mq_receive"); +} +#endif + +#ifdef _POSIX_VERSION +void gdbstub_sys_send(const struct msg *msg) +{ + if (mq_send(in_queue, (const char *)msg, sizeof *msg, 0)) { + perror("dbg_sys_send(): mq_send()"); + } +} +#endif + +void dbg_stop(void) +{ + exit_loop = 1; + stop_thread(); +} + +void dbg_start(void) +{ + if (server_socket > 0) { + fprintf(stderr, "gdb server already started\n"); + return; + } + else { + const unsigned short port = 3333; + + server_socket = StartServer(port); + + if (server_socket > 0) { + printf("GDB server started on port %hu.\n", port); + if (queue_create()) + fprintf(stderr, "could not create gdb stub internal queues\n"); + else + start_thread(); + } + else + fprintf(stderr, "could not start GDB server\n"); + } } diff --git a/gdbstub/gdbstub_sys.h b/gdbstub/gdbstub_sys.h index 84bae1fa..f44dfcc9 100644 --- a/gdbstub/gdbstub_sys.h +++ b/gdbstub/gdbstub_sys.h @@ -42,7 +42,11 @@ enum DBG_REGISTER { DBG_CPU_MIPS_I_REG_BAD, DBG_CPU_MIPS_I_REG_CAUSE, DBG_CPU_MIPS_I_REG_PC, - DBG_CPU_NUM_REGISTERS + + /* GDB requests 73, where 38 are the ones above and the rest + * are the floating-point registers. This way, unused registers + * are left to zero. */ + DBG_CPU_NUM_REGISTERS = 73 }; typedef unsigned int reg; @@ -52,7 +56,29 @@ struct dbg_state { reg registers[DBG_CPU_NUM_REGISTERS]; }; +struct msg { + enum { + MSG_TYPE_CONTINUE, + MSG_TYPE_BREAKPOINT, + MSG_TYPE_STEP, + MSG_TYPE_ACK, + MSG_TYPE_REMOVE_BREAKPOINT, + MSG_TYPE_SHUTDOWN, + + /* Response frames. */ + MSG_TYPE_HIT + } type; + + union { + struct { + address addr; + } breakpoint; + } data; +}; + void dbg_start(void); -void dbg_sys_process(void); +void dbg_stop(void); +void gdbstub_sys_send(const struct msg *msg); +void gdbstub_sys_recv(struct msg *msg); #endif /* GDBSTUB_SYS_H */ diff --git a/gui/LnxMain.c b/gui/LnxMain.c index 12aeb5fc..2e087ee3 100644 --- a/gui/LnxMain.c +++ b/gui/LnxMain.c @@ -321,6 +321,11 @@ int main(int argc, char *argv[]) { SetIsoFile(isofilename); runcd = RUN_CD; } + else if (!strcmp(argv[i], "-gdb")) { + /* Force configuration. */ + Config.Cpu = CPU_INTERPRETER; + Config.GdbServer = 1; + } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { @@ -461,6 +466,8 @@ int main(int argc, char *argv[]) { psxCpu->Execute(); } + if (Config.GdbServer) dbg_stop(); + return 0; } diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c index 463df73b..ecc9edc7 100644 --- a/libpcsxcore/debug.c +++ b/libpcsxcore/debug.c @@ -397,7 +397,7 @@ void DebugVSync() { if (client_socket < 1) { - client_socket = GetClient(server_socket); + client_socket = GetClient(server_socket, 0); if (client_socket > 0) { @@ -478,7 +478,7 @@ void ProcessDebug() { if (client_socket < 1) { - client_socket = GetClient(server_socket); + client_socket = GetClient(server_socket, 0); if (client_socket > 0) { diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index a2bc0e1d..941fda4b 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -1198,6 +1198,68 @@ static void intClear(u32 Addr, u32 Size) { static void intShutdown() { } +static void process_gdb(void) { + static int shutdown; + static u32 tgt_addr; + static int step, must_continue; + struct msg msg; + + if (shutdown) + return; + + if (step || (must_continue && tgt_addr && tgt_addr == psxRegs.pc)) { + msg.type = MSG_TYPE_HIT; +#if DEBUG == 1 + printf("hit address 0x%08X\n", psxRegs.pc); +#endif + gdbstub_sys_send(&msg); + must_continue = 0; + step = 0; + } + + if (!must_continue) { + gdbstub_sys_recv(&msg); + + switch (msg.type) { + case MSG_TYPE_CONTINUE: + must_continue = 1; + break; + + case MSG_TYPE_STEP: + step = 1; + break; + + case MSG_TYPE_REMOVE_BREAKPOINT: { + struct msg out; + + tgt_addr = 0; + out.type = MSG_TYPE_ACK; + + gdbstub_sys_send(&out); + } + break; + + case MSG_TYPE_BREAKPOINT: { + struct msg out; + + tgt_addr = msg.data.breakpoint.addr; + out.type = MSG_TYPE_ACK; + + gdbstub_sys_send(&out); + } + break; + + case MSG_TYPE_SHUTDOWN: + shutdown = 1; + break; + + default: + fprintf(stderr, "unknown msg.type %d\n", msg.type); + break; + } + } +} + // interpreter execution static inline void execI() { u32 *code = Read_ICache(psxRegs.pc, FALSE); @@ -1205,7 +1267,7 @@ static inline void execI() { debugI(); - if (Config.GdbServer) dbg_sys_process(); + if (Config.GdbServer) process_gdb(); else if (Config.Debug) ProcessDebug(); psxRegs.pc += 4; diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c index 51aefdf7..eec4c96a 100644 --- a/libpcsxcore/socket.c +++ b/libpcsxcore/socket.c @@ -88,7 +88,7 @@ void StopServer(int s_socket) { #endif } -int GetClient(int s_socket) { +int GetClient(int s_socket, int blocking) { int new_socket = accept(s_socket, NULL, NULL); #ifdef _WIN32 @@ -100,6 +100,7 @@ int GetClient(int s_socket) { #endif #ifndef _WIN32 + if (!blocking) { int flags; flags = fcntl(new_socket, F_GETFL, 0); diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h index 531a6485..852c76a4 100644 --- a/libpcsxcore/socket.h +++ b/libpcsxcore/socket.h @@ -35,7 +35,7 @@ enum read_socket_err int StartServer(unsigned short port); void StopServer(int s_socket); -int GetClient(int s_socket); +int GetClient(int s_socket, int blocking); void CloseClient(int client_socket); int HasClient(int client_socket); diff --git a/win32/gui/WndMain.c b/win32/gui/WndMain.c index 374b1877..4c01b200 100644 --- a/win32/gui/WndMain.c +++ b/win32/gui/WndMain.c @@ -238,6 +238,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine RunGui(); + if (Config.GdbServer) dbg_stop(); + return 0; } @@ -1570,7 +1572,7 @@ BOOL CALLBACK ConfigureCpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPar } if (Config.GdbServer) { - GdbStartServer(); + dbg_start(); } SaveConfig(); @@ -1996,8 +1998,7 @@ int SysInit() { LoadMcds(Config.Mcd1, Config.Mcd2); if (Config.Debug) StartDebugger(); - - if (Config.GdbServer) GdbStartServer(); + else if (Config.GdbServer) dbg_start(); return 0; } -- cgit v1.2.3