Writing registers in other threads appears to work. (#585)
Change-Id: Ie2a8bef5e9aa24fc85e9b6c9093021731c58c3e7 Signed-off-by: Tim Newsome <tim@sifive.com>
This commit is contained in:
parent
50a5971be2
commit
ca49f403ef
|
@ -190,6 +190,7 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, threadid_t thread_id,
|
||||||
struct rtos_reg **reg_list, int *num_regs);
|
struct rtos_reg **reg_list, int *num_regs);
|
||||||
static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id,
|
static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id,
|
||||||
uint32_t reg_num, struct rtos_reg *reg);
|
uint32_t reg_num, struct rtos_reg *reg);
|
||||||
|
static int FreeRTOS_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
||||||
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||||
|
|
||||||
struct rtos_type FreeRTOS_rtos = {
|
struct rtos_type FreeRTOS_rtos = {
|
||||||
|
@ -200,6 +201,7 @@ struct rtos_type FreeRTOS_rtos = {
|
||||||
.update_threads = FreeRTOS_update_threads,
|
.update_threads = FreeRTOS_update_threads,
|
||||||
.get_thread_reg_list = FreeRTOS_get_thread_reg_list,
|
.get_thread_reg_list = FreeRTOS_get_thread_reg_list,
|
||||||
.get_thread_reg = FreeRTOS_get_thread_reg,
|
.get_thread_reg = FreeRTOS_get_thread_reg,
|
||||||
|
.set_reg = FreeRTOS_set_reg,
|
||||||
.get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
|
.get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -585,6 +587,24 @@ static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id,
|
||||||
return rtos_generic_stack_read_reg(rtos->target, stacking_info, stack_ptr, reg_num, reg);
|
return rtos_generic_stack_read_reg(rtos->target, stacking_info, stack_ptr, reg_num, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int FreeRTOS_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("[%" PRId64 "] reg_num=%" PRId32, rtos->current_threadid, reg_num);
|
||||||
|
|
||||||
|
/* Let the caller write registers directly for the current thread. */
|
||||||
|
if (rtos->current_threadid == rtos->current_thread)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
const struct rtos_register_stacking *stacking_info;
|
||||||
|
target_addr_t stack_ptr;
|
||||||
|
if (FreeRTOS_get_stacking_info(rtos, rtos->current_threadid,
|
||||||
|
&stacking_info, &stack_ptr) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
return rtos_generic_stack_write_reg(rtos->target, stacking_info, stack_ptr,
|
||||||
|
reg_num, reg_value);
|
||||||
|
}
|
||||||
|
|
||||||
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
|
@ -653,7 +653,7 @@ int rtos_generic_stack_read_reg(struct target *target,
|
||||||
}
|
}
|
||||||
if (i >= total_count) {
|
if (i >= total_count) {
|
||||||
/* This register is not on the stack. Return error so a caller somewhere
|
/* This register is not on the stack. Return error so a caller somewhere
|
||||||
* will just read the register directly fromt he target. */
|
* will just read the register directly from the target. */
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,6 +680,58 @@ int rtos_generic_stack_read_reg(struct target *target,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtos_generic_stack_write_reg(struct target *target,
|
||||||
|
const struct rtos_register_stacking *stacking,
|
||||||
|
target_addr_t stack_ptr,
|
||||||
|
uint32_t reg_num, uint8_t *reg_value)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("stack_ptr=" TARGET_ADDR_FMT ", reg_num=%d", stack_ptr, reg_num);
|
||||||
|
unsigned total_count = MAX(stacking->total_register_count, stacking->num_output_registers);
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < total_count; i++) {
|
||||||
|
if (stacking->register_offsets[i].number == reg_num)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= total_count) {
|
||||||
|
/* This register is not on the stack. Return error so a caller somewhere
|
||||||
|
* will just read the register directly from the target. */
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct stack_register_offset *offsets = &stacking->register_offsets[i];
|
||||||
|
|
||||||
|
unsigned width_bytes = DIV_ROUND_UP(offsets->width_bits, 8);
|
||||||
|
if (offsets->offset >= 0) {
|
||||||
|
target_addr_t address = stack_ptr;
|
||||||
|
|
||||||
|
if (stacking->stack_growth_direction == 1)
|
||||||
|
address -= stacking->stack_registers_size;
|
||||||
|
|
||||||
|
LOG_DEBUG("write 0x%" PRIx64 " to register %d",
|
||||||
|
buf_get_u64(reg_value, 0, offsets->width_bits), reg_num);
|
||||||
|
if (target_write_buffer(
|
||||||
|
target, address + offsets->offset,
|
||||||
|
width_bytes, reg_value) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
} else if (offsets->offset == -1) {
|
||||||
|
/* This register isn't on the stack, but is listed as one of those. We
|
||||||
|
* read it as 0, and ignore writes. */
|
||||||
|
} else if (offsets->offset == -2) {
|
||||||
|
/* This register requires computation when we "read" it. I'm not sure
|
||||||
|
* how to handle writes. We can't simply return error here because then
|
||||||
|
* the higher level code will end up writing the register in the halted
|
||||||
|
* core, which is definitely not the same as writing it for a thread. */
|
||||||
|
LOG_ERROR("Don't know how to write register %d with offset -2 in a thread.",
|
||||||
|
reg_num);
|
||||||
|
assert(0);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Don't know how to handle offset <2.");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int rtos_try_next(struct target *target)
|
static int rtos_try_next(struct target *target)
|
||||||
{
|
{
|
||||||
struct rtos *os = target->rtos;
|
struct rtos *os = target->rtos;
|
||||||
|
|
|
@ -143,6 +143,10 @@ int rtos_generic_stack_read_reg(struct target *target,
|
||||||
const struct rtos_register_stacking *stacking,
|
const struct rtos_register_stacking *stacking,
|
||||||
target_addr_t stack_ptr,
|
target_addr_t stack_ptr,
|
||||||
uint32_t reg_num, struct rtos_reg *reg);
|
uint32_t reg_num, struct rtos_reg *reg);
|
||||||
|
int rtos_generic_stack_write_reg(struct target *target,
|
||||||
|
const struct rtos_register_stacking *stacking,
|
||||||
|
target_addr_t stack_ptr,
|
||||||
|
uint32_t reg_num, uint8_t *reg_value);
|
||||||
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size);
|
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size);
|
||||||
int rtos_get_gdb_reg(struct connection *connection, int reg_num);
|
int rtos_get_gdb_reg(struct connection *connection, int reg_num);
|
||||||
int rtos_get_gdb_reg_list(struct connection *connection);
|
int rtos_get_gdb_reg_list(struct connection *connection);
|
||||||
|
|
|
@ -2942,6 +2942,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
|
||||||
char sig_reply[128];
|
char sig_reply[128];
|
||||||
|
|
||||||
LOG_DEBUG("fake step thread %"PRIx64, thread_id);
|
LOG_DEBUG("fake step thread %"PRIx64, thread_id);
|
||||||
|
target->rtos->current_threadid = thread_id;
|
||||||
|
|
||||||
sig_reply_len = snprintf(sig_reply, sizeof(sig_reply),
|
sig_reply_len = snprintf(sig_reply, sizeof(sig_reply),
|
||||||
"T05thread:%016"PRIx64";", thread_id);
|
"T05thread:%016"PRIx64";", thread_id);
|
||||||
|
|
Loading…
Reference in New Issue