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 */
 

-- 

Reply via email to