25 #define LINUX_USER_KERNEL_BORDER 0xc0000000
28 #define MAX_THREADS 200
105 LOG_ERROR(
"Cannot compute linux virt2phys translation");
118 uint32_t address, uint32_t
size, uint32_t
count,
126 if (address < 0xc000000) {
127 LOG_ERROR(
"linux awareness : address in user space");
151 const uint8_t *value_ptr =
buffer;
157 int64_t thread_id,
struct rtos_reg **reg_list,
int *num_regs)
170 if (next->threadid == thread_id)
174 }
while ((found == 0) && (next != tmp) && (next));
177 LOG_ERROR(
"could not find thread: %" PRIx64, thread_id);
182 struct reg **gdb_reg_list;
196 "current thread %" PRIx64
": no target to perform access of core id %" PRIx32,
207 *reg_list = calloc(*num_regs,
sizeof(
struct rtos_reg));
209 for (
int i = 0; i < *num_regs; ++i) {
210 if (!gdb_reg_list[i]->valid)
211 gdb_reg_list[i]->
type->
get(gdb_reg_list[i]);
213 (*reg_list)[i].number = gdb_reg_list[i]->
number;
214 (*reg_list)[i].size = gdb_reg_list[i]->
size;
216 buf_cpy(gdb_reg_list[i]->value, (*reg_list)[i].value, (*reg_list)[i].
size);
277 LOG_ERROR(
"fill_task_pid: unable to read memory");
289 uint8_t *
buffer = calloc(1, 4);
296 LOG_ERROR(
"fill_task: unable to read memory");
304 LOG_ERROR(
"fill task: unable to read memory");
312 LOG_ERROR(
"fill task: unable to read memory");
320 uint32_t asid_addr = val +
MM_CTX;
328 (
"fill task: unable to read memory -- ASID");
332 LOG_ERROR(
"fill task: unable to read memory");
342 uint32_t full_name[4];
346 for (i = 0; i < 17; i++)
352 LOG_ERROR(
"get_name: unable to read memory\n");
359 t->
name[3] = raw_name >> 24;
360 t->
name[2] = raw_name >> 16;
361 t->
name[1] = raw_name >> 8;
362 t->
name[0] = raw_name;
365 t->
name[7] = raw_name >> 24;
366 t->
name[6] = raw_name >> 16;
367 t->
name[5] = raw_name >> 8;
368 t->
name[4] = raw_name;
371 t->
name[11] = raw_name >> 24;
372 t->
name[10] = raw_name >> 16;
373 t->
name[9] = raw_name >> 8;
374 t->
name[8] = raw_name;
377 t->
name[15] = raw_name >> 24;
378 t->
name[14] = raw_name >> 16;
379 t->
name[13] = raw_name >> 8;
380 t->
name[12] = raw_name;
391 uint8_t *
buffer = calloc(1, 4);
399 ctt->TS = 0xdeadbeef;
404 struct reg **reg_list;
414 if (!reg_list[13]->
valid)
415 reg_list[13]->
type->
get(reg_list[13]);
417 buf = reg_list[13]->
value;
419 ti_addr = (val & 0xffffe000);
420 uint32_t ts_addr = ti_addr + 0xc;
425 uint32_t cpu, on_cpu = TS +
ONCPU;
434 while ((ct) && (ct->
core_id != (int32_t) cpu))
437 if ((ct) && (ct->
TS == 0xdeadbeef))
441 (
"error in linux current thread update");
445 t = calloc(1,
sizeof(
struct threads));
472 uint32_t *thread_info_addr_old)
475 uint32_t preempt_count_addr = 0;
476 uint32_t registers[10];
477 uint8_t *
buffer = calloc(1, 4);
478 uint32_t stack = base_addr +
QAT;
479 uint32_t thread_info_addr = 0;
480 uint32_t thread_info_addr_update = 0;
482 context->
R4 = 0xdeadbeef;
483 context->
R5 = 0xdeadbeef;
484 context->
R6 = 0xdeadbeef;
485 context->
R7 = 0xdeadbeef;
486 context->
R8 = 0xdeadbeef;
487 context->
R9 = 0xdeadbeef;
488 context->
IP = 0xdeadbeef;
489 context->
FP = 0xdeadbeef;
490 context->
SP = 0xdeadbeef;
491 context->
PC = 0xdeadbeef;
494 if (*thread_info_addr_old == 0xdeadbeef) {
500 LOG_ERROR(
"cpu_context: unable to read memory");
502 thread_info_addr_update = thread_info_addr;
504 thread_info_addr = *thread_info_addr_old;
506 preempt_count_addr = thread_info_addr +
PREEMPT;
512 if (*thread_info_addr_old != 0xdeadbeef) {
514 (
"cpu_context: cannot read at thread_info_addr");
518 (
"cpu_context : thread_info_addr in userspace!!!");
520 *thread_info_addr_old = 0xdeadbeef;
524 LOG_ERROR(
"cpu_context: unable to read memory");
530 (uint8_t *) registers);
534 LOG_ERROR(
"cpu_context: unable to read memory\n");
559 if (*thread_info_addr_old == 0xdeadbeef)
560 *thread_info_addr_old = thread_info_addr_update;
569 uint8_t *
buffer = calloc(1, 4);
579 LOG_ERROR(
"next task: unable to read memory");
608 LOG_INFO(
"del task %" PRId64, (*t)->threadid);
612 task_list = (*t)->
next;
618 *t = prev ? prev : task_list;
632 struct threads *temp = task_list;
656 while ((ct) && (ct->pid != pid))
658 while ((ct) && (ct->
TS != base_addr))
662 if ((ct) && (ct->pid == pid))
664 if ((ct) && (ct->
TS == base_addr))
740 t = calloc(1,
sizeof(
struct threads));
749 LOG_INFO(
"complete time %" PRId64
", thread mean %" PRId64
"\n",
783 os_linux->
name =
"linux";
825 if (ct->threadid == -1) {
829 t = calloc(1,
sizeof(
struct threads));
837 (
"linux identify_current_threads: unable to read pid");
875 LOG_INFO(
"current thread core %x identified %s",
876 ct->core_id, t->
name);
878 LOG_INFO(
"current thread core %x, reused %s",
879 ct->core_id, t->
name);
887 LOG_INFO(
"current thread core %x , already identified %s !!!",
888 ct->core_id, tmp.
name);
931 uint32_t previous = 0xdeadbeef;
938 (t->
base_addr != previous)) || (loop == 0)) {
945 retval = fill_task_pid(
target, t);
955 while (thread_list) {
957 if (t->
pid == thread_list->pid) {
959 if (t->
base_addr == thread_list->base_addr) {
961 if (!thread_list->status) {
963 if (t->
base_addr != thread_list->base_addr)
964 LOG_INFO(
"thread base_addr has changed !!");
968 thread_list->status = 1;
977 thread_list->context =
979 thread_list->base_addr,
980 &thread_list->thread_info_addr);
990 thread_list = thread_list->next;
1007 t = calloc(1,
sizeof(
struct threads));
1014 LOG_INFO(
"update thread done %" PRId64
", mean%" PRId64
"\n",
1031 LOG_INFO(
"received thread request without init task address");
1042 char *tmp_str = out_str;
1043 tmp_str += sprintf(tmp_str,
"m");
1047 tmp_str += sprintf(tmp_str,
"%016" PRIx64, temp->
threadid);
1050 tmp_str += sprintf(tmp_str,
",");
1078 char *out_strr = calloc(
MAX_THREADS * 17 + 10, 1);
1079 char *tmp_strr = out_strr;
1080 tmp_strr += sprintf(tmp_strr,
"m");
1082 tmp_strr += sprintf(tmp_strr,
"%016" PRIx64, temp->threadid);
1088 tmp_strr += sprintf(tmp_strr,
",");
1090 sprintf(tmp_strr,
"%016" PRIx64, temp->threadid);
1109 int64_t threadid = 0;
1112 sscanf(packet,
"qThreadExtraInfo,%" SCNx64, &threadid);
1118 char *
pid =
" PID: ";
1119 char *pid_current =
"*PID: ";
1120 char *
name =
"Name: ";
1121 int str_size = strlen(
pid) + strlen(
name);
1122 char *tmp_str = calloc(1, str_size + 50);
1123 char *tmp_str_ptr = tmp_str;
1127 tmp_str_ptr += sprintf(tmp_str_ptr,
"%s",
1130 tmp_str_ptr += sprintf(tmp_str_ptr,
"%s",
pid);
1132 tmp_str_ptr += sprintf(tmp_str_ptr,
"%d, ", (
int)temp->
pid);
1133 sprintf(tmp_str_ptr,
"%s",
name);
1134 sprintf(tmp_str_ptr,
"%s", temp->
name);
1135 char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
1136 size_t pkt_len =
hexify(hex_str, (
const uint8_t *)tmp_str,
1137 strlen(tmp_str), strlen(tmp_str) * 2 + 1);
1152 struct target *
target,
char const *packet,
int packet_size)
1158 sscanf(packet,
"T%" SCNx64, &threadid);
1185 LOG_INFO(
"gdb requested status on non existing thread");
1212 struct target *
target,
char const *packet,
int packet_size)
1222 int64_t current_gdb_thread_rq;
1225 if ((ct) && (ct->threadid == -1)) {
1228 while ((ct) && (ct->threadid == -1))
1235 LOG_INFO(
"no current thread identified");
1241 while ((ct) && (ct->threadid == -1)) {
1244 LOG_INFO(
"name of unidentified thread %s",
1253 if (packet[1] ==
'g') {
1254 sscanf(packet,
"Hg%16" SCNx64, ¤t_gdb_thread_rq);
1256 if (current_gdb_thread_rq == 0) {
1261 current_gdb_thread_rq;
1264 }
else if (packet[1] ==
'c') {
1265 sscanf(packet,
"Hc%16" SCNx64, ¤t_gdb_thread_rq);
1267 if ((current_gdb_thread_rq == 0) ||
1268 (current_gdb_thread_rq == ct->threadid)) {
1289 switch (packet[0]) {
1301 if (strncmp(packet,
"qSymbol", 7) == 0) {
1308 }
else if (strncmp(packet,
"qfThreadInfo", 12) == 0) {
1322 }
else if (strncmp(packet,
"qsThreadInfo", 12) == 0) {
1325 }
else if (strncmp(packet,
"qThreadExtraInfo,", 17) == 0) {
1347 if ((ct) && (ct->
threadid == -1)) {
1350 while ((ct) && (ct->
threadid == -1))
1357 LOG_WARNING(
"WARNING! current GDB thread do not match "
1358 "current thread running. "
1359 "Switch thread in GDB to threadid %d",
1362 LOG_INFO(
"threads_needs_update = 1");
1394 ct->TS = 0xdeadbeef;
1412 os_linux->
name =
"linux";
1424 ct->
TS = 0xdeadbeef;
1452 LOG_INFO(
"allocation for %d threads line",
1460 tmp += sprintf(tmp,
"PID\t\tCPU\t\tASID\t\tNAME\n");
1461 tmp += sprintf(tmp,
"---\t\t---\t\t----\t\t----\n");
1468 "%" PRIu32
"\t\t%" PRIu32
"\t\t%" PRIx32
"\t\t%s\n",
1474 "%" PRIu32
"\t\t%" PRIu32
"\t\t%" PRIx32
"\t\t%s\n",
1486 display = calloc(40, 1);
1487 sprintf(display,
"linux_ps_command failed\n");
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.
int gdb_put_packet(struct connection *connection, char *buffer, int len)
static struct target * get_target_from_connection(struct connection *connection)
The JTAG interface can be implemented with a software or hardware fifo.
static struct current_thread * add_current_thread(struct current_thread *currents, struct current_thread *ct)
static int fill_task(struct target *target, struct threads *t)
static int clean_threadlist(struct target *target)
static int linux_os_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
static int current_base_addr(struct linux_os *linux_os, uint32_t base_addr)
static int linux_thread_extra_info(struct target *target, struct connection *connection, char const *packet, int packet_size)
static void linux_identify_current_threads(struct target *target)
static char * linux_ps_command(struct target *target)
static int linux_os_smp_init(struct target *target)
static uint32_t next_task(struct target *target, struct threads *t)
static int linux_gdb_thread_update(struct target *target, struct connection *connection, char const *packet, int packet_size)
static int linux_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
static int insert_into_threadlist(struct target *target, struct threads *t)
static int get_current(struct target *target, int create)
static int linux_gdb_h_packet(struct connection *connection, struct target *target, char const *packet, int packet_size)
static struct threads * liste_add_task(struct threads *task_list, struct threads *t, struct threads **last)
static int linux_compute_virt2phys(struct target *target, target_addr_t address)
static int linux_os_clean(struct target *target)
static int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer)
static const char *const linux_symbol_list[]
static bool linux_os_detect(struct target *target)
#define LINUX_USER_KERNEL_BORDER
static int linux_get_tasks(struct target *target, int context)
static struct cpu_context * cpu_context_read(struct target *target, uint32_t base_addr, uint32_t *info_addr)
static int linux_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
static int get_name(struct target *target, struct threads *t)
const struct rtos_type linux_rtos
static int linux_gdb_thread_packet(struct target *target, struct connection *connection, char const *packet, int packet_size)
static int linux_os_dummy_update(struct rtos *rtos)
static int linux_task_update(struct target *target, int context)
static uint32_t get_buffer(struct target *target, const uint8_t *buffer)
static int linux_os_create(struct target *target)
static int linux_thread_packet(struct connection *connection, char const *packet, int packet_size)
static int linux_gdb_t_packet(struct connection *connection, struct target *target, char const *packet, int packet_size)
static struct threads * liste_del_task(struct threads *task_list, struct threads **t, struct threads *prev)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size)
#define GDB_THREAD_PACKET_NOT_CONSUMED
size_t size
Size of the control block search area.
#define foreach_smp_target(pos, head)
struct current_thread * next
struct threads * thread_list
struct current_thread * current_threads
int preupdtate_threadid_count
int(* get)(struct reg *reg)
const struct reg_arch_type * type
int(* create)(struct target *target)
int(* gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size)
struct symbol_table_elem * symbols
void * rtos_specific_params
Table should be terminated by an element with NULL in symbol_name.
int(* virt2phys)(struct target *target, target_addr_t address, target_addr_t *physical)
struct list_head * smp_targets
struct target_type * type
struct cpu_context * context
uint32_t thread_info_addr
int target_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class)
Obtain the registers for GDB.
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
#define ERROR_TARGET_FAILURE
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.