Browse Source

do not check checksums in noack case

git-svn-id: svn://svn.berlios.de/openocd/trunk@969 b42882b7-edfa-0310-969c-e2dbd0fdcd60
tags/v0.1.0
oharboe 15 years ago
parent
commit
f5507d8929
1 changed files with 124 additions and 104 deletions
  1. +124
    -104
      src/server/gdb_server.c

+ 124
- 104
src/server/gdb_server.c View File

@@ -395,13 +395,119 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len)
return retval;
}

int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
static __inline__ int fetch_packet(connection_t *connection, int *checksum_ok, int noack, int *len, char *buffer)
{
unsigned char my_checksum = 0;
char checksum[3];
int character;
int retval;
gdb_connection_t *gdb_con = connection->priv;
my_checksum = 0;
int count = 0;
count = 0;
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)
{
LOG_ERROR("packet buffer too small");
return ERROR_GDB_BUFFER_TOO_SMALL;
}

if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;

if (character == '#')
break;

if (character == '}')
{
/* data transmitted in binary mode (X packet)
* uses 0x7d as escape character */
my_checksum += character & 0xff;
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
my_checksum += character & 0xff;
buffer[count++] = (character ^ 0x20) & 0xff;
}
else
{
my_checksum += character & 0xff;
buffer[count++] = character & 0xff;
}
}

*len = count;

if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
checksum[0] = character;
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
checksum[1] = character;
checksum[2] = 0;
if (!noack)
{
*checksum_ok=(my_checksum == strtoul(checksum, NULL, 16));
}
return ERROR_OK;
}

int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
{
int character;
int retval;
char checksum[3];
unsigned char my_checksum = 0;
gdb_connection_t *gdb_con = connection->priv;

while (1)
@@ -437,116 +543,30 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
}
} while (character != '$');

my_checksum = 0;

count = 0;
gdb_connection_t *gdb_con = connection->priv;
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)
{
LOG_ERROR("packet buffer too small");
return ERROR_GDB_BUFFER_TOO_SMALL;
}

if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
int checksum_ok;
/* explicit code expansion here to get faster inlined code in -O3 by not
* calculating checksum
*/
if (gdb_con->noack_mode)
{
if ((retval=fetch_packet(connection, &checksum_ok, 1, len, buffer))!=ERROR_OK)
return retval;

if (character == '#')
break;

if (character == '}')
{
/* data transmitted in binary mode (X packet)
* uses 0x7d as escape character */
my_checksum += character & 0xff;
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
my_checksum += character & 0xff;
buffer[count++] = (character ^ 0x20) & 0xff;
}
else
{
my_checksum += character & 0xff;
buffer[count++] = character & 0xff;
}
}

*len = count;

if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
checksum[0] = character;
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
checksum[1] = character;
checksum[2] = 0;

if (my_checksum == strtoul(checksum, NULL, 16))
} else
{
if (gdb_con->noack_mode)
break;
gdb_write(connection, "+", 1);
break;
if ((retval=fetch_packet(connection, &checksum_ok, 0, len, buffer))!=ERROR_OK)
return retval;
}

if (!gdb_con->noack_mode)
if (gdb_con->noack_mode)
{
LOG_WARNING("checksum error, requesting retransmission");
gdb_write(connection, "-", 1);
/* checksum is not checked in noack mode */
break;
}
else
if (checksum_ok)
{
LOG_WARNING("checksum error, no-ack-mode");
gdb_write(connection, "+", 1);
break;
}
}


Loading…
Cancel
Save