Replaced in-house gdb stub by MIT-licensed implementation
Imported from a fork of https://github.com/mborgerson/gdbstub
This commit is contained in:
parent
470da05658
commit
850010a96b
|
@ -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
|
||||
|
|
|
@ -52,3 +52,4 @@ add_subdirectory(gui)
|
|||
add_subdirectory(plugins)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(dynstr)
|
||||
add_subdirectory(gdbstub)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
message(STATUS "* Configuring gdbstub")
|
||||
|
||||
set(SRCS gdbstub/gdbstub.c gdbstub_sys.c)
|
||||
include_directories(gdbstub .)
|
||||
add_library(gdbstub STATIC ${SRCS})
|
|
@ -0,0 +1 @@
|
|||
Subproject commit b00d0f815b3996a13ce87a4d9d6d7038353e77e6
|
|
@ -0,0 +1,132 @@
|
|||
#include "gdbstub_sys.h"
|
||||
#include "gdbstub.h"
|
||||
#include "libpcsxcore/socket.h"
|
||||
#include "libpcsxcore/r3000a.h"
|
||||
#include <stdio.h>
|
||||
|
||||
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");
|
||||
}
|
|
@ -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 */
|
|
@ -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")));
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -474,7 +474,7 @@ void ProcessDebug() {
|
|||
MarkMap(_Rd_, MAP_EXEC_JAL);
|
||||
}
|
||||
}
|
||||
while (paused || GdbServerRunning()) {
|
||||
while (paused) {
|
||||
|
||||
if (client_socket < 1)
|
||||
{
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
#include "socket.h"
|
||||
#include "psxcommon.h"
|
||||
#include "misc.h"
|
||||
#include "system.h"
|
||||
#include "dynstr.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
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();
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -323,8 +323,7 @@ void psxRcntUpdate()
|
|||
}
|
||||
}
|
||||
|
||||
DebugVSync();
|
||||
GdbServerVSync();
|
||||
if (Config.Debug) DebugVSync();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "sio.h"
|
||||
#include "misc.h"
|
||||
#include "cheat.h"
|
||||
#include "gdb_server.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#ifndef LVM_GETSELECTIONMARK
|
||||
|
|
Loading…
Reference in New Issue