Add gdb_report_register_access_error command
This replaces the earlier mechanism which would propagate errors only for targets that decided they wanted to. It was suggested by Matthias Welwarsky from the OpenOCD team. Change-Id: Ibe8e97644abb47aff26d74b8280377d42615a4d3
This commit is contained in:
parent
58a2994b00
commit
eeae8c4261
|
@ -126,6 +126,9 @@ static int gdb_flash_program = 1;
|
||||||
* Disabled by default.
|
* Disabled by default.
|
||||||
*/
|
*/
|
||||||
static int gdb_report_data_abort;
|
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
|
/* set if we are sending target descriptions to gdb
|
||||||
* via qXfer:features:read packet */
|
* via qXfer:features:read packet */
|
||||||
|
@ -1174,7 +1177,7 @@ static int gdb_get_registers_packet(struct connection *connection,
|
||||||
for (i = 0; i < reg_list_size; i++) {
|
for (i = 0; i < reg_list_size; i++) {
|
||||||
if (!reg_list[i]->valid) {
|
if (!reg_list[i]->valid) {
|
||||||
retval = reg_list[i]->type->get(reg_list[i]);
|
retval = reg_list[i]->type->get(reg_list[i]);
|
||||||
if (retval != ERROR_OK && target->propagate_register_errors) {
|
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
||||||
LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name);
|
LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name);
|
||||||
free(reg_packet);
|
free(reg_packet);
|
||||||
free(reg_list);
|
free(reg_list);
|
||||||
|
@ -1242,7 +1245,7 @@ static int gdb_set_registers_packet(struct connection *connection,
|
||||||
gdb_target_to_reg(target, packet_p, chars, bin_buf);
|
gdb_target_to_reg(target, packet_p, chars, bin_buf);
|
||||||
|
|
||||||
retval = 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 && target->propagate_register_errors) {
|
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
||||||
LOG_DEBUG("Couldn't set register %s.", reg_list[i]->name);
|
LOG_DEBUG("Couldn't set register %s.", reg_list[i]->name);
|
||||||
free(reg_list);
|
free(reg_list);
|
||||||
free(bin_buf);
|
free(bin_buf);
|
||||||
|
@ -1289,7 +1292,7 @@ static int gdb_get_register_packet(struct connection *connection,
|
||||||
|
|
||||||
if (!reg_list[reg_num]->valid) {
|
if (!reg_list[reg_num]->valid) {
|
||||||
retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
|
retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
|
||||||
if (retval != ERROR_OK && target->propagate_register_errors) {
|
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
||||||
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
|
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
|
||||||
free(reg_list);
|
free(reg_list);
|
||||||
return gdb_error(connection, retval);
|
return gdb_error(connection, retval);
|
||||||
|
@ -1349,7 +1352,7 @@ static int gdb_set_register_packet(struct connection *connection,
|
||||||
gdb_target_to_reg(target, separator + 1, chars, bin_buf);
|
gdb_target_to_reg(target, separator + 1, chars, bin_buf);
|
||||||
|
|
||||||
retval = 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 && target->propagate_register_errors) {
|
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
||||||
LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name);
|
LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name);
|
||||||
free(bin_buf);
|
free(bin_buf);
|
||||||
free(reg_list);
|
free(reg_list);
|
||||||
|
@ -3209,6 +3212,15 @@ COMMAND_HANDLER(handle_gdb_report_data_abort_command)
|
||||||
return ERROR_OK;
|
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 */
|
/* gdb_breakpoint_override */
|
||||||
COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
|
COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
|
||||||
{
|
{
|
||||||
|
@ -3330,6 +3342,13 @@ static const struct command_registration gdb_command_handlers[] = {
|
||||||
.help = "enable or disable reporting data aborts",
|
.help = "enable or disable reporting data aborts",
|
||||||
.usage = "('enable'|'disable')"
|
.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",
|
.name = "gdb_breakpoint_override",
|
||||||
.handler = handle_gdb_breakpoint_override_command,
|
.handler = handle_gdb_breakpoint_override_command,
|
||||||
|
|
|
@ -247,7 +247,6 @@ static int riscv_init_target(struct command_context *cmd_ctx,
|
||||||
struct target *target)
|
struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("riscv_init_target()");
|
LOG_DEBUG("riscv_init_target()");
|
||||||
target->propagate_register_errors = true;
|
|
||||||
target->arch_info = calloc(1, sizeof(riscv_info_t));
|
target->arch_info = calloc(1, sizeof(riscv_info_t));
|
||||||
if (!target->arch_info)
|
if (!target->arch_info)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
|
@ -204,14 +204,6 @@ struct target {
|
||||||
|
|
||||||
/* file-I/O information for host to do syscall */
|
/* file-I/O information for host to do syscall */
|
||||||
struct gdb_fileio_info *fileio_info;
|
struct gdb_fileio_info *fileio_info;
|
||||||
|
|
||||||
/**
|
|
||||||
* When true, send gdb an error result when reading/writing a register
|
|
||||||
* fails. This must be false for some ARM targets (Cortex-M3), where a 'g'
|
|
||||||
* packet results in an attempt to read 'r0', which fails, which causes gdb
|
|
||||||
* to close the connection.
|
|
||||||
*/
|
|
||||||
bool propagate_register_errors;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_list {
|
struct target_list {
|
||||||
|
|
Loading…
Reference in New Issue