GDB on PS2

Discuss the development of software, tools, libraries and anything else that helps make ps2dev happen.

Moderators: cheriff, Herben

Post Reply
RandomZero
Posts: 2
Joined: Fri Dec 23, 2005 4:25 pm

GDB on PS2

Post by RandomZero »

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.
User avatar
Drakonite
Site Admin
Posts: 990
Joined: Sat Jan 17, 2004 1:30 am
Contact:

Post by Drakonite »

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
Mega Man
Posts: 260
Joined: Sat Jun 18, 2005 3:14 am
Contact:

Post by Mega Man »

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):

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&#40;char **ptr, int *intValue&#41;;
 static unsigned char *mem2hex&#40;char *mem, char *buf, int count, int may_fault&#41;;
 void handle_exception&#40; gdb_regs_ps2 *regs &#41;;
+static int gdbstub_net_accept&#40;&#41;;
 
 // 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&#40; gdbstub_recv_buffer_g&#91;recvd_chars_processed++&#93; &#41;;
 	&#125;
 
-	gdbstub_error&#40; "Couldn't get a char\n" &#41;;
+
+	printf&#40;"Waiting for remote GDB to connect\n"&#41;;
+	while &#40;gdbstub_net_accept&#40;&#41; == -1&#41;
+	&#123;
+		printf&#40;"GDB reconnect failed.\n"&#41;;
+	&#125;
 
 	return 0xff;
 &#125;
@@ -444,6 +453,9 @@
 	unsigned char checksum;
 	unsigned char ch;
 	int count, sent_size;
+	int n;
+	int len;
+
 	gdbstub_send_buffer_g&#91;0&#93; = '$';
 	checksum = 0;
 	count = 0;
@@ -460,7 +472,16 @@
 	while&#40; !gdbstub_ready_to_send&#40;&#41; &#41; &#123;
 		;
 	&#125;
-	sent_size = send&#40; cs_g, gdbstub_send_buffer_g, count+4, 0 &#41;;
+	len = count+4;
+	sent_size = n = send&#40;cs_g, gdbstub_send_buffer_g, len, 0&#41;;
+	// Send buffer of ps2ips &#40;1024 Bytes&#41; could be to small when sending all registers&#58;
+	while &#40;sent_size < len&#41;
+	&#123;
+		n = send&#40;cs_g, &gdbstub_send_buffer_g&#91;sent_size&#93;, len - sent_size, 0&#41;;
+		if &#40;n <= 0&#41;
+			break;
+		sent_size += n;
+	&#125;
 	while &#40;&#40;getDebugChar&#40;&#41; & 0x7f&#41; != '+'&#41;;		// Wait for ack.
 &#125;
 
@@ -468,6 +489,27 @@
 // has been an error. WHAT'S THIS ABOUT THEN???
 static volatile int mem_err = 0;
 
+// Convert register to hex &#40;Print 64 bit register&#41;.
+static unsigned char *reg2hex&#40;char *mem, char *buf, int count, int may_fault&#41;
+&#123;
+	unsigned char *ptr;
+	unsigned int i;
+	unsigned int j;
+
+	ptr = buf;
+
+	for &#40;i = 0; i < count; i += 4&#41;
+	&#123;
+		ptr = mem2hex&#40;&mem&#91;i&#93;, ptr, 4, may_fault&#41;;
+		for &#40;j = 0; j < 8; j++&#41;
+		&#123;
+			*ptr++ = hexchars&#91;0&#93;;
+		&#125;
+	&#125;
+
+	return ptr;
+&#125;
+
 
 // Convert the memory pointed to by mem into hex, placing result in buf.
 // Return a pointer to the last char put in buf &#40;null&#41;, in case of mem fault, return 0.
@@ -510,6 +552,21 @@
 	return buf;
 &#125;
 
+// Copy hex to register
+static char *hex2reg&#40;char *buf, char *mem, int count, int may_fault&#41;
+&#123;
+	char *ptr;
+	int i;
+
+	ptr = mem;
+
+	for &#40;i = 0; i < count; i += 4&#41;
+	&#123;
+		// Only use lower 32 bit.
+		ptr = hex2mem&#40;&buf&#91;4*i&#93;, ptr, 4, may_fault&#41;;
+	&#125;
+	return ptr;
+&#125;
 
 // 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&#91;REG_EPC >> 4&#93;;
 	*ptr++ = hexchars&#91;REG_EPC & 0xf&#93;;
 	*ptr++ = '&#58;';
