lkml.org 
[lkml]   [2001]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPatch to gdbstub++ taking care of possible stale data in Recieve buffers and qOffsets cmd for x86.
Hi

This patch takes care of 2 things related to remote debuging of Linux
kernel using Gdb

Problem and Solution (1)
------------------------

When trying out Remote Debugging of Linux kernel using GDB, I found a
possible protocol synchronisation issue between gdb (in host) and gdbstub
(on RemoteTarget) in the current gdb remote protocol implementation (i.e
which don't use the SequenceNumber mechanism of the protocol).

The situation unfolds as follows
1) HostGdb sends a command to the RemoteTargetStub.
2) Before the RemoteTargetStub can process the command a exception or
breakpoint occurs. Or the RemoteTargetStub is getting activated only now
during booting of the RemoteTarget m/c.
3) RemoteTargetStub sends Sxx to HostGDB. HostGDB takes this as response
to command from 1 above (or ignores the command from 1 due to this)
4) HostGDB sends a new gdb command.
5) RemoteTargetStub picks up the old gdb command (from 1), and responds
to it.
6) HostGDB assumes its the response to the new command from 4 above, but
actually its response to the old (now stale or no longer valid) command
from 1 above.

Thus the RemoteTargetGdbStub and the HostGDB go out of sync.

I faced this problem when trying out remote debuging between a Linux Host
and a PC Emulation software (vmware or so) using /dev/ptyq0 and /dev/ttyq0
for communication. On looking into this I found this possible
synchronisation problem between the Host and Remote in GDB protocol, if
there is any content or old command in the Recieve buffers (s/w buffer in
gdbserial.c and or h/w buffer of uart) due to what ever reason.

To solve this problem I have implemented a clearRecieveDataBufferGDB in
gdbserail which when invoked will clear all buffered contents associated
with recieving ((a) the s/w buffer in gdbserial and (b) the buffer in
uart). It uses the existing read_char implementation of gdbserial in a
loop to accomplish this.

INTURN I call this from with in handle_exception of gdbstub just before
sending SXX signal(to notify of the exception) to HostGDB, So that
handle_exception won't respond to any old (and no longer valid)command or
invalid data in the Recieve buffer.


Problem and Solution (2)
------------------------

Also I noticed that HostGDB was sending a qOffsets query to the
RemoteTargetStub, but x86 gdbstub doesn't currently provide a
implementation for qOffset. So I implemented one which uses the following
symbols to provide the required offsets

stext for Text
gdt_table for Data (currently corresponds to .data or sdata)
__bss_start for Bss.

However once Implemented I did find that HostGDBs symbol info was getting
corrupted and I was forced to reload the symbols using symbol_file. On
looking into gdb source casualy it felt as if I can ignore qOffsets
command. Either way I already had a implementation (which is very
simple) for qOffsets command, so I have retained it in the patch __as the
bug__ seems to be __in the HostGDB code__. On looking into other gdbstub
implementations in the linux kernel Even the PPC arch's gdbstub talks
about this bug in HostGDB.

Also I picked up the elegent sprintf solution to create the response
string for qOffset from the PPC guys. Earlier I had tried a solution with
mem2hex which retains the Bytes of the address in the Target Byte order,
but for qOffset one requires to represent the address (in Hex) in the
normal reading order (varified by looking into remote.c in gdb
source) which automaticaly suites the sprintf solution.


These problem seems to be universal as far as gdb remote debug protocols
current implementations are concerned, so may be even the GDB guys need to
be informed about these possible problems. But I am not in the GDB devel
list, so someone on the list can inform them also.

-----------
Keep :-)
HanishKVC


diff -Naur linux-2.4.3-kgdb/arch/i386/kernel/gdbstub.c linux-2.4.3-kgdb-hankvc/arch/i386/kernel/gdbstub.c
--- linux-2.4.3-kgdb/arch/i386/kernel/gdbstub.c Sun Apr 29 21:25:20 2001
+++ linux-2.4.3-kgdb-hankvc/arch/i386/kernel/gdbstub.c Mon Apr 30 01:53:12 2001
@@ -116,6 +116,7 @@
/* Thread reference */
typedef unsigned char threadref[8];

+extern void clearRecieveDataBufferGDB(void); /* clear the Recieve software and hardware data buffers */
extern int putDebugChar(int); /* write a single character */
extern int getDebugChar(void); /* read and return a single char */

@@ -765,6 +766,7 @@
int i;
int dr6;
struct pt_regs tempregs;
+ extern int stext,gdt_table,__bss_start;
#define regs (*linux_regs)

/*
@@ -830,6 +832,10 @@
gdb_i386vector = exceptionVector;
gdb_i386errcode = err_code ;

+ /* clear existing (possibly stale) contents in the Recieve buffers
+ (s/w(gdbserial) and h/w) of the terminal/SerialPort used for
+ remote debugging, so that we start with a clean slate */
+ clearRecieveDataBufferGDB();
/* reply to host that an exception has occurred */
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[signo >> 4];
@@ -1043,6 +1049,17 @@
case 'E':
/* Print exception info */
printexceptioninfo(exceptionVector, err_code, remcomOutBuffer);
+ break;
+
+ case 'O':
+ /* get Section offsets */
+ /* gdb's symbol info seems to be getting corrupted after
+ this command, even ppc guys have mentioned this.
+ One is required to reload using symbol-file cmd */
+ /* .data (or sdata) currently correspond to gdt_table */
+ sprintf(remcomOutBuffer,
+ "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
+ (int)&stext, (int)&gdt_table, (int)&__bss_start);
break;
}
break;
diff -Naur linux-2.4.3-kgdb/drivers/char/gdbserial.c linux-2.4.3-kgdb-hankvc/drivers/char/gdbserial.c
--- linux-2.4.3-kgdb/drivers/char/gdbserial.c Sun Apr 29 21:25:20 2001
+++ linux-2.4.3-kgdb-hankvc/drivers/char/gdbserial.c Mon Apr 30 02:14:15 2001
@@ -278,3 +278,25 @@

} /* putDebugChar */

+/*
+ * Clear the Recieve software and hardware buffers
+ */
+void clearRecieveDataBufferGDB(void)
+{
+ int iCur;
+
+#ifdef PRNT
+ printk("clearRecieveDataBufferGDB: Entering \n");
+#endif
+ /* while((iCur=read_data_bfr()) != -1) */
+ while((iCur=read_char()) != -1)
+#ifdef PRNT
+ printk("clearRecieveDataBufferGDB: read %c \n",iCur);
+#else
+ ;
+#endif
+#ifdef PRNT
+ printk("clearRecieveDataBufferGDB: Leaving \n");
+#endif
+}
+
\
 
 \ /
  Last update: 2005-03-22 12:52    [W:0.049 / U:1.120 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site