Skip to content

Commit

Permalink
server/gdb_server.c: support unavailable registers
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-on: https://review.openocd.org/c/openocd/+/7876
Reviewed-by: Marek Vrbka <[email protected]>
Reviewed-by: Antonio Borneo <[email protected]>
Reviewed-by: Anatoly Parshintsev <[email protected]>
Tested-by: jenkins
  • Loading branch information
en-sc authored and borneoa committed Sep 17, 2023
1 parent 51d4996 commit 236c54c
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions src/server/gdb_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 236c54c

Please sign in to comment.