gdb_server: allow multiple GDB connections to selected targets

The default way of working is to have a single GDB attached to one
target, so OpenOCD accepts only one connection to the GDB port of
each targets and rejects any further connection.

There are some barely safe use cases in which it could get useful
having a second GDB connection to the same target.
One such use case is while using GDB as a 'non-intrusive memory
inspector', as explained in the OpenOCD documentation.
One GDB can be left running an infinite loop to dump some memory
area, or even analysing the content, while keeping a second GDB
ready for user interaction or spot memory check.

Add a target configure option to specify the maximum number of GDB
connections allowed for that target, keeping the default to 1.

Change-Id: I4985a602e61588df0b527d2f2aa5b955c93e125e
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5865
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
This commit is contained in:
Antonio Borneo 2020-10-15 14:45:27 +02:00
parent 360b2c2701
commit e2e8a5f467
4 changed files with 40 additions and 5 deletions

View File

@ -4694,6 +4694,11 @@ possible values of the parameter @var{number}, which are not only numeric values
Use this option to override, for this target only, the global parameter set with
command @command{gdb_port}.
@xref{gdb_port,,command gdb_port}.
@item @code{-gdb-max-connections} @var{number} -- EXPERIMENTAL: set the maximum
number of GDB connections that are allowed for the target. Default is 1.
A negative value for @var{number} means unlimited connections.
See @xref{gdbmeminspect,,Using GDB as a non-intrusive memory inspector}.
@end itemize
@end deffn
@ -10606,7 +10611,13 @@ of a running target. Do not use GDB commands @command{continue},
and GDB would require stopping the target to get the prompt back.
Do not use this mode under an IDE like Eclipse as it caches values of
previously shown varibles.
previously shown variables.
It's also possible to connect more than one GDB to the same target by the
target's configuration option @code{-gdb-max-connections}. This allows, for
example, one GDB to run a script that continuously polls a set of variables
while other GDB can be used interactively. Be extremely careful in this case,
because the two GDB can easily get out-of-sync.
@section RTOS Support
@cindex RTOS Support

View File

@ -3508,7 +3508,7 @@ static int gdb_target_start(struct target *target, const char *port)
target->gdb_service = gdb_service;
ret = add_service("gdb",
port, 1, &gdb_new_connection, &gdb_input,
port, target->gdb_max_connections, &gdb_new_connection, &gdb_input,
&gdb_connection_closed, gdb_service);
/* initialize all targets gdb service with the same pointer */
{

View File

@ -1263,10 +1263,10 @@ int target_get_gdb_reg_list_noread(struct target *target,
bool target_supports_gdb_connection(struct target *target)
{
/*
* based on current code, we can simply exclude all the targets that
* don't provide get_gdb_reg_list; this could change with new targets.
* exclude all the targets that don't provide get_gdb_reg_list
* or that have explicit gdb_max_connection == 0
*/
return !!target->type->get_gdb_reg_list;
return !!target->type->get_gdb_reg_list && !!target->gdb_max_connections;
}
int target_step(struct target *target,
@ -4652,6 +4652,7 @@ enum target_cfg_param {
TCFG_RTOS,
TCFG_DEFER_EXAMINE,
TCFG_GDB_PORT,
TCFG_GDB_MAX_CONNECTIONS,
};
static Jim_Nvp nvp_config_opts[] = {
@ -4668,6 +4669,7 @@ static Jim_Nvp nvp_config_opts[] = {
{ .name = "-rtos", .value = TCFG_RTOS },
{ .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE },
{ .name = "-gdb-port", .value = TCFG_GDB_PORT },
{ .name = "-gdb-max-connections", .value = TCFG_GDB_MAX_CONNECTIONS },
{ .name = NULL, .value = -1 }
};
@ -4975,6 +4977,25 @@ no_params:
Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1);
/* loop for more */
break;
case TCFG_GDB_MAX_CONNECTIONS:
if (goi->isconfigure) {
struct command_context *cmd_ctx = current_command_context(goi->interp);
if (cmd_ctx->mode != COMMAND_CONFIG) {
Jim_SetResultString(goi->interp, "-gdb-max-conenctions must be configured before 'init'", -1);
return JIM_ERR;
}
e = Jim_GetOpt_Wide(goi, &w);
if (e != JIM_OK)
return e;
target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w;
} else {
if (goi->argc != 0)
goto no_params;
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections));
break;
}
} /* while (goi->argc) */
@ -5555,6 +5576,7 @@ static int target_create(Jim_GetOptInfo *goi)
target->rtos_auto_detect = false;
target->gdb_port_override = NULL;
target->gdb_max_connections = 1;
/* Do the rest as "configure" options */
goi->isconfigure = 1;

View File

@ -211,6 +211,8 @@ struct target {
char *gdb_port_override; /* target-specific override for gdb_port */
int gdb_max_connections; /* max number of simultaneous gdb connections */
/* The semihosting information, extracted from the target. */
struct semihosting *semihosting;
};