diff options
author | Evgeniy Naydanov <evgeniy.naydanov@syntacore.com> | 2023-08-22 16:24:30 +0300 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2023-09-17 12:01:47 +0000 |
commit | 236c54c94a53ff76537a1bf91cfe74a264a2756f (patch) | |
tree | 730b34d2d4ff96f9424bddad60dababbf46b3a83 /src/server/gdb_server.c | |
parent | 51d4996c5b48e2f871e98af982f7627e527e8683 (diff) | |
download | riscv-openocd-236c54c94a53ff76537a1bf91cfe74a264a2756f.zip riscv-openocd-236c54c94a53ff76537a1bf91cfe74a264a2756f.tar.gz riscv-openocd-236c54c94a53ff76537a1bf91cfe74a264a2756f.tar.bz2 |
server/gdb_server.c: support unavailable registers
According to gdb documentation, `g` and `p` packets can report a
register being unavailable by a string of 'x' instead of register's
value.
Change-Id: I8ef279f1357c2e612f5d3290eb0022c1b47d9fa7
Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7876
Reviewed-by: Marek Vrbka <marek.vrbka@codasip.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Anatoly Parshintsev <kupokupokupopo@gmail.com>
Tested-by: jenkins
Diffstat (limited to 'src/server/gdb_server.c')
-rw-r--r-- | src/server/gdb_server.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 4a4ea53..497f62c 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1207,6 +1207,27 @@ static void gdb_target_to_reg(struct target *target, } } +/* get register value if needed and fill the buffer accordingly */ +static int gdb_get_reg_value_as_str(struct target *target, char *tstr, struct reg *reg) +{ + int retval = ERROR_OK; + + if (!reg->valid) + retval = reg->type->get(reg); + + const unsigned int len = DIV_ROUND_UP(reg->size, 8) * 2; + switch (retval) { + case ERROR_OK: + gdb_str_to_target(target, tstr, reg); + return ERROR_OK; + case ERROR_TARGET_RESOURCE_NOT_AVAILABLE: + memset(tstr, 'x', len); + tstr[len] = '\0'; + return ERROR_OK; + } + return ERROR_FAIL; +} + static int gdb_get_registers_packet(struct connection *connection, char const *packet, int packet_size) { @@ -1248,16 +1269,11 @@ static int gdb_get_registers_packet(struct connection *connection, for (i = 0; i < reg_list_size; i++) { if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) continue; - if (!reg_list[i]->valid) { - retval = reg_list[i]->type->get(reg_list[i]); - if (retval != ERROR_OK && gdb_report_register_access_error) { - LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name); - free(reg_packet); - free(reg_list); - return gdb_error(connection, retval); - } + if (gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]) != ERROR_OK) { + free(reg_packet); + free(reg_list); + return gdb_error(connection, retval); } - gdb_str_to_target(target, reg_packet_p, reg_list[i]); reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1369,18 +1385,13 @@ static int gdb_get_register_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - if (!reg_list[reg_num]->valid) { - retval = reg_list[reg_num]->type->get(reg_list[reg_num]); - if (retval != ERROR_OK && gdb_report_register_access_error) { - LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name); - free(reg_list); - return gdb_error(connection, retval); - } - } - reg_packet = calloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1, 1); /* plus one for string termination null */ - gdb_str_to_target(target, reg_packet, reg_list[reg_num]); + if (gdb_get_reg_value_as_str(target, reg_packet, reg_list[reg_num]) != ERROR_OK) { + free(reg_packet); + free(reg_list); + return gdb_error(connection, retval); + } gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); |