Does anyone know of a GDB port (or any other PS2-side debugger) which runs on the PS2, and which will allow remote debugging via a Windows sytem running VC6?
Ie, allow execution of a binary compiled with plugin tools in VC6, initiate transfer of the binary to the PS2, and allow windows side stepping through of that binary running on the PS2.
If not, I might look at getting gdb running on the PS2 for such a purpose.
GDB on PS2
If you look in svn there is "ps2gdb" ;) .. Of course, the last I knew it did not work very well, i.e. it was extremely slow. If you can get it working nicely you'd make a lot of people happy.
Shoot Pixels Not People!
Makeshift Development
Makeshift Development
I used a normal gdb 6.3 with the following configuration:
./configure --host=i686-pc-linux-gnu --target=mips32
and the following patch for ps2gdb (this patch uses 32 Bits for all registers):
The advantage of the patch is, that it works with an unpatched gdb. I also added some improvements, e.g. big messages couldn't be send correctly.
I don't tested it with the current version of ps2gdb, but I think ps2gdb doesn't change.
To connect use the following commands in gdb:
set endian little
target remote 192.168.1.23:12
Don't forget to add "gdb_stub_main(argc, argv);" to your application to activate it.
./configure --host=i686-pc-linux-gnu --target=mips32
and the following patch for ps2gdb (this patch uses 32 Bits for all registers):
Code: Select all
Index: ee/Makefile
===================================================================
RCS file: /home/ps2cvs/ps2gdb/ee/Makefile,v
retrieving revision 1.3
diff -u -r1.3 Makefile
--- ee/Makefile 26 Oct 2004 10:07:53 -0000 1.3
+++ ee/Makefile 3 Jul 2005 16:06:41 -0000
@@ -5,7 +5,7 @@
EE_LIB = ../lib/libps2gdbStub.a
EE_OBJS = ps2gdbStub.o gdb-low.o
-EE_CFLAGS += -g
+EE_CFLAGS += -g #-DDEBUG
EE_LDFLAGS += -Wl,-Map,ps2gdbStub.map -L. -L../lib -L$(PS2SDK)/ee/lib
all: $(EE_LIB)
Index: ee/ps2gdbStub.c
===================================================================
RCS file: /home/ps2cvs/ps2gdb/ee/ps2gdbStub.c,v
retrieving revision 1.5
diff -u -r1.5 ps2gdbStub.c
--- ee/ps2gdbStub.c 26 Oct 2004 09:52:36 -0000 1.5
+++ ee/ps2gdbStub.c 3 Jul 2005 16:06:45 -0000
@@ -12,6 +12,9 @@
#include <debug.h>
#include <ps2ip.h>
#include <tcpip.h>
+#include <string.h>
+#include <loadfile.h>
+
#include "gdb-stub.h"
#include "inst.h"
@@ -80,6 +83,7 @@
static int hexToInt(char **ptr, int *intValue);
static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
void handle_exception( gdb_regs_ps2 *regs );
+static int gdbstub_net_accept();
// These are the gdb buffers. For the tcpip comms, there are seperate buffers, which fill input_buffer and output_buffer when
// needed.
@@ -165,7 +169,7 @@
struct sockaddr_in gdb_remote_addr_g;
fd_set comms_fd_g;
int sh_g;
-int cs_g;
+int cs_g = -1;
int alarmid_g;
// Don't want to wait around too much.
@@ -320,7 +324,12 @@
return( gdbstub_recv_buffer_g[recvd_chars_processed++] );
}
- gdbstub_error( "Couldn't get a char\n" );
+
+ printf("Waiting for remote GDB to connect\n");
+ while (gdbstub_net_accept() == -1)
+ {
+ printf("GDB reconnect failed.\n");
+ }
return 0xff;
}
@@ -444,6 +453,9 @@
unsigned char checksum;
unsigned char ch;
int count, sent_size;
+ int n;
+ int len;
+
gdbstub_send_buffer_g[0] = '$';
checksum = 0;
count = 0;
@@ -460,7 +472,16 @@
while( !gdbstub_ready_to_send() ) {
;
}
- sent_size = send( cs_g, gdbstub_send_buffer_g, count+4, 0 );
+ len = count+4;
+ sent_size = n = send(cs_g, gdbstub_send_buffer_g, len, 0);
+ // Send buffer of ps2ips (1024 Bytes) could be to small when sending all registers:
+ while (sent_size < len)
+ {
+ n = send(cs_g, &gdbstub_send_buffer_g[sent_size], len - sent_size, 0);
+ if (n <= 0)
+ break;
+ sent_size += n;
+ }
while ((getDebugChar() & 0x7f) != '+'); // Wait for ack.
}
@@ -468,6 +489,27 @@
// has been an error. WHAT'S THIS ABOUT THEN???
static volatile int mem_err = 0;
+// Convert register to hex (Print 64 bit register).
+static unsigned char *reg2hex(char *mem, char *buf, int count, int may_fault)
+{
+ unsigned char *ptr;
+ unsigned int i;
+ unsigned int j;
+
+ ptr = buf;
+
+ for (i = 0; i < count; i += 4)
+ {
+ ptr = mem2hex(&mem[i], ptr, 4, may_fault);
+ for (j = 0; j < 8; j++)
+ {
+ *ptr++ = hexchars[0];
+ }
+ }
+
+ return ptr;
+}
+
// Convert the memory pointed to by mem into hex, placing result in buf.
// Return a pointer to the last char put in buf (null), in case of mem fault, return 0.
@@ -510,6 +552,21 @@
return buf;
}
+// Copy hex to register
+static char *hex2reg(char *buf, char *mem, int count, int may_fault)
+{
+ char *ptr;
+ int i;
+
+ ptr = mem;
+
+ for (i = 0; i < count; i += 4)
+ {
+ // Only use lower 32 bit.
+ ptr = hex2mem(&buf[4*i], ptr, 4, may_fault);
+ }
+ return ptr;
+}
// Writes the binary of the hex array pointed to by into mem.
// Returns a pointer to the byte AFTER the last written.
@@ -1027,7 +1084,7 @@
*ptr++ = hexchars[REG_EPC >> 4];
*ptr++ = hexchars[REG_EPC & 0xf];
*ptr++ = ':';
- ptr = mem2hex((char *)®s->cp0_epc, ptr, 4, 0);
+ ptr = reg2hex((char *)®s->cp0_epc, ptr, 4, 0);
*ptr++ = ';';
#ifdef COMPILER_USES_30_AS_FP
@@ -1035,14 +1092,14 @@
*ptr++ = hexchars[REG_FP >> 4];
*ptr++ = hexchars[REG_FP & 0xf];
*ptr++ = ':';
- ptr = mem2hex((char *)®s->reg30, ptr, 4, 0);
+ ptr = reg2hex((char *)®s->reg30, ptr, 4, 0);
*ptr++ = ';';
#else
// Send stack pointer as frame pointer instead, it's the best we can do?
*ptr++ = hexchars[REG_FP >> 4];
*ptr++ = hexchars[REG_FP & 0xf];
*ptr++ = ':';
- ptr = mem2hex((char *)®s->reg29, ptr, 4, 0);
+ ptr = reg2hex((char *)®s->reg29, ptr, 4, 0);
*ptr++ = ';';
#endif
@@ -1050,7 +1107,7 @@
*ptr++ = hexchars[REG_SP >> 4];
*ptr++ = hexchars[REG_SP & 0xf];
*ptr++ = ':';
- ptr = mem2hex((char *)®s->reg29, ptr, 4, 0);
+ ptr = reg2hex((char *)®s->reg29, ptr, 4, 0);
*ptr++ = ';';
// put the packet.
@@ -1088,12 +1145,13 @@
// Return the value of the CPU registers.
case 'g':
- ptr = mem2hex((char *)®s->reg0, ptr, 32*4, 0); // r0...r31
- ptr = mem2hex((char *)®s->cp0_status, ptr, 6*4, 0); // status, lo, hi, bad, cause, pc (epc!).
- ptr = mem2hex((char *)®s->fpr0, ptr, 32*4, 0); // f0...31
- ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*4, 0); // cp1
- ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*4, 0); // fp, dummy. What's dummy for?
- ptr = mem2hex((char *)®s->cp0_index, ptr, 16*4, 0); // index, random, entrylo0, entrylo0 ... prid
+ ptr = reg2hex((char *)®s->reg0, ptr, 32*4, 0); // r0...r31
+ ptr = reg2hex((char *)®s->cp0_status, ptr, 6*4, 0); // status, lo, hi, bad, cause, pc (epc!).
+ ptr = reg2hex((char *)®s->fpr0, ptr, 32*4, 0); // f0...31
+ ptr = mem2hex((char *)®s->cp1_fsr, ptr, 4, 0); // cp1
+ ptr = mem2hex((char *)®s->cp1_fir, ptr, 4, 0); // cp1
+ /*ptr = reg2hex((char *)®s->frame_ptr, ptr, 4, 0); // fp, dummy. What's dummy for?
+ ptr = reg2hex((char *)®s->cp0_index, ptr, 16*4, 0); // index, random, entrylo0, entrylo0 ... prid*/
break;
// Set the value of the CPU registers - return OK.
@@ -1102,7 +1160,17 @@
// TODO :: Test this, what about the SP stuff?
ptr2 = &input_buffer[1];
printf("DODGY G COMMAND RECIEVED\n");
- hex2mem(ptr2, (char *)regs, 90*4, 0); // All regs.
+ //hex2reg(ptr2, (char *)regs, 90*4, 0); // All regs.
+ hex2reg(ptr2, (char *)®s->reg0, 32*4, 0);
+ ptr2 = &ptr2[32*16];
+ hex2reg(ptr2, (char *)®s->cp0_status, 6*4, 0);
+ ptr2 = &ptr2[6*16];
+ hex2reg(ptr2, (char *)®s->fpr0, 32*4, 0);
+ ptr2 = &ptr2[32*16];
+ hex2mem(ptr2, (char *)®s->cp1_fsr, 4, 0);
+ ptr2 = &ptr2[1*8];
+ hex2mem(ptr2, (char *)®s->cp1_fir, 4, 0);
+ ptr2 = &ptr2[1*8];
// Not sure about this part, so I'm not doing it.
// See if the stack pointer has moved. If so, then copy the saved locals and ins to the new location.
// newsp = (unsigned long *)registers[SP];
@@ -1276,7 +1344,7 @@
// -1 == failure
int gdbstub_net_open()
{
- int remote_len, tmp;
+ int tmp;
int rc_bind, rc_listen;
if( SifLoadModule(HOSTPATHIRX "ps2ips.irx", 0, NULL) < 0 ) {
@@ -1321,8 +1389,18 @@
return -1;
}
gdbstub_printf( DEBUG_COMMSINIT, "Listen returned %i.\n", rc_listen );
+ return 0;
+}
+
+static int gdbstub_net_accept()
+{
+ int remote_len;
+ int tmp;
remote_len = sizeof( gdb_remote_addr_g );
+ // Disconnect last connection if there was any.
+ if (cs_g >= 0)
+ disconnect(cs_g);
cs_g = accept( sh_g, (struct sockaddr *)&gdb_remote_addr_g, &remote_len );
if ( cs_g < 0 ) {
@@ -1345,7 +1423,6 @@
return 0;
}
-
void gdbstub_net_close()
{
disconnect( cs_g );
@@ -1365,7 +1442,8 @@
gdbstub_num_exceptions_g = 0;
thread_id_g = GetThreadId();
- if( gdbstub_net_open() == -1 ) {
+ if( gdbstub_net_open() == -1
+ || gdbstub_net_accept() == -1) {
gdbstub_error("failed to open net connection.\n");
return -1;
}
@@ -1434,4 +1512,5 @@
ExitDeleteThread();
return -1;
}
+ return 0;
}
I don't tested it with the current version of ps2gdb, but I think ps2gdb doesn't change.
To connect use the following commands in gdb:
set endian little
target remote 192.168.1.23:12
Don't forget to add "gdb_stub_main(argc, argv);" to your application to activate it.
Check also the thread
http://forums.ps2dev.org/viewtopic.php?t=11075
where I applied Megaman's patch and experimented with ps2gdb.
There were some issues regarding exceptions but I managed to get it working.
What would nice now would be a gdb GUI or use Eclipse integrated support (it's already being used with pspsdk - there are some threads about it).
http://forums.ps2dev.org/viewtopic.php?t=11075
where I applied Megaman's patch and experimented with ps2gdb.
There were some issues regarding exceptions but I managed to get it working.
What would nice now would be a gdb GUI or use Eclipse integrated support (it's already being used with pspsdk - there are some threads about it).
Hi,raema wrote:Hello Cosmito, are you still there ... ?
What is the status of your patches on ps2gdb ?
Does it still work with the latest ps2sdk ?
I haven't done no more modifications since the last. I sort of gave up using gdb since it's too little user-friendly and very slow due to the network performance of the TCP stack. Unfortunably there's no better alternative...