aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorAntonio Borneo <borneo.antonio@gmail.com>2022-03-30 23:55:04 +0200
committerAntonio Borneo <borneo.antonio@gmail.com>2022-04-23 09:25:43 +0000
commit5ebb1bdea1dfff9cce430bd17d08e340eea38e03 (patch)
tree3f2cc7319a1d6c1a7acaefa5bdd2c2fdc06b3ea3 /src/server
parentd8c81d72540a9e6a9f59412686332379ece1618f (diff)
downloadriscv-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.c43
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;