gdb_server, rtos: Fine-grained RTOS register access
1. Add get_thread_reg() to rtos. It's used in rtos_get_gdb_reg() to read the value of a single register, instead of reading all register values by calling get_thread_reg_list(). 2. Add set_reg() to rtos. gdb_server uses this to change a single register value for a specific thread. 3. Add target_get_gdb_reg_list_noread() so it's possible for gdb to get a list of registers without attempting to read their contents. The clang static checker doesn't find any new problems with this change. Change-Id: I77f792d1238cb015b91527ca8cb99593ccc8870e Signed-off-by: Tim Newsome <tim@sifive.com> Reviewed-on: http://openocd.zylin.com/5114 Tested-by: jenkins Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
This commit is contained in:
committed by
Andreas Fritiofson
parent
16496488d1
commit
0819541366
+37
-9
@@ -462,6 +462,7 @@ static int rtos_put_gdb_reg_list(struct connection *connection,
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** Look through all registers to find this register. */
|
||||
int rtos_get_gdb_reg(struct connection *connection, int reg_num)
|
||||
{
|
||||
struct target *target = get_target_from_connection(connection);
|
||||
@@ -473,19 +474,31 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num)
|
||||
struct rtos_reg *reg_list;
|
||||
int num_regs;
|
||||
|
||||
LOG_DEBUG("RTOS: getting register %d for thread 0x%" PRIx64
|
||||
", target->rtos->current_thread=0x%" PRIx64 "\r\n",
|
||||
LOG_DEBUG("getting register %d for thread 0x%" PRIx64
|
||||
", target->rtos->current_thread=0x%" PRIx64,
|
||||
reg_num,
|
||||
current_threadid,
|
||||
target->rtos->current_thread);
|
||||
|
||||
int retval = target->rtos->type->get_thread_reg_list(target->rtos,
|
||||
current_threadid,
|
||||
®_list,
|
||||
&num_regs);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("RTOS: failed to get register list");
|
||||
return retval;
|
||||
int retval;
|
||||
if (target->rtos->type->get_thread_reg) {
|
||||
reg_list = calloc(1, sizeof(*reg_list));
|
||||
num_regs = 1;
|
||||
retval = target->rtos->type->get_thread_reg(target->rtos,
|
||||
current_threadid, reg_num, ®_list[0]);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("RTOS: failed to get register %d", reg_num);
|
||||
return retval;
|
||||
}
|
||||
} else {
|
||||
retval = target->rtos->type->get_thread_reg_list(target->rtos,
|
||||
current_threadid,
|
||||
®_list,
|
||||
&num_regs);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("RTOS: failed to get register list");
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_regs; ++i) {
|
||||
@@ -501,6 +514,7 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/** Return a list of general registers. */
|
||||
int rtos_get_gdb_reg_list(struct connection *connection)
|
||||
{
|
||||
struct target *target = get_target_from_connection(connection);
|
||||
@@ -534,6 +548,20 @@ int rtos_get_gdb_reg_list(struct connection *connection)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int rtos_set_reg(struct connection *connection, int reg_num,
|
||||
uint8_t *reg_value)
|
||||
{
|
||||
struct target *target = get_target_from_connection(connection);
|
||||
int64_t current_threadid = target->rtos->current_threadid;
|
||||
if ((target->rtos != NULL) &&
|
||||
(target->rtos->type->set_reg != NULL) &&
|
||||
(current_threadid != -1) &&
|
||||
(current_threadid != 0)) {
|
||||
return target->rtos->type->set_reg(target->rtos, reg_num, reg_value);
|
||||
}
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int rtos_generic_stack_read(struct target *target,
|
||||
const struct rtos_register_stacking *stacking,
|
||||
int64_t stack_ptr,
|
||||
|
||||
Reference in New Issue
Block a user