1 /***************************************************************************
2 * Copyright (C) 2011 by STEricsson *
3 * Heythem Bouhaja heythem.bouhaja@stericsson.com : creation *
4 * Michel JAOUEN michel.jaouen@stericsson.com : adaptation to rtos *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
24 #include <helper/time_support.h>
25 #include <jtag/jtag.h>
26 #include "target/target.h"
27 #include "target/target_type.h"
28 #include "helper/log.h"
29 #include "helper/types.h"
31 #include "rtos_standard_stackings.h"
32 #include <target/register.h>
33 #include "server/gdb_server.h"
35 #define LINUX_USER_KERNEL_BORDER 0xc0000000
36 #include "linux_header.h"
38 #define MAX_THREADS 200
42 uint32_t init_task_addr
;
45 int preupdtate_threadid_count
;
48 int threads_needs_update
;
49 struct current_thread
*current_threads
;
50 struct threads
*thread_list
;
51 /* virt2phys parameter */
56 struct current_thread
{
63 struct current_thread
*next
;
68 uint32_t base_addr
; /* address to read magic */
69 uint32_t state
; /* magic value : filled only at creation */
70 uint32_t pid
; /* linux pid : id for identifying a thread */
71 uint32_t oncpu
; /* content cpu number in current thread */
72 uint32_t asid
; /* filled only at creation */
74 int status
; /* dead = 1 alive = 2 current = 3 alive and current */
75 /* value that should not change during the live of a thread ? */
76 uint32_t thread_info_addr
; /* contain latest thread_info_addr computed */
77 /* retrieve from thread_info */
78 struct cpu_context
*context
;
93 uint32_t preempt_count
;
95 struct cpu_context
*cpu_context_read(struct target
*target
, uint32_t base_addr
,
97 static int insert_into_threadlist(struct target
*target
, struct threads
*t
);
99 static int linux_os_create(struct target
*target
);
101 static int linux_os_dummy_update(struct rtos
*rtos
)
103 /* update is done only when thread request come
104 * too many thread to do it on each stop */
108 static int linux_compute_virt2phys(struct target
*target
, target_addr_t address
)
110 struct linux_os
*linux_os
= (struct linux_os
*)
111 target
->rtos
->rtos_specific_params
;
112 target_addr_t pa
= 0;
113 int retval
= target
->type
->virt2phys(target
, address
, &pa
);
114 if (retval
!= ERROR_OK
) {
115 LOG_ERROR("Cannot compute linux virt2phys translation");
116 /* fixes default address */
117 linux_os
->phys_base
= 0;
121 linux_os
->init_task_addr
= address
;
122 address
= address
& linux_os
->phys_mask
;
123 linux_os
->phys_base
= pa
- address
;
127 static int linux_read_memory(struct target
*target
,
128 uint32_t address
, uint32_t size
, uint32_t count
,
132 struct linux_os
*linux_os
= (struct linux_os
*)
133 target
->rtos
->rtos_specific_params
;
134 uint32_t pa
= (address
& linux_os
->phys_mask
) + linux_os
->phys_base
;
136 if (address
< 0xc000000) {
137 LOG_ERROR("linux awareness : address in user space");
141 target_read_phys_memory(target
, pa
, size
, count
, buffer
);
143 target_read_memory(target
, address
, size
, count
, buffer
);
147 int fill_buffer(struct target
*target
, uint32_t addr
, uint8_t *buffer
)
150 if ((addr
& 0xfffffffc) != addr
)
151 LOG_INFO("unaligned address %" PRIx32
"!!", addr
);
153 int retval
= linux_read_memory(target
, addr
, 4, 1, buffer
);
158 uint32_t get_buffer(struct target
*target
, const uint8_t *buffer
)
161 const uint8_t *value_ptr
= buffer
;
162 value
= target_buffer_get_u32(target
, value_ptr
);
166 static int linux_os_thread_reg_list(struct rtos
*rtos
,
167 int64_t thread_id
, struct rtos_reg
**reg_list
, int *num_regs
)
169 struct target
*target
= rtos
->target
;
170 struct linux_os
*linux_os
= (struct linux_os
*)
171 target
->rtos
->rtos_specific_params
;
172 struct current_thread
*tmp
= linux_os
->current_threads
;
173 struct current_thread
*next
;
176 /* check if a current thread is requested */
180 if (next
->threadid
== thread_id
)
184 } while ((found
== 0) && (next
!= tmp
) && (next
!= NULL
));
187 LOG_ERROR("could not find thread: %" PRIx64
, thread_id
);
191 /* search target to perfom the access */
192 struct reg
**gdb_reg_list
;
193 struct target_list
*head
;
197 if (head
->target
->coreid
== next
->core_id
) {
199 target
= head
->target
;
204 } while ((head
!= (struct target_list
*)NULL
) && (found
== 0));
209 "current thread %" PRIx64
": no target to perform access of core id %" PRIx32
,
215 /*LOG_INFO("thread %lx current on core %x",thread_id, target->coreid);*/
216 retval
= target_get_gdb_reg_list(target
, &gdb_reg_list
, num_regs
, REG_CLASS_GENERAL
);
217 if (retval
!= ERROR_OK
)
220 *reg_list
= calloc(*num_regs
, sizeof(struct rtos_reg
));
222 for (int i
= 0; i
< *num_regs
; ++i
) {
223 if (!gdb_reg_list
[i
]->valid
)
224 gdb_reg_list
[i
]->type
->get(gdb_reg_list
[i
]);
226 (*reg_list
)[i
].number
= gdb_reg_list
[i
]->number
;
227 (*reg_list
)[i
].size
= gdb_reg_list
[i
]->size
;
229 buf_cpy(gdb_reg_list
[i
]->value
, (*reg_list
)[i
].value
, (*reg_list
)[i
].size
);
235 static bool linux_os_detect(struct target
*target
)
237 LOG_INFO("should no be called");
241 static int linux_os_smp_init(struct target
*target
);
242 static int linux_os_clean(struct target
*target
);
244 static const char * const linux_symbol_list
[] = {
249 static int linux_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
252 *symbol_list
= (symbol_table_elem_t
*)
253 calloc(ARRAY_SIZE(linux_symbol_list
), sizeof(symbol_table_elem_t
));
255 for (i
= 0; i
< ARRAY_SIZE(linux_symbol_list
); i
++)
256 (*symbol_list
)[i
].symbol_name
= linux_symbol_list
[i
];
261 static char *linux_ps_command(struct target
*target
);
263 const struct rtos_type Linux_os
= {
265 .detect_rtos
= linux_os_detect
,
266 .create
= linux_os_create
,
267 .smp_init
= linux_os_smp_init
,
268 .update_threads
= linux_os_dummy_update
,
269 .get_thread_reg_list
= linux_os_thread_reg_list
,
270 .get_symbol_list_to_lookup
= linux_get_symbol_list_to_lookup
,
271 .clean
= linux_os_clean
,
272 .ps_command
= linux_ps_command
,
275 static int linux_thread_packet(struct connection
*connection
, char const *packet
,
277 static void linux_identify_current_threads(struct target
*target
);
280 int fill_task_pid(struct target
*target
, struct threads
*t
)
282 uint32_t pid_addr
= t
->base_addr
+ PID
;
284 int retval
= fill_buffer(target
, pid_addr
, buffer
);
286 if (retval
== ERROR_OK
) {
287 uint32_t val
= get_buffer(target
, buffer
);
290 LOG_ERROR("fill_task_pid: unable to read memory");
296 int fill_task(struct target
*target
, struct threads
*t
)
299 uint32_t pid_addr
= t
->base_addr
+ PID
;
300 uint32_t mem_addr
= t
->base_addr
+ MEM
;
301 uint32_t on_cpu
= t
->base_addr
+ ONCPU
;
302 uint8_t *buffer
= calloc(1, 4);
303 retval
= fill_buffer(target
, t
->base_addr
, buffer
);
305 if (retval
== ERROR_OK
) {
306 uint32_t val
= get_buffer(target
, buffer
);
309 LOG_ERROR("fill_task: unable to read memory");
311 retval
= fill_buffer(target
, pid_addr
, buffer
);
313 if (retval
== ERROR_OK
) {
314 uint32_t val
= get_buffer(target
, buffer
);
317 LOG_ERROR("fill task: unable to read memory");
319 retval
= fill_buffer(target
, on_cpu
, buffer
);
321 if (retval
== ERROR_OK
) {
322 uint32_t val
= get_buffer(target
, buffer
);
325 LOG_ERROR("fill task: unable to read memory");
327 retval
= fill_buffer(target
, mem_addr
, buffer
);
329 if (retval
== ERROR_OK
) {
330 uint32_t val
= get_buffer(target
, buffer
);
333 uint32_t asid_addr
= val
+ MM_CTX
;
334 retval
= fill_buffer(target
, asid_addr
, buffer
);
336 if (retval
== ERROR_OK
) {
337 val
= get_buffer(target
, buffer
);
341 ("fill task: unable to read memory -- ASID");
345 LOG_ERROR("fill task: unable to read memory");
352 int get_name(struct target
*target
, struct threads
*t
)
355 uint32_t full_name
[4];
356 uint32_t comm
= t
->base_addr
+ COMM
;
359 for (i
= 0; i
< 17; i
++)
362 retval
= linux_read_memory(target
, comm
, 4, 4, (uint8_t *) full_name
);
364 if (retval
!= ERROR_OK
) {
365 LOG_ERROR("get_name: unable to read memory\n");
369 uint32_t raw_name
= target_buffer_get_u32(target
,
372 t
->name
[3] = raw_name
>> 24;
373 t
->name
[2] = raw_name
>> 16;
374 t
->name
[1] = raw_name
>> 8;
375 t
->name
[0] = raw_name
;
377 target_buffer_get_u32(target
, (const uint8_t *)&full_name
[1]);
378 t
->name
[7] = raw_name
>> 24;
379 t
->name
[6] = raw_name
>> 16;
380 t
->name
[5] = raw_name
>> 8;
381 t
->name
[4] = raw_name
;
383 target_buffer_get_u32(target
, (const uint8_t *)&full_name
[2]);
384 t
->name
[11] = raw_name
>> 24;
385 t
->name
[10] = raw_name
>> 16;
386 t
->name
[9] = raw_name
>> 8;
387 t
->name
[8] = raw_name
;
389 target_buffer_get_u32(target
, (const uint8_t *)&full_name
[3]);
390 t
->name
[15] = raw_name
>> 24;
391 t
->name
[14] = raw_name
>> 16;
392 t
->name
[13] = raw_name
>> 8;
393 t
->name
[12] = raw_name
;
398 int get_current(struct target
*target
, int create
)
400 struct target_list
*head
;
405 uint8_t *buffer
= calloc(1, 4);
406 struct linux_os
*linux_os
= (struct linux_os
*)
407 target
->rtos
->rtos_specific_params
;
408 struct current_thread
*ctt
= linux_os
->current_threads
;
410 /* invalid current threads content */
411 while (ctt
!= NULL
) {
413 ctt
->TS
= 0xdeadbeef;
417 while (head
!= (struct target_list
*)NULL
) {
418 struct reg
**reg_list
;
422 if (target_get_gdb_reg_list(head
->target
, ®_list
,
423 ®_list_size
, REG_CLASS_GENERAL
) != ERROR_OK
) {
425 return ERROR_TARGET_FAILURE
;
428 if (!reg_list
[13]->valid
)
429 reg_list
[13]->type
->get(reg_list
[13]);
431 buf
= reg_list
[13]->value
;
432 val
= get_buffer(target
, buf
);
433 ti_addr
= (val
& 0xffffe000);
434 uint32_t TS_addr
= ti_addr
+ 0xc;
435 retval
= fill_buffer(target
, TS_addr
, buffer
);
437 if (retval
== ERROR_OK
) {
438 uint32_t TS
= get_buffer(target
, buffer
);
439 uint32_t cpu
, on_cpu
= TS
+ ONCPU
;
440 retval
= fill_buffer(target
, on_cpu
, buffer
);
442 if (retval
== ERROR_OK
) {
443 /*uint32_t cpu = get_buffer(target, buffer);*/
444 struct current_thread
*ct
=
445 linux_os
->current_threads
;
446 cpu
= head
->target
->coreid
;
448 while ((ct
!= NULL
) && (ct
->core_id
!= (int32_t) cpu
))
451 if ((ct
!= NULL
) && (ct
->TS
== 0xdeadbeef))
455 ("error in linux current thread update");
459 t
= calloc(1, sizeof(struct threads
));
460 t
->base_addr
= ct
->TS
;
461 fill_task(target
, t
);
464 insert_into_threadlist(target
, t
);
466 t
->thread_info_addr
= 0xdeadbeef;
467 ct
->threadid
= t
->threadid
;
468 linux_os
->thread_count
++;
472 /*LOG_INFO("Creation of current thread %s",t->name);*/
486 struct cpu_context
*cpu_context_read(struct target
*target
, uint32_t base_addr
,
487 uint32_t *thread_info_addr_old
)
489 struct cpu_context
*context
= calloc(1, sizeof(struct cpu_context
));
490 uint32_t preempt_count_addr
= 0;
491 uint32_t registers
[10];
492 uint8_t *buffer
= calloc(1, 4);
493 uint32_t stack
= base_addr
+ QAT
;
494 uint32_t thread_info_addr
= 0;
495 uint32_t thread_info_addr_update
= 0;
496 int retval
= ERROR_FAIL
;
497 context
->R4
= 0xdeadbeef;
498 context
->R5
= 0xdeadbeef;
499 context
->R6
= 0xdeadbeef;
500 context
->R7
= 0xdeadbeef;
501 context
->R8
= 0xdeadbeef;
502 context
->R9
= 0xdeadbeef;
503 context
->IP
= 0xdeadbeef;
504 context
->FP
= 0xdeadbeef;
505 context
->SP
= 0xdeadbeef;
506 context
->PC
= 0xdeadbeef;
509 if (*thread_info_addr_old
== 0xdeadbeef) {
510 retval
= fill_buffer(target
, stack
, buffer
);
512 if (retval
== ERROR_OK
)
513 thread_info_addr
= get_buffer(target
, buffer
);
515 LOG_ERROR("cpu_context: unable to read memory");
517 thread_info_addr_update
= thread_info_addr
;
519 thread_info_addr
= *thread_info_addr_old
;
521 preempt_count_addr
= thread_info_addr
+ PREEMPT
;
522 retval
= fill_buffer(target
, preempt_count_addr
, buffer
);
524 if (retval
== ERROR_OK
)
525 context
->preempt_count
= get_buffer(target
, buffer
);
527 if (*thread_info_addr_old
!= 0xdeadbeef) {
529 ("cpu_context: cannot read at thread_info_addr");
531 if (*thread_info_addr_old
< LINUX_USER_KERNEL_BORDER
)
533 ("cpu_context : thread_info_addr in userspace!!!");
535 *thread_info_addr_old
= 0xdeadbeef;
539 LOG_ERROR("cpu_context: unable to read memory");
542 thread_info_addr
+= CPU_CONT
;
544 retval
= linux_read_memory(target
, thread_info_addr
, 4, 10,
545 (uint8_t *) registers
);
547 if (retval
!= ERROR_OK
) {
549 LOG_ERROR("cpu_context: unable to read memory\n");
554 target_buffer_get_u32(target
, (const uint8_t *)®isters
[0]);
556 target_buffer_get_u32(target
, (const uint8_t *)®isters
[1]);
558 target_buffer_get_u32(target
, (const uint8_t *)®isters
[2]);
560 target_buffer_get_u32(target
, (const uint8_t *)®isters
[3]);
562 target_buffer_get_u32(target
, (const uint8_t *)®isters
[4]);
564 target_buffer_get_u32(target
, (const uint8_t *)®isters
[5]);
566 target_buffer_get_u32(target
, (const uint8_t *)®isters
[6]);
568 target_buffer_get_u32(target
, (const uint8_t *)®isters
[7]);
570 target_buffer_get_u32(target
, (const uint8_t *)®isters
[8]);
572 target_buffer_get_u32(target
, (const uint8_t *)®isters
[9]);
574 if (*thread_info_addr_old
== 0xdeadbeef)
575 *thread_info_addr_old
= thread_info_addr_update
;
582 uint32_t next_task(struct target
*target
, struct threads
*t
)
584 uint8_t *buffer
= calloc(1, 4);
585 uint32_t next_addr
= t
->base_addr
+ NEXT
;
586 int retval
= fill_buffer(target
, next_addr
, buffer
);
588 if (retval
== ERROR_OK
) {
589 uint32_t val
= get_buffer(target
, buffer
);
594 LOG_ERROR("next task: unable to read memory");
601 struct current_thread
*add_current_thread(struct current_thread
*currents
,
602 struct current_thread
*ct
)
606 if (currents
== NULL
) {
610 struct current_thread
*temp
= currents
;
612 while (temp
->next
!= NULL
)
620 struct threads
*liste_del_task(struct threads
*task_list
, struct threads
**t
,
621 struct threads
*prev
)
623 LOG_INFO("del task %" PRId64
, (*t
)->threadid
);
625 prev
->next
= (*t
)->next
;
627 task_list
= (*t
)->next
;
629 /* free content of threads */
634 *t
= prev
? prev
: task_list
;
638 struct threads
*liste_add_task(struct threads
*task_list
, struct threads
*t
,
639 struct threads
**last
)
644 if (task_list
== NULL
) {
648 struct threads
*temp
= task_list
;
650 while (temp
->next
!= NULL
)
664 static int current_pid(struct linux_os
*linux_os
, uint32_t pid
)
666 static int current_base_addr(struct linux_os
*linux_os
, uint32_t base_addr
)
669 struct current_thread
*ct
= linux_os
->current_threads
;
672 while ((ct
!= NULL
) && (ct
->pid
!= pid
))
674 while ((ct
!= NULL
) && (ct
->TS
!= base_addr
))
678 if ((ct
!= NULL
) && (ct
->pid
== pid
))
680 if ((ct
!= NULL
) && (ct
->TS
== base_addr
))
687 int linux_get_tasks(struct target
*target
, int context
)
691 struct linux_os
*linux_os
= (struct linux_os
*)
692 target
->rtos
->rtos_specific_params
;
693 linux_os
->thread_list
= NULL
;
694 linux_os
->thread_count
= 0;
696 if (linux_os
->init_task_addr
== 0xdeadbeef) {
697 LOG_INFO("no init symbol\n");
701 int64_t start
= timeval_ms();
703 struct threads
*t
= calloc(1, sizeof(struct threads
));
704 struct threads
*last
= NULL
;
705 t
->base_addr
= linux_os
->init_task_addr
;
706 /* retrieve the thread id , currently running in the different smp core */
707 get_current(target
, 1);
709 while (((t
->base_addr
!= linux_os
->init_task_addr
) &&
710 (t
->base_addr
!= 0)) || (loop
== 0)) {
712 fill_task(target
, t
);
713 retval
= get_name(target
, t
);
715 if (loop
> MAX_THREADS
) {
717 LOG_INFO("more than %d threads !!", MAX_THREADS
);
721 if (retval
!= ERROR_OK
) {
726 /* check that this thread is not one the current threads already
731 if (!current_pid(linux_os
, t
->pid
)) {
733 if (!current_base_addr(linux_os
, t
->base_addr
)) {
735 t
->threadid
= linux_os
->threadid_count
;
737 linux_os
->threadid_count
++;
739 linux_os
->thread_list
=
740 liste_add_task(linux_os
->thread_list
, t
, &last
);
741 /* no interest to fill the context if it is a current thread. */
742 linux_os
->thread_count
++;
743 t
->thread_info_addr
= 0xdeadbeef;
747 cpu_context_read(target
, t
->base_addr
,
748 &t
->thread_info_addr
);
749 base_addr
= next_task(target
, t
);
751 /*LOG_INFO("thread %s is a current thread already created",t->name); */
752 base_addr
= next_task(target
, t
);
756 t
= calloc(1, sizeof(struct threads
));
757 t
->base_addr
= base_addr
;
760 linux_os
->threads_lookup
= 1;
761 linux_os
->threads_needs_update
= 0;
762 linux_os
->preupdtate_threadid_count
= linux_os
->threadid_count
- 1;
763 /* check that all current threads have been identified */
765 LOG_INFO("complete time %" PRId64
", thread mean %" PRId64
"\n",
766 (timeval_ms() - start
),
767 (timeval_ms() - start
) / linux_os
->threadid_count
);
769 LOG_INFO("threadid count %d", linux_os
->threadid_count
);
775 static int clean_threadlist(struct target
*target
)
777 struct linux_os
*linux_os
= (struct linux_os
*)
778 target
->rtos
->rtos_specific_params
;
779 struct threads
*old
, *temp
= linux_os
->thread_list
;
781 while (temp
!= NULL
) {
794 static int linux_os_clean(struct target
*target
)
796 struct linux_os
*os_linux
= (struct linux_os
*)
797 target
->rtos
->rtos_specific_params
;
798 clean_threadlist(target
);
799 os_linux
->init_task_addr
= 0xdeadbeef;
800 os_linux
->name
= "linux";
801 os_linux
->thread_list
= NULL
;
802 os_linux
->thread_count
= 0;
803 os_linux
->nr_cpus
= 0;
804 os_linux
->threads_lookup
= 0;
805 os_linux
->threads_needs_update
= 0;
806 os_linux
->threadid_count
= 1;
810 static int insert_into_threadlist(struct target
*target
, struct threads
*t
)
812 struct linux_os
*linux_os
= (struct linux_os
*)
813 target
->rtos
->rtos_specific_params
;
814 struct threads
*temp
= linux_os
->thread_list
;
815 t
->threadid
= linux_os
->threadid_count
;
816 linux_os
->threadid_count
++;
821 linux_os
->thread_list
= t
;
823 while (temp
->next
!= NULL
)
833 static void linux_identify_current_threads(struct target
*target
)
835 struct linux_os
*linux_os
= (struct linux_os
*)
836 target
->rtos
->rtos_specific_params
;
837 struct threads
*thread_list
= linux_os
->thread_list
;
838 struct current_thread
*ct
= linux_os
->current_threads
;
839 struct threads
*t
= NULL
;
841 while ((ct
!= NULL
)) {
842 if (ct
->threadid
== -1) {
844 /* un-identified thread */
846 t
= calloc(1, sizeof(struct threads
));
847 t
->base_addr
= ct
->TS
;
850 if (fill_task_pid(target
, t
) != ERROR_OK
) {
854 ("linux identify_current_threads: unable to read pid");
859 /* search in the list of threads if pid
861 while ((thread_list
!= NULL
) && (found
== 0)) {
863 if (thread_list
->pid
== t
->pid
) {
865 if (thread_list
->base_addr
== t
->base_addr
) {
871 thread_list
= thread_list
->next
;
875 /* it is a new thread */
876 if (fill_task(target
, t
) != ERROR_OK
)
880 insert_into_threadlist(target
, t
);
881 t
->thread_info_addr
= 0xdeadbeef;
885 ct
->threadid
= t
->threadid
;
889 linux_os
->thread_count
++;
892 LOG_INFO("current thread core %x identified %s",
893 ct
->core_id
, t
->name
);
895 LOG_INFO("current thread core %x, reused %s",
896 ct
->core_id
, t
->name
);
902 tmp
.base_addr
= ct
->TS
;
903 get_name(target
, &tmp
);
904 LOG_INFO("current thread core %x , already identified %s !!!",
905 ct
->core_id
, tmp
.name
);
915 LOG_ERROR("unable to read pid");
921 static int linux_task_update(struct target
*target
, int context
)
923 struct linux_os
*linux_os
= (struct linux_os
*)
924 target
->rtos
->rtos_specific_params
;
925 struct threads
*thread_list
= linux_os
->thread_list
;
928 linux_os
->thread_count
= 0;
930 /*thread_list = thread_list->next; skip init_task*/
931 while (thread_list
!= NULL
) {
932 thread_list
->status
= 0; /*setting all tasks to dead state*/
934 if (thread_list
->context
) {
935 free(thread_list
->context
);
936 thread_list
->context
= NULL
;
939 thread_list
= thread_list
->next
;
944 if (linux_os
->init_task_addr
== 0xdeadbeef) {
945 LOG_INFO("no init symbol\n");
948 int64_t start
= timeval_ms();
949 struct threads
*t
= calloc(1, sizeof(struct threads
));
950 uint32_t previous
= 0xdeadbeef;
951 t
->base_addr
= linux_os
->init_task_addr
;
952 retval
= get_current(target
, 0);
953 /*check that all current threads have been identified */
954 linux_identify_current_threads(target
);
956 while (((t
->base_addr
!= linux_os
->init_task_addr
) &&
957 (t
->base_addr
!= previous
)) || (loop
== 0)) {
958 /* for avoiding any permanent loop for any reason possibly due to
961 previous
= t
->base_addr
;
964 retval
= fill_task_pid(target
, t
);
967 if (retval
!= ERROR_OK
) {
972 thread_list
= linux_os
->thread_list
;
974 while (thread_list
!= NULL
) {
976 if (t
->pid
== thread_list
->pid
) {
978 if (t
->base_addr
== thread_list
->base_addr
) {
980 if (!thread_list
->status
) {
982 if (t
->base_addr
!= thread_list
->base_addr
)
983 LOG_INFO("thread base_addr has changed !!");
985 /* this is not a current thread */
986 thread_list
->base_addr
= t
->base_addr
;
987 thread_list
->status
= 1;
989 /* we don 't update this field any more */
991 /*thread_list->state = t->state;
992 thread_list->oncpu = t->oncpu;
993 thread_list->asid = t->asid;
996 thread_list
->context
=
997 cpu_context_read(target
,
998 thread_list
->base_addr
,
999 &thread_list
->thread_info_addr
);
1001 /* it is a current thread no need to read context */
1004 linux_os
->thread_count
++;
1009 thread_list
= thread_list
->next
;
1015 fill_task(target
, t
);
1016 get_name(target
, t
);
1017 retval
= insert_into_threadlist(target
, t
);
1018 t
->thread_info_addr
= 0xdeadbeef;
1022 cpu_context_read(target
, t
->base_addr
,
1023 &t
->thread_info_addr
);
1025 base_addr
= next_task(target
, t
);
1026 t
= calloc(1, sizeof(struct threads
));
1027 t
->base_addr
= base_addr
;
1028 linux_os
->thread_count
++;
1030 t
->base_addr
= next_task(target
, t
);
1033 LOG_INFO("update thread done %" PRId64
", mean%" PRId64
"\n",
1034 (timeval_ms() - start
), (timeval_ms() - start
) / loop
);
1036 linux_os
->threads_needs_update
= 0;
1040 int linux_gdb_thread_packet(struct target
*target
,
1041 struct connection
*connection
, char const *packet
,
1045 struct linux_os
*linux_os
=
1046 (struct linux_os
*)target
->rtos
->rtos_specific_params
;
1048 if (linux_os
->init_task_addr
== 0xdeadbeef) {
1049 /* it has not been initialized */
1050 LOG_INFO("received thread request without init task address");
1051 gdb_put_packet(connection
, "l", 1);
1055 retval
= linux_get_tasks(target
, 1);
1057 if (retval
!= ERROR_OK
)
1058 return ERROR_TARGET_FAILURE
;
1060 char *out_str
= calloc(MAX_THREADS
* 17 + 10, 1);
1061 char *tmp_str
= out_str
;
1062 tmp_str
+= sprintf(tmp_str
, "m");
1063 struct threads
*temp
= linux_os
->thread_list
;
1065 while (temp
!= NULL
) {
1066 tmp_str
+= sprintf(tmp_str
, "%016" PRIx64
, temp
->threadid
);
1069 tmp_str
+= sprintf(tmp_str
, ",");
1072 gdb_put_packet(connection
, out_str
, strlen(out_str
));
1077 int linux_gdb_thread_update(struct target
*target
,
1078 struct connection
*connection
, char const *packet
,
1082 struct linux_os
*linux_os
= (struct linux_os
*)
1083 target
->rtos
->rtos_specific_params
;
1084 struct threads
*temp
= linux_os
->thread_list
;
1086 while (temp
!= NULL
) {
1087 if (temp
->threadid
== linux_os
->preupdtate_threadid_count
+ 1) {
1088 /*LOG_INFO("FOUND");*/
1096 /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/
1097 char *out_strr
= calloc(MAX_THREADS
* 17 + 10, 1);
1098 char *tmp_strr
= out_strr
;
1099 tmp_strr
+= sprintf(tmp_strr
, "m");
1100 /*LOG_INFO("CHAR MALLOC & M DONE");*/
1101 tmp_strr
+= sprintf(tmp_strr
, "%016" PRIx64
, temp
->threadid
);
1105 while (temp
!= NULL
) {
1106 /*LOG_INFO("INTO GDB THREAD UPDATE WHILE");*/
1107 tmp_strr
+= sprintf(tmp_strr
, ",");
1109 sprintf(tmp_strr
, "%016" PRIx64
, temp
->threadid
);
1114 gdb_put_packet(connection
, out_strr
, strlen(out_strr
));
1115 linux_os
->preupdtate_threadid_count
=
1116 linux_os
->threadid_count
- 1;
1119 gdb_put_packet(connection
, "l", 1);
1124 int linux_thread_extra_info(struct target
*target
,
1125 struct connection
*connection
, char const *packet
,
1128 int64_t threadid
= 0;
1129 struct linux_os
*linux_os
= (struct linux_os
*)
1130 target
->rtos
->rtos_specific_params
;
1131 sscanf(packet
, "qThreadExtraInfo,%" SCNx64
, &threadid
);
1132 /*LOG_INFO("lookup extra info for thread %" SCNx64, threadid);*/
1133 struct threads
*temp
= linux_os
->thread_list
;
1135 while (temp
!= NULL
) {
1136 if (temp
->threadid
== threadid
) {
1137 char *pid
= " PID: ";
1138 char *pid_current
= "*PID: ";
1139 char *name
= "Name: ";
1140 int str_size
= strlen(pid
) + strlen(name
);
1141 char *tmp_str
= calloc(1, str_size
+ 50);
1142 char *tmp_str_ptr
= tmp_str
;
1144 /* discriminate current task */
1145 if (temp
->status
== 3)
1146 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s",
1149 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%s", pid
);
1151 tmp_str_ptr
+= sprintf(tmp_str_ptr
, "%d, ", (int)temp
->pid
);
1152 sprintf(tmp_str_ptr
, "%s", name
);
1153 sprintf(tmp_str_ptr
, "%s", temp
->name
);
1154 char *hex_str
= calloc(1, strlen(tmp_str
) * 2 + 1);
1155 size_t pkt_len
= hexify(hex_str
, (const uint8_t *)tmp_str
,
1156 strlen(tmp_str
), strlen(tmp_str
) * 2 + 1);
1157 gdb_put_packet(connection
, hex_str
, pkt_len
);
1166 LOG_INFO("thread not found");
1170 int linux_gdb_T_packet(struct connection
*connection
,
1171 struct target
*target
, char const *packet
, int packet_size
)
1174 struct linux_os
*linux_os
= (struct linux_os
*)
1175 target
->rtos
->rtos_specific_params
;
1176 int retval
= ERROR_OK
;
1177 sscanf(packet
, "T%" SCNx64
, &threadid
);
1179 if (linux_os
->threads_needs_update
== 0) {
1180 struct threads
*temp
= linux_os
->thread_list
;
1181 struct threads
*prev
= NULL
;
1183 while (temp
!= NULL
) {
1184 if (temp
->threadid
== threadid
) {
1185 if (temp
->status
!= 0) {
1186 gdb_put_packet(connection
, "OK", 2);
1189 /* delete item in the list */
1190 linux_os
->thread_list
=
1191 liste_del_task(linux_os
->thread_list
,
1193 linux_os
->thread_count
--;
1194 gdb_put_packet(connection
, "E01", 3);
1204 LOG_INFO("gdb requested status on non existing thread");
1205 gdb_put_packet(connection
, "E01", 3);
1209 retval
= linux_task_update(target
, 1);
1210 struct threads
*temp
= linux_os
->thread_list
;
1212 while (temp
!= NULL
) {
1213 if (temp
->threadid
== threadid
) {
1214 if (temp
->status
== 1) {
1215 gdb_put_packet(connection
, "OK", 2);
1218 gdb_put_packet(connection
, "E01", 3);
1230 int linux_gdb_h_packet(struct connection
*connection
,
1231 struct target
*target
, char const *packet
, int packet_size
)
1233 struct linux_os
*linux_os
= (struct linux_os
*)
1234 target
->rtos
->rtos_specific_params
;
1235 struct current_thread
*ct
= linux_os
->current_threads
;
1237 /* select to display the current thread of the selected target */
1238 while ((ct
!= NULL
) && (ct
->core_id
!= target
->coreid
))
1241 int64_t current_gdb_thread_rq
;
1243 if (linux_os
->threads_lookup
== 1) {
1244 if ((ct
!= NULL
) && (ct
->threadid
== -1)) {
1245 ct
= linux_os
->current_threads
;
1247 while ((ct
!= NULL
) && (ct
->threadid
== -1))
1252 /* no current thread can be identified
1253 * any way with smp */
1254 LOG_INFO("no current thread identified");
1255 /* attempt to display the name of the 2 threads identified with
1258 ct
= linux_os
->current_threads
;
1260 while ((ct
!= NULL
) && (ct
->threadid
== -1)) {
1261 t
.base_addr
= ct
->TS
;
1262 get_name(target
, &t
);
1263 LOG_INFO("name of unidentified thread %s",
1268 gdb_put_packet(connection
, "OK", 2);
1272 if (packet
[1] == 'g') {
1273 sscanf(packet
, "Hg%16" SCNx64
, ¤t_gdb_thread_rq
);
1275 if (current_gdb_thread_rq
== 0) {
1276 target
->rtos
->current_threadid
= ct
->threadid
;
1277 gdb_put_packet(connection
, "OK", 2);
1279 target
->rtos
->current_threadid
=
1280 current_gdb_thread_rq
;
1281 gdb_put_packet(connection
, "OK", 2);
1283 } else if (packet
[1] == 'c') {
1284 sscanf(packet
, "Hc%16" SCNx64
, ¤t_gdb_thread_rq
);
1286 if ((current_gdb_thread_rq
== 0) ||
1287 (current_gdb_thread_rq
== ct
->threadid
)) {
1288 target
->rtos
->current_threadid
= ct
->threadid
;
1289 gdb_put_packet(connection
, "OK", 2);
1291 gdb_put_packet(connection
, "E01", 3);
1294 gdb_put_packet(connection
, "OK", 2);
1299 static int linux_thread_packet(struct connection
*connection
, char const *packet
,
1302 int retval
= ERROR_OK
;
1303 struct current_thread
*ct
;
1304 struct target
*target
= get_target_from_connection(connection
);
1305 struct linux_os
*linux_os
= (struct linux_os
*)
1306 target
->rtos
->rtos_specific_params
;
1308 switch (packet
[0]) {
1309 case 'T': /* Is thread alive?*/
1311 linux_gdb_T_packet(connection
, target
, packet
, packet_size
);
1313 case 'H': /* Set current thread */
1314 /* ( 'c' for step and continue, 'g' for all other operations )*/
1315 /*LOG_INFO(" H packet received '%s'", packet);*/
1316 linux_gdb_h_packet(connection
, target
, packet
, packet_size
);
1320 if (strncmp(packet
, "qSymbol", 7) == 0) {
1321 if (rtos_qsymbol(connection
, packet
, packet_size
) == 1) {
1322 linux_compute_virt2phys(target
,
1323 target
->rtos
->symbols
[INIT_TASK
].address
);
1327 } else if (strncmp(packet
, "qfThreadInfo", 12) == 0) {
1328 if (linux_os
->thread_list
== NULL
) {
1329 retval
= linux_gdb_thread_packet(target
,
1335 retval
= linux_gdb_thread_update(target
,
1341 } else if (strncmp(packet
, "qsThreadInfo", 12) == 0) {
1342 gdb_put_packet(connection
, "l", 1);
1344 } else if (strncmp(packet
, "qThreadExtraInfo,", 17) == 0) {
1345 linux_thread_extra_info(target
, connection
, packet
,
1349 retval
= GDB_THREAD_PACKET_NOT_CONSUMED
;
1354 /* previously response was : thread not found
1355 * gdb_put_packet(connection, "E01", 3); */
1356 retval
= GDB_THREAD_PACKET_NOT_CONSUMED
;
1360 if (linux_os
->threads_lookup
== 1) {
1361 ct
= linux_os
->current_threads
;
1363 while ((ct
!= NULL
) && (ct
->core_id
) != target
->coreid
)
1366 if ((ct
!= NULL
) && (ct
->threadid
== -1)) {
1367 ct
= linux_os
->current_threads
;
1369 while ((ct
!= NULL
) && (ct
->threadid
== -1))
1373 if ((ct
!= NULL
) && (ct
->threadid
!=
1374 target
->rtos
->current_threadid
)
1375 && (target
->rtos
->current_threadid
!= -1))
1376 LOG_WARNING("WARNING! current GDB thread do not match "
1377 "current thread running. "
1378 "Switch thread in GDB to threadid %d",
1381 LOG_INFO("threads_needs_update = 1");
1382 linux_os
->threads_needs_update
= 1;
1386 /* if a packet handler returned an error, exit input loop */
1387 if (retval
!= ERROR_OK
)
1394 static int linux_os_smp_init(struct target
*target
)
1396 struct target_list
*head
;
1397 /* keep only target->rtos */
1398 struct rtos
*rtos
= target
->rtos
;
1399 struct linux_os
*os_linux
=
1400 (struct linux_os
*)rtos
->rtos_specific_params
;
1401 struct current_thread
*ct
;
1402 head
= target
->head
;
1404 while (head
!= (struct target_list
*)NULL
) {
1405 if (head
->target
->rtos
!= rtos
) {
1406 struct linux_os
*smp_os_linux
=
1407 (struct linux_os
*)head
->target
->rtos
->rtos_specific_params
;
1408 /* remap smp target on rtos */
1409 free(head
->target
->rtos
);
1410 head
->target
->rtos
= rtos
;
1411 /* reuse allocated ct */
1412 ct
= smp_os_linux
->current_threads
;
1414 ct
->TS
= 0xdeadbeef;
1415 ct
->core_id
= head
->target
->coreid
;
1416 os_linux
->current_threads
=
1417 add_current_thread(os_linux
->current_threads
, ct
);
1418 os_linux
->nr_cpus
++;
1428 static int linux_os_create(struct target
*target
)
1430 struct linux_os
*os_linux
= calloc(1, sizeof(struct linux_os
));
1431 struct current_thread
*ct
= calloc(1, sizeof(struct current_thread
));
1432 LOG_INFO("linux os creation\n");
1433 os_linux
->init_task_addr
= 0xdeadbeef;
1434 os_linux
->name
= "linux";
1435 os_linux
->thread_list
= NULL
;
1436 os_linux
->thread_count
= 0;
1437 target
->rtos
->current_threadid
= -1;
1438 os_linux
->nr_cpus
= 1;
1439 os_linux
->threads_lookup
= 0;
1440 os_linux
->threads_needs_update
= 0;
1441 os_linux
->threadid_count
= 1;
1442 os_linux
->current_threads
= NULL
;
1443 target
->rtos
->rtos_specific_params
= os_linux
;
1444 ct
->core_id
= target
->coreid
;
1446 ct
->TS
= 0xdeadbeef;
1447 os_linux
->current_threads
=
1448 add_current_thread(os_linux
->current_threads
, ct
);
1449 /* overload rtos thread default handler */
1450 target
->rtos
->gdb_thread_packet
= linux_thread_packet
;
1451 /* initialize a default virt 2 phys translation */
1452 os_linux
->phys_mask
= ~0xc0000000;
1453 os_linux
->phys_base
= 0x0;
1457 static char *linux_ps_command(struct target
*target
)
1459 struct linux_os
*linux_os
= (struct linux_os
*)
1460 target
->rtos
->rtos_specific_params
;
1461 int retval
= ERROR_OK
;
1464 if (linux_os
->threads_lookup
== 0)
1465 retval
= linux_get_tasks(target
, 1);
1467 if (linux_os
->threads_needs_update
!= 0)
1468 retval
= linux_task_update(target
, 0);
1471 if (retval
== ERROR_OK
) {
1472 struct threads
*temp
= linux_os
->thread_list
;
1474 LOG_INFO("allocation for %d threads line",
1475 linux_os
->thread_count
);
1476 display
= calloc((linux_os
->thread_count
+ 2) * 80, 1);
1482 tmp
+= sprintf(tmp
, "PID\t\tCPU\t\tASID\t\tNAME\n");
1483 tmp
+= sprintf(tmp
, "---\t\t---\t\t----\t\t----\n");
1485 while (temp
!= NULL
) {
1490 "%" PRId32
"\t\t%" PRId32
"\t\t%" PRIx32
"\t\t%s\n",
1491 temp
->pid
, temp
->oncpu
,
1492 temp
->asid
, temp
->name
);
1496 "%" PRId32
"\t\t%" PRId32
"\t\t%" PRIx32
"\t\t%s\n",
1497 temp
->pid
, temp
->oncpu
,
1498 temp
->asid
, temp
->name
);
1508 display
= calloc(40, 1);
1509 sprintf(display
, "linux_ps_command failed\n");
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)