-	ptr = mem2hex&#40;&#40;char *&#41;&regs->cp0_epc, ptr, 4, 0&#41;;
+	ptr = reg2hex&#40;&#40;char *&#41;&regs->cp0_epc, ptr, 4, 0&#41;;
 	*ptr++ = ';';
 
 #ifdef COMPILER_USES_30_AS_FP
@@ -1035,14 +1092,14 @@
 	*ptr++ = hexchars&#91;REG_FP >> 4&#93;;
 	*ptr++ = hexchars&#91;REG_FP & 0xf&#93;;
 	*ptr++ = '&#58;';
-	ptr = mem2hex&#40;&#40;char *&#41;&regs->reg30, ptr, 4, 0&#41;;
+	ptr = reg2hex&#40;&#40;char *&#41;&regs->reg30, ptr, 4, 0&#41;;
 	*ptr++ = ';';
 #else
 	// Send stack pointer as frame pointer instead, it's the best we can do?
 	*ptr++ = hexchars&#91;REG_FP >> 4&#93;;
 	*ptr++ = hexchars&#91;REG_FP & 0xf&#93;;
 	*ptr++ = '&#58;';
-	ptr = mem2hex&#40;&#40;char *&#41;&regs->reg29, ptr, 4, 0&#41;;
+	ptr = reg2hex&#40;&#40;char *&#41;&regs->reg29, ptr, 4, 0&#41;;
 	*ptr++ = ';';
 #endif
 
@@ -1050,7 +1107,7 @@
 	*ptr++ = hexchars&#91;REG_SP >> 4&#93;;
 	*ptr++ = hexchars&#91;REG_SP & 0xf&#93;;
 	*ptr++ = '&#58;';
-	ptr = mem2hex&#40;&#40;char *&#41;&regs->reg29, ptr, 4, 0&#41;;
+	ptr = reg2hex&#40;&#40;char *&#41;&regs->reg29, ptr, 4, 0&#41;;
 	*ptr++ = ';';
 
 	// put the packet.
@@ -1088,12 +1145,13 @@
 
 		// Return the value of the CPU registers.
 		case 'g'&#58;
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->reg0, ptr, 32*4, 0&#41;;		// r0...r31
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->cp0_status, ptr, 6*4, 0&#41;;	// status, lo, hi, bad, cause, pc &#40;epc!&#41;.
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->fpr0, ptr, 32*4, 0&#41;;		// f0...31
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->cp1_fsr, ptr, 2*4, 0&#41;;		// cp1
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->frame_ptr, ptr, 2*4, 0&#41;;	// fp, dummy. What's dummy for?
-			ptr = mem2hex&#40;&#40;char *&#41;&regs->cp0_index, ptr, 16*4, 0&#41;;	// index, random, entrylo0, entrylo0 ... prid
+			ptr = reg2hex&#40;&#40;char *&#41;&regs->reg0, ptr, 32*4, 0&#41;;		// r0...r31
+			ptr = reg2hex&#40;&#40;char *&#41;&regs->cp0_status, ptr, 6*4, 0&#41;;	// status, lo, hi, bad, cause, pc &#40;epc!&#41;.
+			ptr = reg2hex&#40;&#40;char *&#41;&regs->fpr0, ptr, 32*4, 0&#41;;		// f0...31
+			ptr = mem2hex&#40;&#40;char *&#41;&regs->cp1_fsr, ptr, 4, 0&#41;;		// cp1
+			ptr = mem2hex&#40;&#40;char *&#41;&regs->cp1_fir, ptr, 4, 0&#41;;		// cp1
+			/*ptr = reg2hex&#40;&#40;char *&#41;&regs->frame_ptr, ptr, 4, 0&#41;;	// fp, dummy. What's dummy for?
+			ptr = reg2hex&#40;&#40;char *&#41;&regs->cp0_index, ptr, 16*4, 0&#41;;	// index, random, entrylo0, entrylo0 ... prid*/
 			break;
 
 		// Set the value of the CPU registers - return OK.
@@ -1102,7 +1160,17 @@
 			// TODO &#58;&#58; Test this, what about the SP stuff?
 			ptr2 = &input_buffer&#91;1&#93;;
 			printf&#40;"DODGY G COMMAND RECIEVED\n"&#41;;
