diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2022-03-30 23:55:04 +0200 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2022-04-23 09:25:43 +0000 |
commit | 5ebb1bdea1dfff9cce430bd17d08e340eea38e03 (patch) | |
tree | 3f2cc7319a1d6c1a7acaefa5bdd2c2fdc06b3ea3 /src/server | |
parent | d8c81d72540a9e6a9f59412686332379ece1618f (diff) | |
download | riscv-openocd-5ebb1bdea1dfff9cce430bd17d08e340eea38e03.zip riscv-openocd-5ebb1bdea1dfff9cce430bd17d08e340eea38e03.tar.gz riscv-openocd-5ebb1bdea1dfff9cce430bd17d08e340eea38e03.tar.bz2 |
server/gdb: fix return of gdb remote monitor command
Current implementation for gdb remote monitor command uses the
command_run_line() to execute the command.
While command_run_line() has several advantages, it unfortunately
hides the error codes and outputs the result of the command
through LOG_USER(), which is not what gdb requires. See 'qRcmd' in
https://sourceware.org/gdb/onlinedocs/gdb/General-Query-Packets.html
Replace command_run_line() with Jim_EvalObj() and parse the output
to provide the proper result to gdb.
Can be tested by defining in OpenOCD:
proc a {} {return hello}
proc b {} {return -code 4}
proc c {} {return -code 4 "This is an error!"}
then by executing in gdb console:
monitor a
monitor b
monitor c
monitor foo
Change-Id: I1b85554d59221560e97861a499e16764e70c1172
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reported-by: Torbjorn Svensson <torbjorn.svensson@st.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6886
Tested-by: jenkins
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/gdb_server.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 82c8ce9..fcc87fb 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2761,11 +2761,52 @@ static int gdb_query_packet(struct connection *connection, /* 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); + struct target *saved_target_override = cmd_ctx->current_target_override; + cmd_ctx->current_target_override = target; + + int retval = Jim_EvalObj(cmd_ctx->interp, Jim_NewStringObj(cmd_ctx->interp, cmd, -1)); + + cmd_ctx->current_target_override = saved_target_override; current_gdb_connection = NULL; target_call_timer_callbacks_now(); gdb_connection->output_flag = GDB_OUTPUT_NO; free(cmd); + if (retval == JIM_RETURN) + retval = cmd_ctx->interp->returnCode; + int lenmsg; + const char *cretmsg = Jim_GetString(Jim_GetResult(cmd_ctx->interp), &lenmsg); + char *retmsg; + if (lenmsg && cretmsg[lenmsg - 1] != '\n') { + retmsg = alloc_printf("%s\n", cretmsg); + lenmsg++; + } else { + retmsg = strdup(cretmsg); + } + if (!retmsg) + return ERROR_GDB_BUFFER_TOO_SMALL; + + if (retval == JIM_OK) { + if (lenmsg) { + char *hex_buffer = malloc(lenmsg * 2 + 1); + if (!hex_buffer) { + free(retmsg); + return ERROR_GDB_BUFFER_TOO_SMALL; + } + + size_t pkt_len = hexify(hex_buffer, (const uint8_t *)retmsg, lenmsg, + lenmsg * 2 + 1); + gdb_put_packet(connection, hex_buffer, pkt_len); + free(hex_buffer); + } else { + gdb_put_packet(connection, "OK", 2); + } + } else { + if (lenmsg) + gdb_output_con(connection, retmsg); + gdb_send_error(connection, retval); + } + free(retmsg); + return ERROR_OK; } gdb_put_packet(connection, "OK", 2); return ERROR_OK; |