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
This commit is contained in:
Tim Newsome 2018-03-06 14:10:04 -08:00 committed by Matthias Welwarsky
parent 0dba1815e6
commit 2e2bb14b27
2 changed files with 57 additions and 6 deletions

View File

@ -2200,6 +2200,13 @@ The default behaviour is @option{disable};
use @option{enable} see these errors reported.
@end deffn
@deffn {Config Command} gdb_report_register_access_error (@option{enable}|@option{disable})
Specifies whether register accesses requested by GDB register read/write
packets report errors or not.
The default behaviour is @option{disable};
use @option{enable} see these errors reported.
@end deffn
@deffn {Config Command} gdb_target_description (@option{enable}|@option{disable})
Set to @option{enable} to cause OpenOCD to send the target descriptions to gdb via qXfer:features:read packet.
The default behaviour is @option{enable}.

View File

@ -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)
{
@ -3589,6 +3626,13 @@ static const struct command_registration gdb_command_handlers[] = {
.help = "enable or disable reporting data aborts",
.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,