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