aboutsummaryrefslogtreecommitdiff
path: root/src/rtos/rtos.c
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2019-04-08 16:42:48 -0700
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>2019-08-28 08:07:37 +0100
commit081954136681b26ad30db9b4cc40cb360f47602c (patch)
treeb154e83ef45f87aab59ad6bb6dd56bc47ec709fa /src/rtos/rtos.c
parent16496488d10fc9f6c340b81446a85eef2c95ce00 (diff)
downloadriscv-openocd-081954136681b26ad30db9b4cc40cb360f47602c.zip
riscv-openocd-081954136681b26ad30db9b4cc40cb360f47602c.tar.gz
riscv-openocd-081954136681b26ad30db9b4cc40cb360f47602c.tar.bz2
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>
Diffstat (limited to 'src/rtos/rtos.c')
-rw-r--r--src/rtos/rtos.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index 20e875d..002d7b5 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -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,
- &reg_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, &reg_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,
+ &reg_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,