This is an automated email from Gerrit. "Tim Hutt <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9535
-- gerrit commit 2418359158b45f8c1edacb0715be89268a85eff6 Author: Tim Hutt <[email protected]> Date: Wed Mar 18 09:41:20 2026 +0000 server: return actual TCP port from $target cget -gdb-port When the port used for a target is 0, a random port is used. Currently there's no way to programmatically get that port, which means most people just scrape stdout which is clearly suboptimal. This change allows you to use `$target cget -gdb-port` to get the actual port. Tested with this command (wrapped to fit in commit message) openocd -c 'adapter driver dummy; gdb_port 0; jtag newtap tap cpu -irlen 5; target create tap.cpu riscv -chain-position tap.cpu; init; echo "Resolved port is [tap.cpu cget -gdb-port]"; shutdown' Change-Id: I29bc2d352c0058f8b6a1c4296345f9ece4fbe03f Signed-off-by: Tim Hutt <[email protected]> diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index f59eb5029e..4c695ca955 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -3906,7 +3906,7 @@ static const struct service_driver gdb_service_driver = { .keep_client_alive_handler = gdb_keep_client_alive, }; -static int gdb_target_start(struct target *target, const char *port) +static int gdb_target_start(struct target *target, const char *port, unsigned short *resolved_tcp_port) { struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service)); if (!gdb_service) { @@ -3922,7 +3922,7 @@ static int gdb_target_start(struct target *target, const char *port) target->gdb_service = gdb_service; int retval = add_service(&gdb_service_driver, port, - target->gdb_max_connections, gdb_service); + target->gdb_max_connections, gdb_service, resolved_tcp_port); if (retval != ERROR_OK) { free(gdb_service); return retval; @@ -3956,7 +3956,7 @@ static int gdb_target_add_one(struct target *target) LOG_TARGET_INFO(target, "gdb port disabled"); return ERROR_OK; } - return gdb_target_start(target, target->gdb_port_override); + return gdb_target_start(target, target->gdb_port_override, &target->gdb_resolved_tcp_port); } if (strcmp(gdb_port_next, "disabled") == 0) { @@ -3964,10 +3964,11 @@ static int gdb_target_add_one(struct target *target) return ERROR_OK; } - int retval = gdb_target_start(target, gdb_port_next); + int retval = gdb_target_start(target, gdb_port_next, &target->gdb_resolved_tcp_port); if (retval == ERROR_OK) { - /* save the port number so can be queried with - * $target_name cget -gdb-port + /* Save the port so can be queried with `$target_name cget -gdb-port`. + * This is actually only used for 'pipe' now because for TCP + * we will use `gdb_resolved_tcp_port`. */ target->gdb_port_override = strdup(gdb_port_next); diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index 466717c468..0a6cafaca8 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -815,7 +815,7 @@ static int ipdbg_start(struct ipdbg_hub *hub, uint16_t port, uint8_t tool) char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH]; snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port); - retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service); + retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service, NULL); if (retval != ERROR_OK) { free(service); return retval; diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c index b44101c3dc..a81255c75f 100644 --- a/src/server/rtt_server.c +++ b/src/server/rtt_server.c @@ -184,7 +184,7 @@ COMMAND_HANDLER(handle_rtt_start_command) service->hello_message[hello_length] = '\n'; service->hello_message[hello_length + 1] = '\0'; } - ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service); + ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service, NULL); if (ret != ERROR_OK) { free(service); diff --git a/src/server/server.c b/src/server/server.c index a48c0dba97..3de9fac0ed 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -204,7 +204,7 @@ static void free_service(struct service *c) } int add_service(const struct service_driver *driver, const char *port, - int max_connections, void *priv) + int max_connections, void *priv, unsigned short *resolved_tcp_port) { struct service *c, **p; struct hostent *hp; @@ -309,9 +309,13 @@ int add_service(const struct service_driver *driver, const char *port, struct sockaddr_in addr_in; addr_in.sin_port = 0; socklen_t addr_in_size = sizeof(addr_in); - if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0) - LOG_INFO("Listening on port %hu for %s connections", - ntohs(addr_in.sin_port), c->name); + if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0) { + unsigned short host_port = ntohs(addr_in.sin_port); + LOG_INFO("Listening on port %u for %s connections", host_port, c->name); + /* If port was '0' this allows us to query what the actual assigned port was. */ + if (resolved_tcp_port) + *resolved_tcp_port = host_port; + } } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); diff --git a/src/server/server.h b/src/server/server.h index 393dba7691..f628746cfe 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -85,7 +85,7 @@ struct service { }; int add_service(const struct service_driver *driver, const char *port, - int max_connections, void *priv); + int max_connections, void *priv, unsigned short *resolved_tcp_port); int remove_service(const char *name, const char *port); int server_host_os_entry(void); diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 929fbee0c7..291ea234d5 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -291,7 +291,7 @@ int tcl_init(void) return ERROR_OK; } - return add_service(&tcl_service_driver, tcl_port, CONNECTION_LIMIT_UNLIMITED, NULL); + return add_service(&tcl_service_driver, tcl_port, CONNECTION_LIMIT_UNLIMITED, NULL, NULL); } bool tcl_is_from_tcl_session(struct command_context *cmd_ctx) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index ea7f38fb88..40e266f1ca 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -958,7 +958,7 @@ int telnet_init(char *banner) telnet_service->banner = banner; int ret = add_service(&telnet_service_driver, telnet_port, CONNECTION_LIMIT_UNLIMITED, - telnet_service); + telnet_service, NULL); if (ret != ERROR_OK) { free(telnet_service); diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 715b1c962c..3b12e84f91 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -736,7 +736,7 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_enable) priv->obj = obj; LOG_INFO("starting trace server for %s on %s", obj->name, &obj->out_filename[1]); retval = add_service(&arm_tpiu_swo_service_driver, &obj->out_filename[1], - CONNECTION_LIMIT_UNLIMITED, priv); + CONNECTION_LIMIT_UNLIMITED, priv, NULL); if (retval != ERROR_OK) { command_print(CMD, "Can't configure trace TCP port %s", &obj->out_filename[1]); free(priv); diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c index 60cbb49834..cb2ac09549 100644 --- a/src/target/openrisc/jsp_server.c +++ b/src/target/openrisc/jsp_server.c @@ -203,7 +203,7 @@ int jsp_init(struct or1k_jtag *jtag_info, char *banner) jsp_service->banner = banner; jsp_service->jtag_info = jtag_info; - int retval = add_service(&jsp_service_driver, jsp_port, 1, jsp_service); + int retval = add_service(&jsp_service_driver, jsp_port, 1, jsp_service, NULL); if (retval != ERROR_OK) free(jsp_service); diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index 345e542c3c..10f15d32d7 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -1943,7 +1943,7 @@ COMMAND_HANDLER(handle_common_semihosting_redirect_command) } int ret = add_service(&semihosting_service_driver, - port, 1, service); + port, 1, service, NULL); if (ret != ERROR_OK) { LOG_ERROR("failed to initialize %s", service->name); diff --git a/src/target/target.c b/src/target/target.c index f766d1da43..376fa8dd9b 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5182,7 +5182,10 @@ static COMMAND_HELPER(target_configure, struct target *target, unsigned int inde } else { if (index != CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; - command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined"); + if (target->gdb_resolved_tcp_port != 0) + command_print(CMD, "%hu", target->gdb_resolved_tcp_port); + else + command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined"); } /* loop for more */ break; @@ -5774,6 +5777,8 @@ COMMAND_HANDLER(handle_target_create) target->gdb_port_override = NULL; target->gdb_max_connections = 1; + target->gdb_resolved_tcp_port = 0; + target->cmd_name = strdup(CMD_ARGV[0]); if (!target->cmd_name) { LOG_ERROR("Out of memory"); diff --git a/src/target/target.h b/src/target/target.h index 2b66dd741c..36054b5f26 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -204,7 +204,14 @@ struct target { /* file-I/O information for host to do syscall */ struct gdb_fileio_info *fileio_info; - char *gdb_port_override; /* target-specific override for gdb_port */ + /* Target-specific override for gdb_port. When the GDB server is started + * for this target, if this is NULL then the value of the global `gdb port` + * setting is used and copied into here. */ + char *gdb_port_override; + + /* If the port is 0 then a random port is used. The actual port that + * is used gets saved here (otherwise this is 0). */ + unsigned short gdb_resolved_tcp_port; int gdb_max_connections; /* max number of simultaneous gdb connections */ --
