117 if (strcmp(cp,
"none") == 0)
120 if (strcmp(cp,
"auto") == 0) {
135 Jim_SetResultFormatted(goi->
interp,
"Unknown RTOS type %s, try one of: ", cp);
136 res = Jim_GetResult(goi->
interp);
139 Jim_AppendStrings(goi->
interp, res,
", auto or none",
NULL);
213 int rtos_detected = 0;
221 reply_len = sprintf(reply,
"OK");
227 size_t len =
unhexify((uint8_t *)cur_sym, strchr(packet + 8,
':') + 1, strlen(strchr(packet + 8,
':') + 1));
230 const char no_suffix[] =
"";
231 const char lto_suffix[] =
".lto_priv.0";
232 const size_t lto_suffix_len = strlen(lto_suffix);
234 const char *cur_suffix;
235 const char *next_suffix;
239 if (len > lto_suffix_len && !strcmp(cur_sym + len - lto_suffix_len, lto_suffix)) {
241 cur_sym[len - lto_suffix_len] =
'\0';
242 cur_suffix = lto_suffix;
245 cur_suffix = no_suffix;
246 next_suffix = lto_suffix;
249 if ((strcmp(packet,
"qSymbol::") != 0) &&
250 (!sscanf(packet,
"qSymbol:%" SCNx64
":", &
addr))) {
259 LOG_WARNING(
"RTOS %s not detected. (GDB could not find symbol \'%s\')", os->
type->
name, cur_sym);
274 LOG_DEBUG(
"RTOS: Address of symbol '%s%s' is 0x%" PRIx64, cur_sym, cur_suffix,
addr);
278 next_suffix = no_suffix;
283 LOG_WARNING(
"RTOS: Debugger sent us qSymbol with '%s%s' that we did not ask for", cur_sym, cur_suffix);
309 reply_len += 2 * strlen(next_suffix);
311 if (reply_len >
sizeof(reply)) {
312 LOG_ERROR(
"ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->
symbol_name, next_suffix);
316 LOG_DEBUG(
"RTOS: Requesting symbol lookup of '%s%s' from the debugger", next_sym->
symbol_name, next_suffix);
318 reply_len = snprintf(reply,
sizeof(reply),
"qSymbol:");
319 reply_len +=
hexify(reply + reply_len,
321 sizeof(reply) - reply_len);
322 reply_len +=
hexify(reply + reply_len,
323 (
const uint8_t *)next_suffix, strlen(next_suffix),
324 sizeof(reply) - reply_len);
328 return rtos_detected;
335 if (strncmp(packet,
"qThreadExtraInfo,", 17) == 0) {
340 sscanf(packet,
"qThreadExtraInfo,%" SCNx64, &threadid);
364 char *tmp_str = calloc(str_size + 9,
sizeof(
char));
365 char *tmp_str_ptr = tmp_str;
368 tmp_str_ptr += sprintf(tmp_str_ptr,
"Name: %s", detail->
thread_name_str);
370 if (tmp_str_ptr != tmp_str)
371 tmp_str_ptr += sprintf(tmp_str_ptr,
", ");
372 tmp_str_ptr += sprintf(tmp_str_ptr,
"%s", detail->
extra_info_str);
375 assert(strlen(tmp_str) ==
376 (
size_t) (tmp_str_ptr - tmp_str));
378 char *hex_str = malloc(strlen(tmp_str) * 2 + 1);
379 size_t pkt_len =
hexify(hex_str, (
const uint8_t *)tmp_str,
380 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
390 }
else if (strncmp(packet,
"qSymbol", 7) == 0) {
399 }
else if (strncmp(packet,
"qfThreadInfo", 12) == 0) {
407 char *tmp_str = out_str;
409 tmp_str += sprintf(tmp_str,
"%c%016" PRIx64, i == 0 ?
'm' :
',',
419 }
else if (strncmp(packet,
"qsThreadInfo", 12) == 0) {
422 }
else if (strncmp(packet,
"qAttached", 9) == 0) {
425 }
else if (strncmp(packet,
"qOffsets", 8) == 0) {
426 char offsets[] =
"Text=0;Data=0;Bss=0";
429 }
else if (strncmp(packet,
"qCRC:", 5) == 0) {
433 }
else if (strncmp(packet,
"qC", 2) == 0) {
442 }
else if (packet[0] ==
'T') {
445 sscanf(packet,
"T%" SCNx64, &
threadid);
460 }
else if (packet[0] ==
'H') {
464 sscanf(packet,
"Hg%16" SCNx64, &
threadid);
480 struct rtos_reg *reg_list,
int num_regs)
482 size_t num_bytes = 1;
483 for (
int i = 0; i < num_regs; ++i)
486 char *hex = malloc(num_bytes);
489 for (
int i = 0; i < num_regs; ++i) {
491 size_t n =
hexify(hex_p, reg_list[i].value,
count, num_bytes);
507 if ((
target->
rtos) && (current_threadid != -1) &&
508 (current_threadid != 0) &&
514 LOG_DEBUG(
"getting register %d for thread 0x%" PRIx64
515 ", target->rtos->current_thread=0x%" PRIx64,
522 reg_list = calloc(1,
sizeof(*reg_list));
525 current_threadid, reg_num, ®_list[0]);
527 LOG_ERROR(
"RTOS: failed to get register %d", reg_num);
536 LOG_ERROR(
"RTOS: failed to get register list");
541 for (
int i = 0; i < num_regs; ++i) {
542 if (reg_list[i].
number == (uint32_t)reg_num) {
559 if ((
target->
rtos) && (current_threadid != -1) &&
560 (current_threadid != 0) &&
566 LOG_DEBUG(
"RTOS: getting register list for thread 0x%" PRIx64
567 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
576 LOG_ERROR(
"RTOS: failed to get register list");
595 (current_threadid != -1) &&
596 (current_threadid != 0)) {
610 if (stack_ptr == 0) {
611 LOG_ERROR(
"Error: null stack pointer in thread");
616 uint32_t address = stack_ptr;
626 LOG_ERROR(
"Error reading stack frame from thread");
629 LOG_DEBUG(
"RTOS: Read stack frame at 0x%" PRIx32, address);
641 stack_data, stacking, stack_ptr);
656 buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].
size);
const struct rtos_type freertos_rtos
void * buf_cpy(const void *from, void *_to, unsigned int size)
Copies size bits out of from and into to.
size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length)
Convert binary data into a string of hexadecimal pairs.
size_t unhexify(uint8_t *bin, const char *hex, size_t count)
Convert a string of hexadecimal pairs into its binary representation.
Support functions to access arbitrary bits in a byte array.
const struct rtos_type chibios_rtos
const struct rtos_type chromium_ec_rtos
const struct rtos_type ecos_rtos
const struct rtos_type embkernel_rtos
enum esirisc_reg_num number
int gdb_put_packet(struct connection *connection, const char *buffer, int len)
static struct target * get_target_from_connection(struct connection *connection)
const struct rtos_type hwthread_rtos
int jim_getopt_string(struct jim_getopt_info *goi, const char **puthere, int *len)
Remove argv[0] as string.
const struct rtos_type linux_rtos
#define ERROR_NOT_IMPLEMENTED
#define LOG_OUTPUT(expr ...)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
const struct rtos_type mqx_rtos
const struct rtos_type nuttx_rtos
const struct rtos_type riot_rtos
const struct rtos_type rtkernel_rtos
static int rtos_target_for_threadid(struct connection *connection, int64_t threadid, struct target **t)
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, struct rtos_reg **reg_list, int *num_regs)
static const struct rtos_type * rtos_types[]
static int os_alloc_create(struct target *target, const struct rtos_type *ostype)
int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size)
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
static struct symbol_table_elem * find_symbol(const struct rtos *os, const char *symbol)
static int os_alloc(struct target *target, const struct rtos_type *ostype)
static void os_free(struct target *target)
int rtos_set_reg(struct connection *connection, int reg_num, uint8_t *reg_value)
int rtos_get_gdb_reg_list(struct connection *connection)
Return a list of general registers.
void rtos_destroy(struct target *target)
static int rtos_try_next(struct target *target)
static int rtos_put_gdb_reg_list(struct connection *connection, struct rtos_reg *reg_list, int num_regs)
int rtos_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
static struct symbol_table_elem * next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
int rtos_update_threads(struct target *target)
int rtos_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
int rtos_smp_init(struct target *target)
int rtos_create(struct jim_getopt_info *goi, struct target *target)
int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size)
void rtos_free_threadlist(struct rtos *rtos)
int rtos_get_gdb_reg(struct connection *connection, int reg_num)
Look through all registers to find this register.
#define GDB_THREAD_PACKET_NOT_CONSUMED
const struct rtos_type zephyr_rtos
const struct rtos_type threadx_rtos
const struct rtos_type ucos_iii_rtos
target_addr_t addr
Start address to search for the control block.
size_t size
Size of the control block search area.
A TCL -ish GetOpt like code.
const struct stack_register_offset * register_offsets
unsigned char num_output_registers
target_addr_t(* calculate_process_stack)(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, target_addr_t stack_ptr)
unsigned char stack_registers_size
int(* read_stack)(struct target *target, int64_t stack_ptr, const struct rtos_register_stacking *stacking, uint8_t *stack_data)
signed char stack_growth_direction
int(* create)(struct target *target)
int(* smp_init)(struct target *target)
int(* update_threads)(struct rtos *rtos)
int(* get_thread_reg)(struct rtos *rtos, int64_t thread_id, uint32_t reg_num, struct rtos_reg *reg)
int(* get_symbol_list_to_lookup)(struct symbol_table_elem *symbol_list[])
int(* write_buffer)(struct rtos *rtos, target_addr_t address, uint32_t size, const uint8_t *buffer)
int(* read_buffer)(struct rtos *rtos, target_addr_t address, uint32_t size, uint8_t *buffer)
bool(* detect_rtos)(struct target *target)
int(* get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
Return a list of general registers, with their values filled out.
int(* set_reg)(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value)
const struct rtos_type * type
int(* gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size)
struct thread_detail * thread_details
struct symbol_table_elem * symbols
int(* gdb_target_for_threadid)(struct connection *connection, int64_t thread_id, struct target **p_target)
threadid_t current_thread
unsigned short width_bits
Table should be terminated by an element with NULL in symbol_name.
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
#define ERROR_TARGET_INIT_FAILED
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.