Patch attached. 1. The first "stepi/continue" after a connect will return immediately without affecting the state of the target. This allows GDB to sync up to the target state. Nice when wanting to attach GDB to a running target and deciding using GDB monitor commands how to start examining/halting the target.
2. You can explicitly use the "monitor gdb_sync" command to tell OpenOCD to return immediately from the next stepi/continue to sync up GDB to the target state. 3. As before GDB will return garbage register values to allow GDB to be in the "halted" state even if the target is running, powered down or unresponsive, etc. A possible change would be to automatically set the sync flag if *any* monitor command was issued from GDB, but I held back on that one since it seemed a bit too helpful... (gdb) monitor reg pc 0x20000000 pc (/32): 0x20000000 (gdb) print $pc $2 = (void (*)()) 0x18 # Now sync up GDB to target register values! (gdb) monitor gdb_sync # Notice that target state is not affected! (gdb) stepi Program received signal SIGINT, Interrupt. 0x20000000 in ?? () # if we didn't have the gdb_sync command, we would # have crashed when donig a stepi to sync up! (gdb) c Continuing. Sensed nSRST asserted. Program received signal SIGTRAP, Trace/breakpoint trap. 0xe880ffe6 in ?? () On Mon, Sep 21, 2009 at 9:02 PM, Øyvind Harboe <oyvind.har...@zylin.com> wrote: > I'm wondering if it would be a good idea to modify the handling > of GDB halted/running state as follows: > > - do nothing upon attaching GDB to OpenOCD. This gives > the GDB init script more freedom w.r.t. what should happen > when connecting to the target. > - if the target is running and GDB is halted, then OpenOCD > returns "white lies" in the register and memory queries. This > allows users to issue a "monitor halt" or "stepi/continue" command > after attaching to either halt the target or sync up with it. > - When connecting to a halted target, the next stepi/continue > returns immediately, thus allowing the register state to sync > up to the current state of the target without modifying the > state of the target > - if, while GDB is halted, the target state changes behind > GDBs back, then the next stepi/continue returns immediately > to sync up GDB to the current state > > > -- > Øyvind Harboe > Embedded software and hardware consulting services > http://www.zylin.com > -- Øyvind Harboe http://www.zylin.com/zy1000.html ARM7 ARM9 ARM11 XScale Cortex JTAG debugger and flash programmer
### Eclipse Workspace Patch 1.0 #P openocd Index: src/server/gdb_server.h =================================================================== --- src/server/gdb_server.h (revision 2748) +++ src/server/gdb_server.h (working copy) @@ -43,6 +43,10 @@ int closed; int busy; int noack_mode; + bool sync; /* set flag to true if you want the next stepi to return immediately. + allowing GDB to pick up a fresh set of register values from the target + without modifying the target state. */ + } gdb_connection_t; typedef struct gdb_service_s Index: src/server/gdb_server.c =================================================================== --- src/server/gdb_server.c (revision 2748) +++ src/server/gdb_server.c (working copy) @@ -40,6 +40,8 @@ #define _DEBUG_GDB_IO_ #endif +static gdb_connection_t *current_gdb_connection; + static int gdb_breakpoint_override; static enum breakpoint_type gdb_breakpoint_override_type; @@ -750,6 +752,7 @@ gdb_connection->closed = 0; gdb_connection->busy = 0; gdb_connection->noack_mode = 0; + gdb_connection->sync = true; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); @@ -767,30 +770,6 @@ /* register callback to be informed about target events */ target_register_event_callback(gdb_target_callback_event_handler, connection); - /* a gdb session just attached, try to put the target in halt mode. - * - * DANGER!!!! - * - * If the halt fails(e.g. target needs a reset, JTAG communication not - * working, etc.), then the GDB connect will succeed as - * the get_gdb_reg_list() will lie and return a register list with - * dummy values. - * - * This allows GDB monitor commands to be run from a GDB init script to - * initialize the target - * - * Also, since the halt() is asynchronous target connect will be - * instantaneous and thus avoiding annoying timeout problems during - * connect. - */ - target_halt(gdb_service->target); - /* FIX!!!! could extended-remote work better here? - * - * wait a tiny bit for halted state or we just continue. The - * GDB register packet will then contain garbage - */ - target_wait_state(gdb_service->target, TARGET_HALTED, 500); - /* remove the initial ACK from the incoming buffer */ if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK) return retval; @@ -1609,7 +1588,11 @@ /* We want to print all debug output to GDB connection */ log_add_callback(gdb_log_callback, connection); target_call_timer_callbacks_now(); + /* some commands need to know the GDB connection, make note of current + * GDB connection. */ + current_gdb_connection = gdb_connection; command_run_line(cmd_ctx, cmd); + current_gdb_connection = NULL; target_call_timer_callbacks_now(); log_remove_callback(gdb_log_callback, connection); free(cmd); @@ -2107,10 +2090,17 @@ case 'c': case 's': { - if (target->state != TARGET_HALTED) + gdb_connection_t *gdb_con = connection->priv; + bool nostep = (target->state != TARGET_HALTED) || gdb_con->sync; + gdb_con->sync = false; + if (nostep) { - /* If the target isn't in the halted state, then we can't + /* Either the target isn't in the halted state, then we can't * step/continue. This might be early setup, etc. + * + * Or we want to allow GDB to pick up a fresh set of + * register values without modifying the target state. + * */ gdb_sig_halted(connection); } else @@ -2118,7 +2108,6 @@ /* We're running/stepping, in which case we can * forward log output until the target is halted */ - gdb_connection_t *gdb_con = connection->priv; gdb_con->frontend_state = TARGET_RUNNING; log_add_callback(gdb_log_callback, connection); target_call_event_callbacks(target, TARGET_EVENT_GDB_START); @@ -2255,6 +2244,25 @@ return ERROR_OK; } +int handle_gdb_sync_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc != 0) + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (current_gdb_connection == NULL) + { + command_print(cmd_ctx, + "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\""); + return ERROR_FAIL; + } + + current_gdb_connection->sync = true; + + return ERROR_OK; +} + /* daemon configuration command gdb_port */ int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { @@ -2399,6 +2407,8 @@ int gdb_register_commands(command_context_t *command_context) { + register_command(command_context, NULL, "gdb_sync", handle_gdb_sync_command, + COMMAND_ANY, "next stepi will return immediately allowing GDB fetch register state without affecting target state"); register_command(command_context, NULL, "gdb_port", handle_gdb_port_command, COMMAND_ANY, "daemon configuration command gdb_port"); register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
_______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development