aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2008-01-10 19:29:52 +0000
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2008-01-10 19:29:52 +0000
commit5eedf3e1cef2f2b440519f867c9cb449f616b8cd (patch)
tree97d5b1fe43aa4e1508ae65a149e006d4415c0a63
parent64aac5f7e1f2893d88fc4fb7079829de74c41920 (diff)
downloadriscv-openocd-5eedf3e1cef2f2b440519f867c9cb449f616b8cd.zip
riscv-openocd-5eedf3e1cef2f2b440519f867c9cb449f616b8cd.tar.gz
riscv-openocd-5eedf3e1cef2f2b440519f867c9cb449f616b8cd.tar.bz2
- added faster gdb packet handling (thanks to oyvind harboe for the patch)
- code reformat git-svn-id: svn://svn.berlios.de/openocd/trunk@251 b42882b7-edfa-0310-969c-e2dbd0fdcd60
-rw-r--r--src/helper/command.c8
-rw-r--r--src/server/gdb_server.c84
2 files changed, 78 insertions, 14 deletions
diff --git a/src/helper/command.c b/src/helper/command.c
index e9ea069..afd8667 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -79,12 +79,12 @@ int build_unique_lengths(command_context_t *context, command_t *commands)
/* Avoid evaluating this each time we add a command. Reduces overhead from O(n^2) to O(n).
* Makes a difference on ARM7 types machines and is not observable on GHz machines.
*/
-static int unique_length_dirty=1;
+static int unique_length_dirty = 1;
command_t* register_command(command_context_t *context, command_t *parent, char *name, int (*handler)(struct command_context_s *context, char* name, char** args, int argc), enum command_mode mode, char *help)
{
command_t *c, *p;
- unique_length_dirty=1;
+ unique_length_dirty = 1;
if (!context || !name)
return NULL;
@@ -138,7 +138,7 @@ command_t* register_command(command_context_t *context, command_t *parent, char
int unregister_command(command_context_t *context, char *name)
{
- unique_length_dirty=1;
+ unique_length_dirty = 1;
command_t *c, *p = NULL, *c2;
@@ -316,7 +316,7 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
if (unique_length_dirty)
{
- unique_length_dirty=0;
+ unique_length_dirty = 0;
/* update unique lengths */
build_unique_lengths(context, context->commands);
}
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 1614485..01d0979 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -38,7 +38,7 @@
#include <unistd.h>
#include <stdlib.h>
-#if 0
+#if 1
#define _DEBUG_GDB_IO_
#endif
@@ -185,7 +185,9 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len)
int i;
unsigned char my_checksum = 0;
char checksum[3];
+#ifdef _DEBUG_GDB_IO_
char *debug_buffer;
+#endif
int reply;
int retval;
gdb_connection_t *gdb_con = connection->priv;
@@ -195,12 +197,13 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len)
while (1)
{
+#ifdef _DEBUG_GDB_IO_
debug_buffer = malloc(len + 1);
memcpy(debug_buffer, buffer, len);
debug_buffer[len] = 0;
DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
free(debug_buffer);
-
+#endif
write_socket(connection->fd, "$", 1);
if (len > 0)
write_socket(connection->fd, buffer, len);
@@ -283,9 +286,63 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
} while (character != '$');
my_checksum = 0;
-
- do
+
+ for (;;)
{
+ /* The common case is that we have an entire packet with no escape chars.
+ * We need to leave at least 2 bytes in the buffer to have
+ * gdb_get_char() update various bits and bobs correctly.
+ */
+ if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len))
+ {
+ /* The compiler will struggle a bit with constant propagation and
+ * aliasing, so we help it by showing that these values do not
+ * change inside the loop
+ */
+ int i;
+ char *buf = gdb_con->buf_p;
+ int run = gdb_con->buf_cnt - 2;
+ i = 0;
+ int done = 0;
+ while (i < run)
+ {
+ character = *buf++;
+ i++;
+ if (character == '#')
+ {
+ /* Danger! character can be '#' when esc is
+ * used so we need an explicit boolean for done here.
+ */
+ done = 1;
+ break;
+ }
+
+ if (character == '}')
+ {
+ /* data transmitted in binary mode (X packet)
+ * uses 0x7d as escape character */
+ my_checksum += character & 0xff;
+ character = *buf++;
+ i++;
+ my_checksum += character & 0xff;
+ buffer[count++] = (character ^ 0x20) & 0xff;
+ } else
+ {
+ my_checksum += character & 0xff;
+ buffer[count++] = character & 0xff;
+ }
+ }
+ gdb_con->buf_p += i;
+ gdb_con->buf_cnt -= i;
+ if (done)
+ break;
+ }
+ if (count > *len)
+ {
+ ERROR("packet buffer too small");
+ return ERROR_GDB_BUFFER_TOO_SMALL;
+ }
+
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
@@ -308,12 +365,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
buffer[count++] = character & 0xff;
}
- if (count > *len)
- {
- ERROR("packet buffer too small");
- return ERROR_GDB_BUFFER_TOO_SMALL;
- }
- } while (1);
+ }
*len = count;
@@ -910,6 +962,18 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
retval = target->type->read_memory(target, addr, 1, len, buffer);
}
+#if 0
+ if (retval == ERROR_TARGET_DATA_ABORT)
+ {
+ /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
+ * At some point this might be fixed in GDB, in which case this code can be removed.
+ * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
+ */
+ memset(buffer, 0, len);
+ retval = ERROR_OK;
+ }
+#endif
+
if (retval == ERROR_OK)
{
hex_buffer = malloc(len * 2 + 1);