132 if (strcmp(cp,
"none") == 0)
135 if (strcmp(cp,
"auto") == 0) {
150 Jim_SetResultFormatted(goi->
interp,
"Unknown RTOS type %s, try one of: ", cp);
151 res = Jim_GetResult(goi->
interp);
154 Jim_AppendStrings(goi->
interp, res,
", auto or none",
NULL);
228 int rtos_detected = 0;
236 reply_len = sprintf(reply,
"OK");
242 size_t len =
unhexify((uint8_t *)cur_sym, strchr(packet + 8,
':') + 1, strlen(strchr(packet + 8,
':') + 1));
245 const char no_suffix[] =
"";
246 const char lto_suffix[] =
".lto_priv.0";
247 const size_t lto_suffix_len = strlen(lto_suffix);
249 const char *cur_suffix;
250 const char *next_suffix;
254 if (len > lto_suffix_len && !strcmp(cur_sym + len - lto_suffix_len, lto_suffix)) {
256 cur_sym[len - lto_suffix_len] =
'\0';
257 cur_suffix = lto_suffix;
260 cur_suffix = no_suffix;
261 next_suffix = lto_suffix;
264 if ((strcmp(packet,
"qSymbol::") != 0) &&
265 (!sscanf(packet,
"qSymbol:%" SCNx64
":", &
addr))) {
274 LOG_WARNING(
"RTOS %s not detected. (GDB could not find symbol \'%s\')", os->
type->
name, cur_sym);
289 LOG_DEBUG(
"RTOS: Address of symbol '%s%s' is 0x%" PRIx64, cur_sym, cur_suffix,
addr);
293 next_suffix = no_suffix;
298 LOG_WARNING(
"RTOS: Debugger sent us qSymbol with '%s%s' that we did not ask for", cur_sym, cur_suffix);
324 reply_len += 2 * strlen(next_suffix);
326 if (reply_len >
sizeof(reply)) {
327 LOG_ERROR(
"ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->
symbol_name, next_suffix);
331 LOG_DEBUG(
"RTOS: Requesting symbol lookup of '%s%s' from the debugger", next_sym->
symbol_name, next_suffix);
333 reply_len = snprintf(reply,
sizeof(reply),
"qSymbol:");
334 reply_len +=
hexify(reply + reply_len,
336 sizeof(reply) - reply_len);
337 reply_len +=
hexify(reply + reply_len,
338 (
const uint8_t *)next_suffix, strlen(next_suffix),
339 sizeof(reply) - reply_len);
343 return rtos_detected;
350 if (strncmp(packet,
"qThreadExtraInfo,", 17) == 0) {
355 sscanf(packet,
"qThreadExtraInfo,%" SCNx64, &threadid);
379 char *tmp_str = calloc(str_size + 9,
sizeof(
char));
380 char *tmp_str_ptr = tmp_str;
383 tmp_str_ptr += sprintf(tmp_str_ptr,
"Name: %s", detail->
thread_name_str);
385 if (tmp_str_ptr != tmp_str)
386 tmp_str_ptr += sprintf(tmp_str_ptr,
", ");
387 tmp_str_ptr += sprintf(tmp_str_ptr,
"%s", detail->
extra_info_str);
390 assert(strlen(tmp_str) ==
391 (
size_t) (tmp_str_ptr - tmp_str));
393 char *hex_str = malloc(strlen(tmp_str) * 2 + 1);
394 size_t pkt_len =
hexify(hex_str, (
const uint8_t *)tmp_str,
395 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
405 }
else if (strncmp(packet,
"qSymbol", 7) == 0) {
414 }
else if (strncmp(packet,
"qfThreadInfo", 12) == 0) {
422 char *tmp_str = out_str;
424 tmp_str += sprintf(tmp_str,
"%c%016" PRIx64, i == 0 ?
'm' :
',',
434 }
else if (strncmp(packet,
"qsThreadInfo", 12) == 0) {
437 }
else if (strncmp(packet,
"qAttached", 9) == 0) {
440 }
else if (strncmp(packet,
"qOffsets", 8) == 0) {
441 char offsets[] =
"Text=0;Data=0;Bss=0";
444 }
else if (strncmp(packet,
"qCRC:", 5) == 0) {
448 }
else if (strncmp(packet,
"qC", 2) == 0) {
457 }
else if (packet[0] ==
'T') {
460 sscanf(packet,
"T%" SCNx64, &
threadid);
475 }
else if (packet[0] ==
'H') {
479 sscanf(packet,
"Hg%16" SCNx64, &
threadid);
495 struct rtos_reg *reg_list,
int num_regs)
497 size_t num_bytes = 1;
498 for (
int i = 0; i < num_regs; ++i)
501 char *hex = malloc(num_bytes);
504 for (
int i = 0; i < num_regs; ++i) {
506 size_t n =
hexify(hex_p, reg_list[i].value,
count, num_bytes);
522 if ((
target->
rtos) && (current_threadid != -1) &&
523 (current_threadid != 0) &&
529 LOG_DEBUG(
"getting register %d for thread 0x%" PRIx64
530 ", target->rtos->current_thread=0x%" PRIx64,
537 reg_list = calloc(1,
sizeof(*reg_list));
540 current_threadid, reg_num, ®_list[0]);
542 LOG_ERROR(
"RTOS: failed to get register %d", reg_num);
551 LOG_ERROR(
"RTOS: failed to get register list");
556 for (
int i = 0; i < num_regs; ++i) {
557 if (reg_list[i].
number == (uint32_t)reg_num) {
574 if ((
target->
rtos) && (current_threadid != -1) &&
575 (current_threadid != 0) &&
581 LOG_DEBUG(
"RTOS: getting register list for thread 0x%" PRIx64
582 ", target->rtos->current_thread=0x%" PRIx64
"\r\n",
591 LOG_ERROR(
"RTOS: failed to get register list");
610 (current_threadid != -1) &&
611 (current_threadid != 0)) {
625 if (stack_ptr == 0) {
626 LOG_ERROR(
"Error: null stack pointer in thread");
631 uint32_t address = stack_ptr;
638 LOG_ERROR(
"Error reading stack frame from thread");
641 LOG_DEBUG(
"RTOS: Read stack frame at 0x%" PRIx32, address);
653 stack_data, stacking, stack_ptr);
668 buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].
size);
void * buf_cpy(const void *from, void *_to, unsigned 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.
enum esirisc_reg_num number
int gdb_put_packet(struct connection *connection, char *buffer, int len)
static struct target * get_target_from_connection(struct connection *connection)
int jim_getopt_string(struct jim_getopt_info *goi, const char **puthere, int *len)
Remove argv[0] as string.
#define ERROR_NOT_IMPLEMENTED
#define LOG_OUTPUT(expr ...)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
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 struct rtos_type * rtos_types[]
struct rtos_type ucos_iii_rtos
int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size)
struct rtos_type chromium_ec_rtos
struct rtos_type riot_rtos
struct rtos_type freertos_rtos
int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
static int os_alloc_create(struct target *target, struct rtos_type *ostype)
struct rtos_type hwthread_rtos
struct rtos_type threadx_rtos
static struct symbol_table_elem * find_symbol(const struct rtos *os, const char *symbol)
static void os_free(struct target *target)
struct rtos_type nuttx_rtos
struct rtos_type embkernel_rtos
struct rtos_type chibios_rtos
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 os_alloc(struct target *target, struct rtos_type *ostype)
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)
struct rtos_type mqx_rtos
int rtos_update_threads(struct target *target)
struct rtos_type zephyr_rtos
int rtos_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
int rtos_smp_init(struct target *target)
struct rtos_type ecos_rtos
int rtos_create(struct jim_getopt_info *goi, struct target *target)
struct rtos_type linux_rtos
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
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
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.