From b5964191f0d2fc3ace607af001df3d57cbfbaf2b Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Mon, 1 May 2017 14:38:35 -0500 Subject: [PATCH] register: support non-existent registers This patch fixes a number of bugs caused by incomplete support for non-existent registers. This is needed for targets that provide optional registers or non-linear register numbers. Change-Id: I216196e0051f28887a2c3da410959382369eed80 Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/4113 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/server/gdb_server.c | 7 ++++++- src/target/register.c | 4 ++++ src/target/target.c | 15 +++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index a45127360..ee9fc1c97 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1179,8 +1179,11 @@ static int gdb_get_registers_packet(struct connection *connection, if (retval != ERROR_OK) return gdb_error(connection, retval); - for (i = 0; i < reg_list_size; i++) + for (i = 0; i < reg_list_size; i++) { + if (reg_list[i] == NULL || reg_list[i]->exist == false) + continue; reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; + } assert(reg_packet_size > 0); @@ -1191,6 +1194,8 @@ 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] == NULL || reg_list[i]->exist == false) + continue; if (!reg_list[i]->valid) { retval = reg_list[i]->type->get(reg_list[i]); if (retval != ERROR_OK && gdb_report_register_access_error) { diff --git a/src/target/register.c b/src/target/register.c index 1d63e12f7..850641448 100644 --- a/src/target/register.c +++ b/src/target/register.c @@ -44,6 +44,8 @@ struct reg *register_get_by_name(struct reg_cache *first, while (cache) { for (i = 0; i < cache->num_regs; i++) { + if (cache->reg_list[i].exist == false) + continue; if (strcmp(cache->reg_list[i].name, name) == 0) return &(cache->reg_list[i]); } @@ -84,6 +86,8 @@ void register_cache_invalidate(struct reg_cache *cache) struct reg *reg = cache->reg_list; for (unsigned n = cache->num_regs; n != 0; n--, reg++) { + if (reg->exist == false) + continue; reg->valid = 0; reg->dirty = 0; } diff --git a/src/target/target.c b/src/target/target.c index 478c39d1b..3aaebcd49 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2804,6 +2804,8 @@ COMMAND_HANDLER(handle_reg_command) for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { + if (reg->exist == false) + continue; /* only print cached values if they are valid */ if (reg->valid) { value = buf_to_str(reg->value, @@ -2857,14 +2859,15 @@ COMMAND_HANDLER(handle_reg_command) /* access a single register by its name */ reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); - if (!reg) { - command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); - return ERROR_OK; - } + if (!reg) + goto not_found; } assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + if (!reg->exist) + goto not_found; + /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { @@ -2898,6 +2901,10 @@ COMMAND_HANDLER(handle_reg_command) } return ERROR_COMMAND_SYNTAX_ERROR; + +not_found: + command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); + return ERROR_OK; } COMMAND_HANDLER(handle_poll_command)