#include "rtos.h"
#include "helper/log.h"
#include "helper/types.h"
-#include "server/gdb_server.h"
+#include "target/register.h"
+#include "rtos_nuttx_stackings.h"
-#include "nuttx_header.h"
-
-
-int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
-
-#ifdef CONFIG_DISABLE_SIGNALS
-#define SIG_QUEUE_NUM 0
-#else
-#define SIG_QUEUE_NUM 1
-#endif /* CONFIG_DISABLE_SIGNALS */
-
-#ifdef CONFIG_DISABLE_MQUEUE
-#define M_QUEUE_NUM 0
-#else
-#define M_QUEUE_NUM 2
-#endif /* CONFIG_DISABLE_MQUEUE */
-
-#ifdef CONFIG_PAGING
-#define PAGING_QUEUE_NUM 1
-#else
-#define PAGING_QUEUE_NUM 0
-#endif /* CONFIG_PAGING */
+#define NAME_SIZE 32
+#define EXTRAINFO_SIZE 256
+/* Only 32-bit CPUs are supported by the current implementation. Supporting
+ * other CPUs will require reading this information from the target and
+ * adapting the code accordingly.
+ */
+#define PTR_WIDTH 4
-#define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
+struct nuttx_params {
+ const char *target_name;
+ const struct rtos_register_stacking *stacking;
+ const struct rtos_register_stacking *(*select_stackinfo)(struct target *target);
+};
+/*
+ * struct tcbinfo_s is located in the sched.h
+ * https://github.com/apache/nuttx/blob/master/include/nuttx/sched.h
+ */
+#define TCBINFO_TARGET_SIZE 22
+struct tcbinfo {
+ uint16_t pid_off; /* Offset of tcb.pid */
+ uint16_t state_off; /* Offset of tcb.task_state */
+ uint16_t pri_off; /* Offset of tcb.sched_priority */
+ uint16_t name_off; /* Offset of tcb.name */
+ uint16_t regs_off; /* Offset of tcb.regs */
+ uint16_t basic_num; /* Num of genernal regs */
+ uint16_t total_num; /* Num of regs in tcbinfo.reg_offs */
+ target_addr_t xcpreg_off; /* Offset pointer of xcp.regs */
+};
-/* see nuttx/sched/os_start.c */
-static char *nuttx_symbol_list[] = {
- "g_readytorun", /* 0: must be top of this array */
- "g_tasklisttable",
- NULL
+struct symbols {
+ const char *name;
+ bool optional;
};
-/* see nuttx/include/nuttx/sched.h */
-struct tcb {
- uint32_t flink;
- uint32_t blink;
- uint8_t dat[512];
+/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
+enum nuttx_symbol_vals {
+ NX_SYM_READYTORUN = 0,
+ NX_SYM_PIDHASH,
+ NX_SYM_NPIDHASH,
+ NX_SYM_TCB_INFO,
};
-static struct {
- uint32_t addr;
- uint32_t prio;
-} g_tasklist[TASK_QUEUE_NUM];
+static const struct symbols nuttx_symbol_list[] = {
+ { "g_readytorun", false },
+ { "g_pidhash", false },
+ { "g_npidhash", false },
+ { "g_tcbinfo", false },
+ { NULL, false }
+};
static char *task_state_str[] = {
"INVALID",
"RUNNING",
"INACTIVE",
"WAIT_SEM",
-#ifndef CONFIG_DISABLE_SIGNALS
"WAIT_SIG",
-#endif /* CONFIG_DISABLE_SIGNALS */
-#ifndef CONFIG_DISABLE_MQUEUE
"WAIT_MQNOTEMPTY",
"WAIT_MQNOTFULL",
-#endif /* CONFIG_DISABLE_MQUEUE */
-#ifdef CONFIG_PAGING
"WAIT_PAGEFILL",
-#endif /* CONFIG_PAGING */
+ "STOPPED",
};
-/* see arch/arm/include/armv7-m/irq_cmnvector.h */
-static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
- { ARMV7M_R0, 0x28, 32 }, /* r0 */
- { ARMV7M_R1, 0x2c, 32 }, /* r1 */
- { ARMV7M_R2, 0x30, 32 }, /* r2 */
- { ARMV7M_R3, 0x34, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x38, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x3c, 32 }, /* lr */
- { ARMV7M_PC, 0x40, 32 }, /* pc */
- { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
+static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target);
+
+static const struct nuttx_params nuttx_params_list[] = {
+ {
+ .target_name = "cortex_m",
+ .stacking = NULL,
+ .select_stackinfo = cortexm_select_stackinfo,
+ },
+ {
+ .target_name = "hla_target",
+ .stacking = NULL,
+ .select_stackinfo = cortexm_select_stackinfo,
+ },
+ {
+ .target_name = "esp32",
+ .stacking = &nuttx_esp32_stacking,
+ },
+ {
+ .target_name = "esp32s2",
+ .stacking = &nuttx_esp32s2_stacking,
+ },
+ {
+ .target_name = "esp32s3",
+ .stacking = &nuttx_esp32s3_stacking,
+ },
+ {
+ .target_name = "esp32c3",
+ .stacking = &nuttx_riscv_stacking,
+ },
};
+static bool cortexm_hasfpu(struct target *target)
+{
+ uint32_t cpacr;
+ struct armv7m_common *armv7m_target = target_to_armv7m(target);
-static const struct rtos_register_stacking nuttx_stacking_cortex_m = {
- .stack_registers_size = 0x48,
- .stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m
-};
-
-static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
- { ARMV7M_R0, 0x6c, 32 }, /* r0 */
- { ARMV7M_R1, 0x70, 32 }, /* r1 */
- { ARMV7M_R2, 0x74, 32 }, /* r2 */
- { ARMV7M_R3, 0x78, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x7c, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x80, 32 }, /* lr */
- { ARMV7M_PC, 0x84, 32 }, /* pc */
- { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
-};
+ if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE)
+ return false;
-static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
- .stack_registers_size = 0x8c,
- .stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m_fpu
-};
+ int retval = target_read_u32(target, FPU_CPACR, &cpacr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Could not read CPACR register to check FPU state");
+ return false;
+ }
-static int pid_offset = PID;
-static int state_offset = STATE;
-static int name_offset = NAME;
-static int xcpreg_offset = XCPREG;
-static int name_size = NAME_SIZE;
+ return cpacr & 0x00F00000;
+}
-static int rcmd_offset(const char *cmd, const char *name)
+static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target)
{
- if (strncmp(cmd, name, strlen(name)))
- return -1;
-
- if (strlen(cmd) <= strlen(name) + 1)
- return -1;
-
- return atoi(cmd + strlen(name));
+ return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m;
}
-static int nuttx_thread_packet(struct connection *connection,
- char const *packet, int packet_size)
+static bool nuttx_detect_rtos(struct target *target)
{
- char cmd[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
-
- if (!strncmp(packet, "qRcmd", 5)) {
- size_t len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd));
- int offset;
-
- if (len <= 0)
- goto pass;
-
- offset = rcmd_offset(cmd, "nuttx.pid_offset");
-
- if (offset >= 0) {
- LOG_INFO("pid_offset: %d", offset);
- pid_offset = offset;
- goto retok;
- }
-
- offset = rcmd_offset(cmd, "nuttx.state_offset");
-
- if (offset >= 0) {
- LOG_INFO("state_offset: %d", offset);
- state_offset = offset;
- goto retok;
- }
+ if (target->rtos->symbols &&
+ target->rtos->symbols[NX_SYM_READYTORUN].address != 0 &&
+ target->rtos->symbols[NX_SYM_PIDHASH].address != 0)
+ return true;
+ return false;
+}
- offset = rcmd_offset(cmd, "nuttx.name_offset");
+static int nuttx_create(struct target *target)
+{
+ const struct nuttx_params *param;
+ unsigned int i;
- if (offset >= 0) {
- LOG_INFO("name_offset: %d", offset);
- name_offset = offset;
- goto retok;
+ for (i = 0; i < ARRAY_SIZE(nuttx_params_list); i++) {
+ param = &nuttx_params_list[i];
+ if (strcmp(target_type_name(target), param->target_name) == 0) {
+ LOG_INFO("Detected target \"%s\"", param->target_name);
+ break;
}
+ }
- offset = rcmd_offset(cmd, "nuttx.xcpreg_offset");
-
- if (offset >= 0) {
- LOG_INFO("xcpreg_offset: %d", offset);
- xcpreg_offset = offset;
- goto retok;
- }
+ if (i >= ARRAY_SIZE(nuttx_params_list)) {
+ LOG_ERROR("Could not find \"%s\" target in NuttX compatibility list", target_type_name(target));
+ return JIM_ERR;
+ }
- offset = rcmd_offset(cmd, "nuttx.name_size");
+ /* We found a target in our list, copy its reference. */
+ target->rtos->rtos_specific_params = (void *)param;
- if (offset >= 0) {
- LOG_INFO("name_size: %d", offset);
- name_size = offset;
- goto retok;
- }
- }
-pass:
- return rtos_thread_packet(connection, packet, packet_size);
-retok:
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
+ return JIM_OK;
}
-
-static bool nuttx_detect_rtos(struct target *target)
+static int nuttx_smp_init(struct target *target)
{
- if ((target->rtos->symbols) &&
- (target->rtos->symbols[0].address != 0) &&
- (target->rtos->symbols[1].address != 0)) {
- return true;
- }
- return false;
+ /* Return OK for now so that the initialisation sequence doesn't stop.
+ * SMP case will be implemented later. */
+ return ERROR_OK;
}
-static int nuttx_create(struct target *target)
+static target_addr_t target_buffer_get_addr(struct target *target, const uint8_t *buffer)
{
-
- target->rtos->gdb_thread_packet = nuttx_thread_packet;
- LOG_INFO("target type name = %s", target->type->name);
- return 0;
+#if PTR_WIDTH == 8
+ return target_buffer_get_u64(target, buffer);
+#else
+ return target_buffer_get_u32(target, buffer);
+#endif
}
static int nuttx_update_threads(struct rtos *rtos)
{
- uint32_t thread_count;
- struct tcb tcb;
- int ret;
- uint32_t head;
- uint32_t tcb_addr;
- uint32_t i;
+ struct tcbinfo tcbinfo;
+ uint32_t pidhashaddr, npidhash, tcbaddr;
+ uint16_t pid;
uint8_t state;
if (!rtos->symbols) {
- LOG_ERROR("No symbols for NuttX");
- return -3;
+ LOG_ERROR("No symbols for nuttx");
+ return ERROR_FAIL;
}
- /* free previous thread details */
+ /* Free previous thread details */
rtos_free_threadlist(rtos);
- ret = target_read_buffer(rtos->target, rtos->symbols[1].address,
- sizeof(g_tasklist), (uint8_t *)&g_tasklist);
- if (ret) {
- LOG_ERROR("target_read_buffer : ret = %d\n", ret);
+ /* NuttX provides a hash table that keeps track of all the TCBs.
+ * We first read its size from g_npidhash and its address from g_pidhash.
+ * Its content is then read from these values.
+ */
+ int ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_NPIDHASH].address, &npidhash);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read g_npidhash: ret = %d", ret);
return ERROR_FAIL;
}
- thread_count = 0;
+ LOG_DEBUG("Hash table size (g_npidhash) = %" PRId32, npidhash);
+
+ ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_PIDHASH].address, &pidhashaddr);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read g_pidhash address: ret = %d", ret);
+ return ERROR_FAIL;
+ }
- for (i = 0; i < TASK_QUEUE_NUM; i++) {
+ LOG_DEBUG("Hash table address (g_pidhash) = %" PRIx32, pidhashaddr);
- if (g_tasklist[i].addr == 0)
+ uint8_t *pidhash = malloc(npidhash * PTR_WIDTH);
+ if (!pidhash) {
+ LOG_ERROR("Failed to allocate pidhash");
+ return ERROR_FAIL;
+ }
+
+ ret = target_read_buffer(rtos->target, pidhashaddr, PTR_WIDTH * npidhash, pidhash);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read tcbhash: ret = %d", ret);
+ goto errout;
+ }
+
+ /* NuttX provides a struct that contains TCB offsets for required members.
+ * Read its content from g_tcbinfo.
+ */
+ uint8_t buff[TCBINFO_TARGET_SIZE];
+ ret = target_read_buffer(rtos->target, rtos->symbols[NX_SYM_TCB_INFO].address, sizeof(buff), buff);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read tcbinfo: ret = %d", ret);
+ goto errout;
+ }
+ tcbinfo.pid_off = target_buffer_get_u16(rtos->target, buff);
+ tcbinfo.state_off = target_buffer_get_u16(rtos->target, buff + 2);
+ tcbinfo.pri_off = target_buffer_get_u16(rtos->target, buff + 4);
+ tcbinfo.name_off = target_buffer_get_u16(rtos->target, buff + 6);
+ tcbinfo.regs_off = target_buffer_get_u16(rtos->target, buff + 8);
+ tcbinfo.basic_num = target_buffer_get_u16(rtos->target, buff + 10);
+ tcbinfo.total_num = target_buffer_get_u16(rtos->target, buff + 12);
+ tcbinfo.xcpreg_off = target_buffer_get_addr(rtos->target, buff + 14);
+
+ /* The head of the g_readytorun list is the currently running task.
+ * Reading in a temporary variable first to avoid endianness issues,
+ * rtos->current_thread is int64_t. */
+ uint32_t current_thread;
+ ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_READYTORUN].address, ¤t_thread);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read g_readytorun: ret = %d", ret);
+ goto errout;
+ }
+ rtos->current_thread = current_thread;
+
+ uint32_t thread_count = 0;
+
+ for (unsigned int i = 0; i < npidhash; i++) {
+ tcbaddr = target_buffer_get_u32(rtos->target, &pidhash[i * PTR_WIDTH]);
+
+ if (!tcbaddr)
continue;
- ret = target_read_u32(rtos->target, g_tasklist[i].addr,
- &head);
+ ret = target_read_u16(rtos->target, tcbaddr + tcbinfo.pid_off, &pid);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read PID of TCB@0x%x from pidhash[%d]: ret = %d",
+ tcbaddr, i, ret);
+ goto errout;
+ }
- if (ret) {
- LOG_ERROR("target_read_u32 : ret = %d\n", ret);
- return ERROR_FAIL;
+ ret = target_read_u8(rtos->target, tcbaddr + tcbinfo.state_off, &state);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read state of TCB@0x%x from pidhash[%d]: ret = %d",
+ tcbaddr, i, ret);
+ goto errout;
}
- /* readytorun head is current thread */
- if (g_tasklist[i].addr == rtos->symbols[0].address)
- rtos->current_thread = head;
+ struct thread_detail *new_thread_details = realloc(rtos->thread_details,
+ sizeof(struct thread_detail) * (thread_count + 1));
+ if (!new_thread_details) {
+ ret = ERROR_FAIL;
+ goto errout;
+ }
+ struct thread_detail *thread = &new_thread_details[thread_count];
+ thread->threadid = tcbaddr;
+ thread->exists = true;
+ thread->extra_info_str = NULL;
- tcb_addr = head;
- while (tcb_addr) {
- struct thread_detail *thread;
- ret = target_read_buffer(rtos->target, tcb_addr,
- sizeof(tcb), (uint8_t *)&tcb);
- if (ret) {
- LOG_ERROR("target_read_buffer : ret = %d\n",
- ret);
- return ERROR_FAIL;
- }
- thread_count++;
-
- rtos->thread_details = realloc(rtos->thread_details,
- sizeof(struct thread_detail) * thread_count);
- thread = &rtos->thread_details[thread_count - 1];
- thread->threadid = tcb_addr;
- thread->exists = true;
-
- state = tcb.dat[state_offset - 8];
- thread->extra_info_str = NULL;
- if (state < ARRAY_SIZE(task_state_str)) {
- thread->extra_info_str = malloc(256);
- snprintf(thread->extra_info_str, 256, "pid:%d, %s",
- tcb.dat[pid_offset - 8] |
- tcb.dat[pid_offset - 8 + 1] << 8,
- task_state_str[state]);
- }
+ rtos->thread_details = new_thread_details;
+ thread_count++;
- if (name_offset) {
- thread->thread_name_str = malloc(name_size + 1);
- snprintf(thread->thread_name_str, name_size,
- "%s", (char *)&tcb.dat[name_offset - 8]);
- } else {
- thread->thread_name_str = malloc(sizeof("None"));
- strcpy(thread->thread_name_str, "None");
+ if (state < ARRAY_SIZE(task_state_str)) {
+ thread->extra_info_str = malloc(EXTRAINFO_SIZE);
+ if (!thread->extra_info_str) {
+ ret = ERROR_FAIL;
+ goto errout;
}
+ snprintf(thread->extra_info_str, EXTRAINFO_SIZE, "pid:%d, %s",
+ pid,
+ task_state_str[state]);
+ }
- tcb_addr = tcb.flink;
+ if (tcbinfo.name_off) {
+ thread->thread_name_str = calloc(NAME_SIZE + 1, sizeof(char));
+ if (!thread->thread_name_str) {
+ ret = ERROR_FAIL;
+ goto errout;
+ }
+ ret = target_read_buffer(rtos->target, tcbaddr + tcbinfo.name_off,
+ sizeof(char) * NAME_SIZE, (uint8_t *)thread->thread_name_str);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read thread's name: ret = %d", ret);
+ goto errout;
+ }
+ } else {
+ thread->thread_name_str = strdup("None");
}
}
- rtos->thread_count = thread_count;
- return 0;
+ ret = ERROR_OK;
+ rtos->thread_count = thread_count;
+errout:
+ free(pidhash);
+ return ret;
}
-
-/*
- * thread_id = tcb address;
- */
-static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+static int nuttx_getreg_current_thread(struct rtos *rtos,
struct rtos_reg **reg_list, int *num_regs)
{
- int retval;
-
- /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
- bool cm4_fpu_enabled = false;
- struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
- if (is_armv7m(armv7m_target)) {
- if (armv7m_target->fp_feature == FPV4_SP) {
- /* Found ARM v7m target which includes a FPU */
- uint32_t cpacr;
-
- retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read CPACR register to check FPU state");
- return -1;
- }
+ struct reg **gdb_reg_list;
+
+ /* Registers for currently running thread are not on task's stack and
+ * should be retrieved from reg caches via target_get_gdb_reg_list */
+ int ret = target_get_gdb_reg_list(rtos->target, &gdb_reg_list, num_regs,
+ REG_CLASS_GENERAL);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("target_get_gdb_reg_list failed %d", ret);
+ return ret;
+ }
- /* Check if CP10 and CP11 are set to full access. */
- if (cpacr & 0x00F00000) {
- /* Found target with enabled FPU */
- cm4_fpu_enabled = 1;
- }
+ *reg_list = calloc(*num_regs, sizeof(struct rtos_reg));
+ if (!(*reg_list)) {
+ LOG_ERROR("Failed to alloc memory for %d", *num_regs);
+ free(gdb_reg_list);
+ return ERROR_FAIL;
+ }
+
+ for (int i = 0; i < *num_regs; i++) {
+ (*reg_list)[i].number = gdb_reg_list[i]->number;
+ (*reg_list)[i].size = gdb_reg_list[i]->size;
+ memcpy((*reg_list)[i].value, gdb_reg_list[i]->value, ((*reg_list)[i].size + 7) / 8);
+ }
+
+ free(gdb_reg_list);
+
+ return ERROR_OK;
+}
+
+static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs)
+{
+ uint16_t xcpreg_off;
+ uint32_t regsaddr;
+ const struct nuttx_params *priv = rtos->rtos_specific_params;
+ const struct rtos_register_stacking *stacking = priv->stacking;
+
+ if (!stacking) {
+ if (priv->select_stackinfo) {
+ stacking = priv->select_stackinfo(rtos->target);
+ } else {
+ LOG_ERROR("Can't find a way to get stacking info");
+ return ERROR_FAIL;
}
}
- const struct rtos_register_stacking *stacking;
- if (cm4_fpu_enabled)
- stacking = &nuttx_stacking_cortex_m_fpu;
- else
- stacking = &nuttx_stacking_cortex_m;
+ int ret = target_read_u16(rtos->target,
+ rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off),
+ &xcpreg_off);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read registers' offset: ret = %d", ret);
+ return ERROR_FAIL;
+ }
+
+ ret = target_read_u32(rtos->target, thread_id + xcpreg_off, ®saddr);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read registers' address: ret = %d", ret);
+ return ERROR_FAIL;
+ }
- return rtos_generic_stack_read(rtos->target, stacking,
- (uint32_t)thread_id + xcpreg_offset, reg_list, num_regs);
+ return rtos_generic_stack_read(rtos->target, stacking, regsaddr, reg_list, num_regs);
}
-static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
+static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs)
{
- unsigned int i;
+ if (!rtos) {
+ LOG_ERROR("NUTTX: out of memory");
+ return ERROR_FAIL;
+ }
+
+ if (thread_id == rtos->current_thread)
+ return nuttx_getreg_current_thread(rtos, reg_list, num_regs);
+ return nuttx_getregs_fromstack(rtos, thread_id, reg_list, num_regs);
+}
- *symbol_list = (struct symbol_table_elem *) calloc(1,
- sizeof(struct symbol_table_elem) * ARRAY_SIZE(nuttx_symbol_list));
+static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
+{
+ *symbol_list = calloc(ARRAY_SIZE(nuttx_symbol_list), sizeof(**symbol_list));
+ if (!*symbol_list) {
+ LOG_ERROR("NUTTX: out of memory");
+ return ERROR_FAIL;
+ }
- for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
- (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
+ for (unsigned int i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++) {
+ (*symbol_list)[i].symbol_name = nuttx_symbol_list[i].name;
+ (*symbol_list)[i].optional = nuttx_symbol_list[i].optional;
+ }
- return 0;
+ return ERROR_OK;
}
-struct rtos_type nuttx_rtos = {
+const struct rtos_type nuttx_rtos = {
.name = "nuttx",
.detect_rtos = nuttx_detect_rtos,
.create = nuttx_create,
+ .smp_init = nuttx_smp_init,
.update_threads = nuttx_update_threads,
.get_thread_reg_list = nuttx_get_thread_reg_list,
.get_symbol_list_to_lookup = nuttx_get_symbol_list_to_lookup,