Search
lxdream.org :: lxdream :: r1271:3edc4bdd7c0b
lxdream 0.9.1
released Jun 29
Download Now
changeset1271:3edc4bdd7c0b
parent1270:65fd19c07e2e
child1272:0b947d924029
authornkeynes
dateThu Mar 15 08:26:06 2012 +1000 (9 years ago)
GDB: Support ^C interruption from GDB
- postpone dreamcast_run() until after the IO callback returns (callback
won't be called again until the callback returns, so blocks all input)
- generate stop notifications when the DC stops, regardless of where the
stop originates.
src/gdbserver.c
1.1 --- a/src/gdbserver.c Thu Mar 15 08:21:22 2012 +1000
1.2 +++ b/src/gdbserver.c Thu Mar 15 08:26:06 2012 +1000
1.3 @@ -26,9 +26,11 @@
1.4 #include <glib.h>
1.5 #include <arpa/inet.h>
1.6 #include "lxdream.h"
1.7 +#include "dream.h"
1.8 #include "dreamcast.h"
1.9 #include "ioutil.h"
1.10 #include "cpu.h"
1.11 +#include "gui.h"
1.12
1.13 #define DEFAULT_BUFFER_SIZE 1024
1.14 #define BUFFER_SIZE_MARGIN 32
1.15 @@ -50,9 +52,12 @@
1.16 int buf_posn;
1.17 };
1.18
1.19 +static GList *gdb_server_conn_list = NULL;
1.20 +
1.21 void gdb_server_free( gpointer data )
1.22 {
1.23 struct gdb_server *server = (struct gdb_server *)data;
1.24 + gdb_server_conn_list = g_list_remove(gdb_server_conn_list, server);
1.25 free((char *)server->peer_name);
1.26 free(server->buf);
1.27 free(data);
1.28 @@ -209,8 +214,7 @@
1.29 gdb_send_frame( server, "S05", 3 );
1.30 break;
1.31 case 'c': /* Continue */
1.32 - dreamcast_run();
1.33 - gdb_send_frame( server, "S05", 3 );
1.34 + gui_do_later(dreamcast_run);
1.35 break;
1.36 case 'g': /* Read all general registers */
1.37 gdb_print_registers( server, buf, sizeof(buf), 0, server->cpu->num_gpr_regs );
1.38 @@ -422,6 +426,10 @@
1.39 continue;
1.40 } else if( server->buf[i] == '-' ) {
1.41 /* Request retransmit */
1.42 + } else if( server->buf[i] == '\003' ) { /* Control-C */
1.43 + if( dreamcast_is_running() ) {
1.44 + dreamcast_stop();
1.45 + }
1.46 } /* Anything else is noise */
1.47 } else if( server->buf[i] == '#' ) {
1.48 frame_len = i - frame_start - 1;
1.49 @@ -496,11 +504,33 @@
1.50 chan_serv->buf_size = 1024;
1.51 chan_serv->buf_posn = 0;
1.52 io_register_tcp_listener( conn_fd, gdb_server_data_callback, chan_serv, gdb_server_free );
1.53 + gdb_server_conn_list = g_list_append(gdb_server_conn_list, chan_serv);
1.54 INFO( "GDB connected from %s", chan_serv->peer_name );
1.55 }
1.56 return TRUE;
1.57 }
1.58
1.59 +void gdb_server_notify_stopped( struct gdb_server *server )
1.60 +{
1.61 + gdb_send_frame( server, "S05", 3 );
1.62 +}
1.63 +
1.64 +/**
1.65 + * stop handler to generate notifications to all connected clients
1.66 + */
1.67 +void gdb_server_on_stop()
1.68 +{
1.69 + GList *ptr;
1.70 + for( ptr = gdb_server_conn_list; ptr != NULL; ptr = ptr->next ) {
1.71 + gdb_server_notify_stopped( (struct gdb_server *)ptr->data );
1.72 + }
1.73 +}
1.74 +
1.75 +static gboolean module_registered = FALSE;
1.76 +static struct dreamcast_module gdb_server_module = {
1.77 + "gdbserver", NULL, NULL, NULL, NULL, gdb_server_on_stop, NULL, NULL };
1.78 +
1.79 +
1.80 /**
1.81 * Bind a network port for a GDB remote server for the specified cpu. The
1.82 * port is registered for the system network callback.
1.83 @@ -514,6 +544,11 @@
1.84 */
1.85 gboolean gdb_init_server( const char *interface, int port, cpu_desc_t cpu, gboolean mmu )
1.86 {
1.87 + if( !module_registered ) {
1.88 + dreamcast_register_module( &gdb_server_module );
1.89 + module_registered = TRUE;
1.90 + }
1.91 +
1.92 int fd = io_create_server_socket( interface, port );
1.93 if( fd == -1 ) {
1.94 return FALSE;
.