extern struct rtos_type ThreadX_rtos;
extern struct rtos_type eCos_rtos;
extern struct rtos_type Linux_os;
-extern struct rtos_type ChibiOS_rtos;
+extern struct rtos_type chibios_rtos;
+extern struct rtos_type chromium_ec_rtos;
extern struct rtos_type embKernel_rtos;
extern struct rtos_type mqx_rtos;
extern struct rtos_type uCOS_III_rtos;
extern struct rtos_type nuttx_rtos;
+extern struct rtos_type hwthread_rtos;
+extern struct rtos_type riot_rtos;
+extern struct rtos_type zephyr_rtos;
static struct rtos_type *rtos_types[] = {
&ThreadX_rtos,
&FreeRTOS_rtos,
&eCos_rtos,
&Linux_os,
- &ChibiOS_rtos,
+ &chibios_rtos,
+ &chromium_ec_rtos,
&embKernel_rtos,
&mqx_rtos,
&uCOS_III_rtos,
&nuttx_rtos,
+ &riot_rtos,
+ &zephyr_rtos,
+ /* keep this as last, as it always matches with rtos auto */
+ &hwthread_rtos,
NULL
};
+static int rtos_try_next(struct target *target);
+
int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
int rtos_smp_init(struct target *target)
if (!target->rtos)
return;
- if (target->rtos->symbols)
- free(target->rtos->symbols);
-
+ free(target->rtos->symbols);
free(target->rtos);
target->rtos = NULL;
}
{
int x;
const char *cp;
- struct Jim_Obj *res;
+ Jim_Obj *res;
int e;
if (!goi->isconfigure && goi->argc != 0) {
return JIM_ERR;
}
+void rtos_destroy(struct target *target)
+{
+ os_free(target);
+}
+
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
{
struct target *target = get_target_from_connection(connection);
return target->rtos->gdb_thread_packet(connection, packet, packet_size);
}
-static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
+static struct symbol_table_elem *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
{
- symbol_table_elem_t *s;
+ struct symbol_table_elem *s;
if (!os->symbols)
os->type->get_symbol_list_to_lookup(&os->symbols);
* if 'symbol' is not declared optional */
static bool is_symbol_mandatory(const struct rtos *os, const char *symbol)
{
- for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) {
+ for (struct symbol_table_elem *s = os->symbols; s->symbol_name; ++s) {
if (!strcmp(s->symbol_name, symbol))
return !s->optional;
}
int rtos_detected = 0;
uint64_t addr = 0;
size_t reply_len;
- char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = "";
- symbol_table_elem_t *next_sym = NULL;
+ char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
+ struct symbol_table_elem *next_sym = NULL;
struct target *target = get_target_from_connection(connection);
struct rtos *os = target->rtos;
return GDB_THREAD_PACKET_NOT_CONSUMED;
}
+static int rtos_put_gdb_reg_list(struct connection *connection,
+ struct rtos_reg *reg_list, int num_regs)
+{
+ size_t num_bytes = 1; /* NUL */
+ for (int i = 0; i < num_regs; ++i)
+ num_bytes += DIV_ROUND_UP(reg_list[i].size, 8) * 2;
+
+ char *hex = malloc(num_bytes);
+ char *hex_p = hex;
+
+ for (int i = 0; i < num_regs; ++i) {
+ size_t count = DIV_ROUND_UP(reg_list[i].size, 8);
+ size_t n = hexify(hex_p, reg_list[i].value, count, num_bytes);
+ hex_p += n;
+ num_bytes -= n;
+ }
+
+ gdb_put_packet(connection, hex, strlen(hex));
+ free(hex);
+
+ 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);
+ int64_t current_threadid = target->rtos->current_threadid;
+ if ((target->rtos != NULL) && (current_threadid != -1) &&
+ (current_threadid != 0) &&
+ ((current_threadid != target->rtos->current_thread) ||
+ (target->smp))) { /* in smp several current thread are possible */
+ struct rtos_reg *reg_list;
+ int num_regs;
+
+ 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;
+ 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) {
+ if (reg_list[i].number == (uint32_t)reg_num) {
+ rtos_put_gdb_reg_list(connection, reg_list + i, 1);
+ free(reg_list);
+ return ERROR_OK;
+ }
+ }
+
+ free(reg_list);
+ }
+ 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);
(current_threadid != 0) &&
((current_threadid != target->rtos->current_thread) ||
(target->smp))) { /* in smp several current thread are possible */
- char *hex_reg_list;
+ struct rtos_reg *reg_list;
+ int num_regs;
LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64
", target->rtos->current_thread=0x%" PRIx64 "\r\n",
int retval = target->rtos->type->get_thread_reg_list(target->rtos,
current_threadid,
- &hex_reg_list);
+ ®_list,
+ &num_regs);
if (retval != ERROR_OK) {
LOG_ERROR("RTOS: failed to get register list");
return retval;
}
- if (hex_reg_list != NULL) {
- gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
- free(hex_reg_list);
- return ERROR_OK;
- }
+ rtos_put_gdb_reg_list(connection, reg_list, num_regs);
+ free(reg_list);
+
+ return ERROR_OK;
+ }
+ 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,
- char **hex_reg_list)
+ struct rtos_reg **reg_list,
+ int *num_regs)
{
- int list_size = 0;
- char *tmp_str_ptr;
- int64_t new_stack_ptr;
- int i;
int retval;
if (stack_ptr == 0) {
LOG_OUTPUT("%02X", stack_data[i]);
LOG_OUTPUT("\r\n");
#endif
- for (i = 0; i < stacking->num_output_registers; i++)
- list_size += stacking->register_offsets[i].width_bits/8;
- *hex_reg_list = malloc(list_size*2 + 1);
- tmp_str_ptr = *hex_reg_list;
+
+ int64_t new_stack_ptr;
if (stacking->calculate_process_stack != NULL) {
new_stack_ptr = stacking->calculate_process_stack(target,
stack_data, stacking, stack_ptr);
new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
stacking->stack_registers_size;
}
- for (i = 0; i < stacking->num_output_registers; i++) {
- int j;
- for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) {
- if (stacking->register_offsets[i].offset == -1)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0);
- else if (stacking->register_offsets[i].offset == -2)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
- ((uint8_t *)&new_stack_ptr)[j]);
- else
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
- stack_data[stacking->register_offsets[i].offset + j]);
- }
+
+ *reg_list = calloc(stacking->num_output_registers, sizeof(struct rtos_reg));
+ *num_regs = stacking->num_output_registers;
+
+ for (int i = 0; i < stacking->num_output_registers; ++i) {
+ (*reg_list)[i].number = stacking->register_offsets[i].number;
+ (*reg_list)[i].size = stacking->register_offsets[i].width_bits;
+
+ int offset = stacking->register_offsets[i].offset;
+ if (offset == -2)
+ buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].size);
+ else if (offset != -1)
+ buf_cpy(stack_data + offset, (*reg_list)[i].value, (*reg_list)[i].size);
}
+
free(stack_data);
/* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
return ERROR_OK;
}
-int rtos_try_next(struct target *target)
+static int rtos_try_next(struct target *target)
{
struct rtos *os = target->rtos;
struct rtos_type **type = rtos_types;
return 0;
os->type = *type;
- if (os->symbols) {
- free(os->symbols);
- os->symbols = NULL;
- }
+
+ free(os->symbols);
+ os->symbols = NULL;
return 1;
}