|
From: Duane E. <op...@du...> - 2008-09-14 15:27:54
|
Index: gdb_server.c
===================================================================
--- gdb_server.c (revision 986)
+++ gdb_server.c (working copy)
@@ -42,9 +42,7 @@
#include <unistd.h>
#include <stdlib.h>
-#if 0
-#define _DEBUG_GDB_IO_
-#endif
+static int debug_gdb_io;
static int gdb_breakpoint_override;
static enum breakpoint_type gdb_breakpoint_override_type;
@@ -78,6 +76,15 @@
* see the code in gdb_read_memory_packet() for further explanations */
int gdb_report_data_abort = 0;
+static int
+safe_toascii(int c)
+{
+ if( (c < 0x20) || (c > 0x7e) ){
+ c = '.';
+ }
+ return c;
+}
+
int gdb_last_signal(target_t *target)
{
switch (target->debug_reason)
@@ -144,10 +151,9 @@
gdb_connection_t *gdb_con = connection->priv;
int retval=ERROR_OK;
-#ifdef _DEBUG_GDB_IO_
char *debug_buffer;
-#endif
+
if (gdb_con->buf_cnt-- > 0)
{
*next_char = *(gdb_con->buf_p++);
@@ -156,9 +162,9 @@
else
connection->input_pending = 0;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
+ }
return ERROR_OK;
}
@@ -217,13 +223,13 @@
#endif
}
-#ifdef _DEBUG_GDB_IO_
- debug_buffer = malloc(gdb_con->buf_cnt + 1);
- memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
- debug_buffer[gdb_con->buf_cnt] = 0;
- LOG_DEBUG("received '%s'", debug_buffer);
- free(debug_buffer);
-#endif
+ if( debug_gdb_io ){
+ debug_buffer = malloc(gdb_con->buf_cnt + 1);
+ memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
+ debug_buffer[gdb_con->buf_cnt] = 0;
+ LOG_DEBUG("received '%s'", debug_buffer);
+ free(debug_buffer);
+ }
gdb_con->buf_p = gdb_con->buffer;
gdb_con->buf_cnt--;
@@ -232,9 +238,9 @@
connection->input_pending = 1;
else
connection->input_pending = 0;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
+ }
return retval;
}
@@ -277,9 +283,7 @@
{
int i;
unsigned char my_checksum = 0;
-#ifdef _DEBUG_GDB_IO_
char *debug_buffer;
-#endif
int reply;
int retval;
gdb_connection_t *gdb_con = connection->priv;
@@ -287,34 +291,39 @@
for (i = 0; i < len; i++)
my_checksum += buffer[i];
-#ifdef _DEBUG_GDB_IO_
- /*
- * At this point we should have nothing in the input queue from GDB,
- * however sometimes '-' is sent even though we've already received
- * an ACK (+) for everything we've sent off.
- */
- int gotdata;
- for (;;)
- {
- if ((retval=check_pending(connection, 0, &gotdata))!=ERROR_OK)
- return retval;
- if (!gotdata)
- break;
- if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
- return retval;
- LOG_WARNING("Discard unexpected char %c", reply);
+ if( debug_gdb_io ){
+ /*
+ * At this point we should have nothing in the input queue from GDB,
+ * however sometimes '-' is sent even though we've already received
+ * an ACK (+) for everything we've sent off.
+ */
+ int gotdata;
+ for (;;){
+ if ((retval=check_pending(connection, 0, &gotdata))!=ERROR_OK)
+ return retval;
+ if (!gotdata)
+ break;
+ if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
+ return retval;
+ if( reply == '$' ){
+ gdb_putback_char( connection, reply );
+ LOG_DEBUG("Unexpected start of new packet");
+ break;
+ } else {
+ LOG_WARNING("Discard unexpected char 0x%02x %c", reply, safe_toascii(reply));
+ }
+ }
}
-#endif
while (1)
{
-#ifdef _DEBUG_GDB_IO_
- debug_buffer = malloc(len + 1);
- memcpy(debug_buffer, buffer, len);
- debug_buffer[len] = 0;
- LOG_DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
- free(debug_buffer);
-#endif
+ if( debug_gdb_io ){
+ debug_buffer = malloc(len + 1);
+ memcpy(debug_buffer, buffer, len);
+ debug_buffer[len] = 0;
+ LOG_DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
+ free(debug_buffer);
+ }
char local_buffer[1024];
local_buffer[0] = '$';
@@ -347,7 +356,14 @@
if (reply == '+')
break;
- else if (reply == '-')
+ else if( reply == '$' ){
+ // $ starts a new GDB packet.
+ // Perhaps GDB is sending a *NEW* packet.
+ // assume the packet was good.
+ gdb_putback_char( connection, reply );
+ LOG_WARNING("Got $, expected - Assuming New Packet");
+ break;
+ } else if (reply == '-')
{
/* Stop sending output packets for now */
log_remove_callback(gdb_log_callback, connection);
@@ -368,14 +384,14 @@
}
else
{
- LOG_ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
+ LOG_ERROR("(^C) unknown character 0x%2.2x (%c) in reply, dropping connection", reply, safe_toascii(reply));
gdb_con->closed=1;
return ERROR_SERVER_REMOTE_CLOSED;
}
}
else
{
- LOG_ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
+ LOG_ERROR("(?) unknown character 0x%2.2x (%c) in reply, dropping connection", reply, safe_toascii(reply));
gdb_con->closed=1;
return ERROR_SERVER_REMOTE_CLOSED;
}
@@ -517,9 +533,9 @@
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("character: '%c'", character);
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("character: '%c'", character);
+ }
switch (character)
{
@@ -538,7 +554,7 @@
*len = 0;
return ERROR_OK;
default:
- LOG_WARNING("ignoring character 0x%x", character);
+ LOG_WARNING("ignoring character 0x%x (%c)", character, safe_toascii(character) );
break;
}
} while (character != '$');
@@ -585,25 +601,42 @@
return retval;
}
+static int gdb_max_o_packet = 256;
int gdb_output_con(connection_t *connection, const char* line)
{
char *hex_buffer;
int i, bin_size;
+ int n;
bin_size = strlen(line);
+ LOG_DEBUG("TX O packet len: %d, chunksize: %d",
+ bin_size, gdb_max_o_packet );
+
+ if( gdb_max_o_packet > 0 ){
+ hex_buffer = malloc(2+(gdb_max_o_packet*2));
+ if (hex_buffer == NULL)
+ return ERROR_GDB_BUFFER_TOO_SMALL;
- hex_buffer = malloc(bin_size*2 + 2);
- if (hex_buffer == NULL)
- return ERROR_GDB_BUFFER_TOO_SMALL;
+ while( bin_size ){
+ n = bin_size;
+ if( n > gdb_max_o_packet ){
+ n = gdb_max_o_packet;
+ }
+
+
+ hex_buffer[0] = 'O';
+ for (i=0; i<n; i++)
+ snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);
+ hex_buffer[(n*2)+1] = 0;
+
+ gdb_put_packet(connection, hex_buffer, (n*2) + 1);
+ line += n;
+ bin_size -= n;
+ }
+
+ free(hex_buffer);
+ }
- hex_buffer[0] = 'O';
- for (i=0; i<bin_size; i++)
- snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);
- hex_buffer[bin_size*2+1] = 0;
-
- gdb_put_packet(connection, hex_buffer, bin_size*2 + 1);
-
- free(hex_buffer);
return ERROR_OK;
}
@@ -845,9 +878,9 @@
char *reg_packet_p;
int i;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("-");
+ }
if ((retval = target->type->get_gdb_reg_list(target, ®_list, ®_list_size)) != ERROR_OK)
{
@@ -868,15 +901,14 @@
reg_packet_p += CEIL(reg_list[i]->size, 8) * 2;
}
-#ifdef _DEBUG_GDB_IO_
- {
+ if( debug_gdb_io ){
char *reg_packet_p;
reg_packet_p = strndup(reg_packet, CEIL(reg_packet_size, 8) * 2);
LOG_DEBUG("reg_packet: %s", reg_packet_p);
free(reg_packet_p);
}
-#endif
+
gdb_put_packet(connection, reg_packet, CEIL(reg_packet_size, 8) * 2);
free(reg_packet);
@@ -893,9 +925,9 @@
int retval;
char *packet_p;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("-");
+ }
/* skip command character */
packet++;
@@ -959,9 +991,9 @@
int reg_list_size;
int retval;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
+ if( debug_gdb_io ){
+ LOG_DEBUG("-");
+ }
if ((retval = target->type->get_gdb_reg_list(target, ®_list, ®_list_size)) != ERROR_OK)
{
@@ -2258,9 +2290,137 @@
return ERROR_OK;
}
+static int
+gdb_config( Jim_GetOptInfo *goi )
+{
+ jim_wide w;
+ int e;
+ Jim_Nvp *n;
+ enum {
+ GDB_CONFIG_MAX_OPACKET,
+ GDB_DEBUG_IO,
+ };
+ const Jim_Nvp nvp_gdb_config[] = {
+ { .name = "-max-O-packet", .value = GDB_CONFIG_MAX_OPACKET },
+ { .name = "-debug-io" , .value = GDB_DEBUG_IO },
+ // terminate
+ { .name = NULL, .value = -1 },
+ };
+ while( goi->argc ){
+ e = Jim_GetOpt_Nvp( goi, nvp_gdb_config, &n );
+ if( e != JIM_OK ){
+ Jim_GetOpt_NvpUnknown( goi, nvp_gdb_config, 1 );
+ return JIM_ERR;
+ }
+
+ switch( n->value ){
+ default:
+ Jim_SetResult_sprintf( goi->interp, "Unknown cfg option %d\n", n->value );
+ return JIM_ERR;
+ case GDB_DEBUG_IO:
+ if( goi->isconfigure ){
+ if( goi->argc != 1 ){
+ Jim_WrongNumArgs(interp, 2, goi->argv-2, "VALUE");
+ return JIM_ERR;
+ }
+ e = Jim_GetOpt_Wide( goi, &w );
+ if( e != JIM_OK ){
+ return e;
+ }
+ if( (w == 0) || (w==1) ){
+ // good
+ } else {
+ /* this is a bit excessive... */
+ Jim_SetResult_sprintf( goi->interp,
+ "Expected 0/1, not %d", (int)(w) );
+ return JIM_ERR;
+ }
+ debug_gdb_io = 1;
+ }
+ Jim_SetResult( interp, Jim_NewIntObj( goi->interp, debug_gdb_io ));
+ break;
+
+ case GDB_CONFIG_MAX_OPACKET:
+ if( goi->isconfigure ){
+ if( goi->argc != 1 ){
+ Jim_WrongNumArgs(interp, 2, goi->argv-2, "VALUE");
+ return JIM_ERR;
+ }
+ e = Jim_GetOpt_Wide( goi, &w );
+ if( e != JIM_OK ){
+ return e;
+ }
+ if( (w > 2048) || (w < -1) ){
+ /* this is a bit excessive... */
+ Jim_SetResult_sprintf( goi->interp, "opacket max is 512, 0 or -1 to disable O packets");
+ return JIM_ERR;
+ }
+ if( w < 0 ){
+ w = 0;
+ }
+ gdb_max_o_packet = w;
+ }
+ Jim_SetResult( interp, Jim_NewIntObj( goi->interp, gdb_max_o_packet ) );
+ break;
+ }
+ }
+ return JIM_OK;
+}
+
+static int
+jim_gdb_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
+{
+ Jim_GetOptInfo goi;
+ Jim_Nvp *n;
+ int e;
+
+ enum {
+ GDB_CMD_CONFIG,
+ GDB_CMD_CGET
+ };
+
+ const Jim_Nvp nvp_gdb_commands[] = {
+ { .name = "configure", .value = GDB_CMD_CONFIG },
+ { .name = "cget", .value = GDB_CMD_CGET },
+ // add more here later
+ { .name = NULL, .value = -1 },
+ };
+
+
+ /* go past cmd name */
+ Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
+
+ e = Jim_GetOpt_Nvp( &goi, nvp_gdb_commands, &n );
+ if( e != JIM_OK ){
+ Jim_GetOpt_NvpUnknown( &goi, nvp_gdb_commands, 1 );
+ return JIM_ERR;
+ }
+ Jim_SetEmptyResult( goi.interp );
+ switch(n->value){
+ default:
+ Jim_SetResultString( goi.interp, "(gdb command) unknown option",-1);
+ return JIM_ERR;
+ break;
+ case GDB_CMD_CONFIG:
+ goi.isconfigure = 1;
+ return gdb_config( &goi );
+ break;
+ case GDB_CMD_CGET:
+ goi.isconfigure = 0;
+ return gdb_config( &goi );
+ break;
+ }
+}
+
+
int gdb_register_commands(command_context_t *command_context)
{
+ register_jim( command_context,
+ "gdb",
+ jim_gdb_command,
+ "(try gdb -help) for details");
+
register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
COMMAND_CONFIG, "");
register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command, |