diff options
author | Tim Newsome <tim@sifive.com> | 2018-03-06 14:10:04 -0800 |
---|---|---|
committer | Matthias Welwarsky <matthias@welwarsky.de> | 2018-04-07 20:31:14 +0100 |
commit | 2e2bb14b276f5bd973308dcfabd1b8018e187243 (patch) | |
tree | 827cdd921636cd329b3ad723ede43ce3ccf51a99 /src/server | |
parent | 0dba1815e6362cc08e983f8f09af0224ad5ae693 (diff) | |
download | riscv-openocd-2e2bb14b276f5bd973308dcfabd1b8018e187243.zip riscv-openocd-2e2bb14b276f5bd973308dcfabd1b8018e187243.tar.gz riscv-openocd-2e2bb14b276f5bd973308dcfabd1b8018e187243.tar.bz2 |
Add gdb_report_register_access_error command
With this option enabled (it's disabled by default) errors accessing
registers are returned to gdb. Otherwise they are ignored and success is
reported to gdb. (This is the current behavior.)
We want this for RISC-V, but there's still some cleanup that needs to be
done before that can be upstreamed.
Signed-off-by: Tim Newsome <tim@sifive.com>
Change-Id: I7e56109ea52d18b780c14a07fb35f9e6e8979da4
Reviewed-on: http://openocd.zylin.com/4452
Reviewed-by: Steven Stallion <sstallion@gmail.com>
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
Tested-by: jenkins
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/gdb_server.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 428547b..a3783af 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -130,6 +130,9 @@ static int gdb_flash_program = 1; * Disabled by default. */ static int gdb_report_data_abort; +/* If set, errors when accessing registers are reported to gdb. Disabled by + * default. */ +static int gdb_report_register_access_error; /* set if we are sending target descriptions to gdb * via qXfer:features:read packet */ @@ -1187,8 +1190,15 @@ static int gdb_get_registers_packet(struct connection *connection, reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i]->valid) - reg_list[i]->type->get(reg_list[i]); + 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); + } + } gdb_str_to_target(target, reg_packet_p, reg_list[i]); reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1249,7 +1259,13 @@ static int gdb_set_registers_packet(struct connection *connection, bin_buf = malloc(DIV_ROUND_UP(reg_list[i]->size, 8)); gdb_target_to_reg(target, packet_p, chars, bin_buf); - reg_list[i]->type->set(reg_list[i], bin_buf); + retval = reg_list[i]->type->set(reg_list[i], bin_buf); + if (retval != ERROR_OK && gdb_report_register_access_error) { + LOG_DEBUG("Couldn't set register %s.", reg_list[i]->name); + free(reg_list); + free(bin_buf); + return gdb_error(connection, retval); + } /* advance packet pointer */ packet_p += chars; @@ -1289,8 +1305,14 @@ static int gdb_get_register_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - if (!reg_list[reg_num]->valid) - reg_list[reg_num]->type->get(reg_list[reg_num]); + 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 = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1); /* plus one for string termination null */ @@ -1344,7 +1366,13 @@ static int gdb_set_register_packet(struct connection *connection, gdb_target_to_reg(target, separator + 1, chars, bin_buf); - reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); + retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); + if (retval != ERROR_OK && gdb_report_register_access_error) { + LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name); + free(bin_buf); + free(reg_list); + return gdb_error(connection, retval); + } gdb_put_packet(connection, "OK", 2); @@ -3468,6 +3496,15 @@ COMMAND_HANDLER(handle_gdb_report_data_abort_command) return ERROR_OK; } +COMMAND_HANDLER(handle_gdb_report_register_access_error) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_report_register_access_error); + return ERROR_OK; +} + /* gdb_breakpoint_override */ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) { @@ -3590,6 +3627,13 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "('enable'|'disable')" }, { + .name = "gdb_report_register_access_error", + .handler = handle_gdb_report_register_access_error, + .mode = COMMAND_CONFIG, + .help = "enable or disable reporting register access errors", + .usage = "('enable'|'disable')" + }, + { .name = "gdb_breakpoint_override", .handler = handle_gdb_breakpoint_override_command, .mode = COMMAND_ANY, |