-			hex2mem&#40;ptr2, &#40;char *&#41;regs, 90*4, 0&#41;;					// All regs.
+			//hex2reg&#40;ptr2, &#40;char *&#41;regs, 90*4, 0&#41;;					// All regs.
+			hex2reg&#40;ptr2, &#40;char *&#41;&regs->reg0, 32*4, 0&#41;;
+			ptr2 = &ptr2&#91;32*16&#93;;
+			hex2reg&#40;ptr2, &#40;char *&#41;&regs->cp0_status, 6*4, 0&#41;;
+			ptr2 = &ptr2&#91;6*16&#93;;
+			hex2reg&#40;ptr2, &#40;char *&#41;&regs->fpr0, 32*4, 0&#41;;
+			ptr2 = &ptr2&#91;32*16&#93;;
+			hex2mem&#40;ptr2, &#40;char *&#41;&regs->cp1_fsr, 4, 0&#41;;
+			ptr2 = &ptr2&#91;1*8&#93;;
+			hex2mem&#40;ptr2, &#40;char *&#41;&regs->cp1_fir, 4, 0&#41;;
+			ptr2 = &ptr2&#91;1*8&#93;;
 			// 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 = &#40;unsigned long *&#41;registers&#91;SP&#93;;
@@ -1276,7 +1344,7 @@
 // -1 == failure
 int gdbstub_net_open&#40;&#41;
 &#123;
-	int remote_len, tmp;
+	int tmp;
 	int rc_bind, rc_listen;
 
 	if&#40; SifLoadModule&#40;HOSTPATHIRX "ps2ips.irx", 0, NULL&#41; < 0 &#41; &#123;
@@ -1321,8 +1389,18 @@
 		return -1;
 	&#125;
 	gdbstub_printf&#40; DEBUG_COMMSINIT, "Listen returned %i.\n", rc_listen &#41;;
+	return 0;
+&#125;
+
+static int gdbstub_net_accept&#40;&#41;
+&#123;
+	int remote_len;
+	int tmp;
 
 	remote_len = sizeof&#40; gdb_remote_addr_g &#41;;
+	// Disconnect last connection if there was any.
+	if &#40;cs_g >= 0&#41;
+		disconnect&#40;cs_g&#41;;
 	cs_g = accept&#40; sh_g, &#40;struct sockaddr *&#41;&gdb_remote_addr_g, &remote_len &#41;;
 
 	if &#40; cs_g < 0 &#41; &#123;
@@ -1345,7 +1423,6 @@
 	return 0;
 &#125;
 
-
 void gdbstub_net_close&#40;&#41;
 &#123;
 	disconnect&#40; cs_g &#41;;
@@ -1365,7 +1442,8 @@
 	gdbstub_num_exceptions_g = 0;
 	thread_id_g = GetThreadId&#40;&#41;;
 
-	if&#40; gdbstub_net_open&#40;&#41; == -1 &#41; &#123;
+	if&#40; gdbstub_net_open&#40;&#41; == -1 
+		|| gdbstub_net_accept&#40;&#41; == -1&#41; &#123;
 		gdbstub_error&#40;"failed to open net connection.\n"&#41;;
 		return -1;
 	&#125;
@@ -1434,4 +1512,5 @@
 		ExitDeleteThread&#40;&#41;;
 		return -1;
 	&#125;
+	return 0;
 &#125;
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.
RandomZero
Posts: 2
Joined: Fri Dec 23, 2005 4:25 pm

Post by RandomZero »

Thanks - nice patch. :)
tumnes
Posts: 23
Joined: Fri Sep 17, 2004 12:02 pm
Contact:

Post by tumnes »

Mega Man wrote: ...

and the following patch for ps2gdb (this patch uses 32 Bits for all registers):

...
If this is the preferred way to do this, is there any reason this patch has not been submitted to the trunk?
cosmito
Posts: 307
Joined: Sun Mar 04, 2007 4:26 am
Location: Portugal
Contact:

Post by cosmito »

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).
raema
Posts: 5
Joined: Tue Jan 26, 2010 1:15 am

Post by raema »

Hello Cosmito, are you still there ... ?

What is the status of your patches on ps2gdb ?

Does it still work with the latest ps2sdk ?
cosmito
Posts: 307
Joined: Sun Mar 04, 2007 4:26 am
Location: Portugal
Contact:

Post by cosmito »

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 ?
Hi,

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...
Post Reply