a4c60904b5397d3b3e37776288c6b0ccf08688cf
[openocd.git] / src / rtos / zephyr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2017 by Intel Corporation
5 * Leandro Pereira <leandro.pereira@intel.com>
6 * Daniel Glöckner <dg@emlix.com>*
7 * Copyright (C) 2021 by Synopsys, Inc.
8 * Evgeniy Didin <didin@synopsys.com>
9 ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <helper/time_support.h>
16 #include <jtag/jtag.h>
17
18 #include "helper/log.h"
19 #include "helper/types.h"
20 #include "rtos.h"
21 #include "rtos_standard_stackings.h"
22 #include "target/target.h"
23 #include "target/target_type.h"
24 #include "target/armv7m.h"
25 #include "target/arc.h"
26
27 #define UNIMPLEMENTED 0xFFFFFFFFU
28
29 /* ARC specific defines */
30 #define ARC_AUX_SEC_BUILD_REG 0xdb
31 #define ARC_REG_NUM 38
32
33 /* ARM specific defines */
34 #define ARM_XPSR_OFFSET 28
35
36 struct zephyr_thread {
37 uint32_t ptr, next_ptr;
38 uint32_t entry;
39 uint32_t stack_pointer;
40 uint8_t state;
41 uint8_t user_options;
42 int8_t prio;
43 char name[64];
44 };
45
46 enum zephyr_offsets {
47 OFFSET_VERSION,
48 OFFSET_K_CURR_THREAD,
49 OFFSET_K_THREADS,
50 OFFSET_T_ENTRY,
51 OFFSET_T_NEXT_THREAD,
52 OFFSET_T_STATE,
53 OFFSET_T_USER_OPTIONS,
54 OFFSET_T_PRIO,
55 OFFSET_T_STACK_POINTER,
56 OFFSET_T_NAME,
57 OFFSET_T_ARCH,
58 OFFSET_T_PREEMPT_FLOAT,
59 OFFSET_T_COOP_FLOAT,
60 OFFSET_T_ARM_EXC_RETURN,
61 OFFSET_MAX
62 };
63
64 struct zephyr_params {
65 const char *target_name;
66 uint8_t size_width;
67 uint8_t pointer_width;
68 uint32_t num_offsets;
69 uint32_t offsets[OFFSET_MAX];
70 const struct rtos_register_stacking *callee_saved_stacking;
71 const struct rtos_register_stacking *cpu_saved_nofp_stacking;
72 const struct rtos_register_stacking *cpu_saved_fp_stacking;
73 int (*get_cpu_state)(struct rtos *rtos, target_addr_t *addr,
74 struct zephyr_params *params,
75 struct rtos_reg *callee_saved_reg_list,
76 struct rtos_reg **reg_list, int *num_regs);
77 };
78
79 static const struct stack_register_offset arm_callee_saved[] = {
80 { ARMV7M_R13, 32, 32 },
81 { ARMV7M_R4, 0, 32 },
82 { ARMV7M_R5, 4, 32 },
83 { ARMV7M_R6, 8, 32 },
84 { ARMV7M_R7, 12, 32 },
85 { ARMV7M_R8, 16, 32 },
86 { ARMV7M_R9, 20, 32 },
87 { ARMV7M_R10, 24, 32 },
88 { ARMV7M_R11, 28, 32 },
89 };
90
91 static const struct stack_register_offset arc_callee_saved[] = {
92 { ARC_R13, 0, 32 },
93 { ARC_R14, 4, 32 },
94 { ARC_R15, 8, 32 },
95 { ARC_R16, 12, 32 },
96 { ARC_R17, 16, 32 },
97 { ARC_R18, 20, 32 },
98 { ARC_R19, 24, 32 },
99 { ARC_R20, 28, 32 },
100 { ARC_R21, 32, 32 },
101 { ARC_R22, 36, 32 },
102 { ARC_R23, 40, 32 },
103 { ARC_R24, 44, 32 },
104 { ARC_R25, 48, 32 },
105 { ARC_GP, 52, 32 },
106 { ARC_FP, 56, 32 },
107 { ARC_R30, 60, 32 }
108 };
109 static const struct rtos_register_stacking arm_callee_saved_stacking = {
110 .stack_registers_size = 36,
111 .stack_growth_direction = -1,
112 .num_output_registers = ARRAY_SIZE(arm_callee_saved),
113 .register_offsets = arm_callee_saved,
114 };
115
116 static const struct rtos_register_stacking arc_callee_saved_stacking = {
117 .stack_registers_size = 64,
118 .stack_growth_direction = -1,
119 .num_output_registers = ARRAY_SIZE(arc_callee_saved),
120 .register_offsets = arc_callee_saved,
121 };
122
123 static const struct stack_register_offset arm_cpu_saved[] = {
124 { ARMV7M_R0, 0, 32 },
125 { ARMV7M_R1, 4, 32 },
126 { ARMV7M_R2, 8, 32 },
127 { ARMV7M_R3, 12, 32 },
128 { ARMV7M_R4, -1, 32 },
129 { ARMV7M_R5, -1, 32 },
130 { ARMV7M_R6, -1, 32 },
131 { ARMV7M_R7, -1, 32 },
132 { ARMV7M_R8, -1, 32 },
133 { ARMV7M_R9, -1, 32 },
134 { ARMV7M_R10, -1, 32 },
135 { ARMV7M_R11, -1, 32 },
136 { ARMV7M_R12, 16, 32 },
137 { ARMV7M_R13, -2, 32 },
138 { ARMV7M_R14, 20, 32 },
139 { ARMV7M_PC, 24, 32 },
140 { ARMV7M_XPSR, 28, 32 },
141 };
142
143 static struct stack_register_offset arc_cpu_saved[] = {
144 { ARC_R0, -1, 32 },
145 { ARC_R1, -1, 32 },
146 { ARC_R2, -1, 32 },
147 { ARC_R3, -1, 32 },
148 { ARC_R4, -1, 32 },
149 { ARC_R5, -1, 32 },
150 { ARC_R6, -1, 32 },
151 { ARC_R7, -1, 32 },
152 { ARC_R8, -1, 32 },
153 { ARC_R9, -1, 32 },
154 { ARC_R10, -1, 32 },
155 { ARC_R11, -1, 32 },
156 { ARC_R12, -1, 32 },
157 { ARC_R13, -1, 32 },
158 { ARC_R14, -1, 32 },
159 { ARC_R15, -1, 32 },
160 { ARC_R16, -1, 32 },
161 { ARC_R17, -1, 32 },
162 { ARC_R18, -1, 32 },
163 { ARC_R19, -1, 32 },
164 { ARC_R20, -1, 32 },
165 { ARC_R21, -1, 32 },
166 { ARC_R22, -1, 32 },
167 { ARC_R23, -1, 32 },
168 { ARC_R24, -1, 32 },
169 { ARC_R25, -1, 32 },
170 { ARC_GP, -1, 32 },
171 { ARC_FP, -1, 32 },
172 { ARC_SP, -1, 32 },
173 { ARC_ILINK, -1, 32 },
174 { ARC_R30, -1, 32 },
175 { ARC_BLINK, 0, 32 },
176 { ARC_LP_COUNT, -1, 32 },
177 { ARC_PCL, -1, 32 },
178 { ARC_PC, -1, 32 },
179 { ARC_LP_START, -1, 32 },
180 { ARC_LP_END, -1, 32 },
181 { ARC_STATUS32, 4, 32 }
182 };
183
184
185 enum zephyr_symbol_values {
186 ZEPHYR_VAL__KERNEL,
187 ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS,
188 ZEPHYR_VAL__KERNEL_OPENOCD_SIZE_T_SIZE,
189 ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS,
190 ZEPHYR_VAL_COUNT
191 };
192
193 static target_addr_t zephyr_cortex_m_stack_align(struct target *target,
194 const uint8_t *stack_data,
195 const struct rtos_register_stacking *stacking, target_addr_t stack_ptr)
196 {
197 return rtos_cortex_m_stack_align(target, stack_data, stacking,
198 stack_ptr, ARM_XPSR_OFFSET);
199 }
200
201 static const struct rtos_register_stacking arm_cpu_saved_nofp_stacking = {
202 .stack_registers_size = 32,
203 .stack_growth_direction = -1,
204 .num_output_registers = ARRAY_SIZE(arm_cpu_saved),
205 .calculate_process_stack = zephyr_cortex_m_stack_align,
206 .register_offsets = arm_cpu_saved,
207 };
208
209 static const struct rtos_register_stacking arm_cpu_saved_fp_stacking = {
210 .stack_registers_size = 32 + 18 * 4,
211 .stack_growth_direction = -1,
212 .num_output_registers = ARRAY_SIZE(arm_cpu_saved),
213 .calculate_process_stack = zephyr_cortex_m_stack_align,
214 .register_offsets = arm_cpu_saved,
215 };
216
217 /* stack_registers_size is 8 because besides caller registers
218 * there are only blink and Status32 registers on stack left */
219 static struct rtos_register_stacking arc_cpu_saved_stacking = {
220 .stack_registers_size = 8,
221 .stack_growth_direction = -1,
222 .num_output_registers = ARRAY_SIZE(arc_cpu_saved),
223 .register_offsets = arc_cpu_saved,
224 };
225
226 /* ARCv2 specific implementation */
227 static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,
228 struct zephyr_params *params,
229 struct rtos_reg *callee_saved_reg_list,
230 struct rtos_reg **reg_list, int *num_regs)
231 {
232
233 uint32_t real_stack_addr;
234 int retval = 0;
235 int num_callee_saved_regs;
236 const struct rtos_register_stacking *stacking;
237
238 /* Getting real stack address from Kernel thread struct */
239 retval = target_read_u32(rtos->target, *addr, &real_stack_addr);
240 if (retval != ERROR_OK)
241 return retval;
242
243 /* Getting callee registers */
244 retval = rtos_generic_stack_read(rtos->target,
245 params->callee_saved_stacking,
246 real_stack_addr, &callee_saved_reg_list,
247 &num_callee_saved_regs);
248 if (retval != ERROR_OK)
249 return retval;
250
251 stacking = params->cpu_saved_nofp_stacking;
252
253 /* Getting blink and status32 registers */
254 retval = rtos_generic_stack_read(rtos->target, stacking,
255 real_stack_addr + num_callee_saved_regs * 4,
256 reg_list, num_regs);
257 if (retval != ERROR_OK)
258 return retval;
259
260 for (int i = 0; i < num_callee_saved_regs; i++)
261 buf_cpy(callee_saved_reg_list[i].value,
262 (*reg_list)[callee_saved_reg_list[i].number].value,
263 callee_saved_reg_list[i].size);
264
265 /* The blink, sp, pc offsets in arc_cpu_saved structure may be changed,
266 * but the registers number shall not. So the next code searches the
267 * offsetst of these registers in arc_cpu_saved structure. */
268 unsigned short blink_offset = 0, pc_offset = 0, sp_offset = 0;
269 for (size_t i = 0; i < ARRAY_SIZE(arc_cpu_saved); i++) {
270 if (arc_cpu_saved[i].number == ARC_BLINK)
271 blink_offset = i;
272 if (arc_cpu_saved[i].number == ARC_SP)
273 sp_offset = i;
274 if (arc_cpu_saved[i].number == ARC_PC)
275 pc_offset = i;
276 }
277
278 if (blink_offset == 0 || sp_offset == 0 || pc_offset == 0) {
279 LOG_ERROR("Basic registers offsets are missing, check <arc_cpu_saved> struct");
280 return ERROR_FAIL;
281 }
282
283 /* Put blink value into PC */
284 buf_cpy((*reg_list)[blink_offset].value,
285 (*reg_list)[pc_offset].value, sizeof((*reg_list)[blink_offset].value));
286
287 /* Put address after callee/caller in SP. */
288 int64_t stack_top;
289
290 stack_top = real_stack_addr + num_callee_saved_regs * 4
291 + arc_cpu_saved_stacking.stack_registers_size;
292 buf_cpy(&stack_top, (*reg_list)[sp_offset].value, sizeof(stack_top));
293
294 return retval;
295 }
296
297 /* ARM Cortex-M-specific implementation */
298 static int zephyr_get_arm_state(struct rtos *rtos, target_addr_t *addr,
299 struct zephyr_params *params,
300 struct rtos_reg *callee_saved_reg_list,
301 struct rtos_reg **reg_list, int *num_regs)
302 {
303
304 int retval = 0;
305 int num_callee_saved_regs;
306 const struct rtos_register_stacking *stacking;
307
308 retval = rtos_generic_stack_read(rtos->target,
309 params->callee_saved_stacking,
310 *addr, &callee_saved_reg_list,
311 &num_callee_saved_regs);
312 if (retval != ERROR_OK)
313 return retval;
314
315 *addr = target_buffer_get_u32(rtos->target,
316 callee_saved_reg_list[0].value);
317
318 if (params->offsets[OFFSET_T_PREEMPT_FLOAT] != UNIMPLEMENTED)
319 stacking = params->cpu_saved_fp_stacking;
320 else
321 stacking = params->cpu_saved_nofp_stacking;
322
323 retval = rtos_generic_stack_read(rtos->target, stacking, *addr, reg_list,
324 num_regs);
325 if (retval != ERROR_OK)
326 return retval;
327
328 for (int i = 1; i < num_callee_saved_regs; i++)
329 buf_cpy(callee_saved_reg_list[i].value,
330 (*reg_list)[callee_saved_reg_list[i].number].value,
331 callee_saved_reg_list[i].size);
332 return 0;
333 }
334
335 static struct zephyr_params zephyr_params_list[] = {
336 {
337 .target_name = "cortex_m",
338 .pointer_width = 4,
339 .callee_saved_stacking = &arm_callee_saved_stacking,
340 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
341 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
342 .get_cpu_state = &zephyr_get_arm_state,
343 },
344 {
345 .target_name = "cortex_r4",
346 .pointer_width = 4,
347 .callee_saved_stacking = &arm_callee_saved_stacking,
348 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
349 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
350 .get_cpu_state = &zephyr_get_arm_state,
351 },
352 {
353 .target_name = "hla_target",
354 .pointer_width = 4,
355 .callee_saved_stacking = &arm_callee_saved_stacking,
356 .cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
357 .cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
358 .get_cpu_state = &zephyr_get_arm_state,
359
360 },
361 {
362 .target_name = "arcv2",
363 .pointer_width = 4,
364 .callee_saved_stacking = &arc_callee_saved_stacking,
365 .cpu_saved_nofp_stacking = &arc_cpu_saved_stacking,
366 .get_cpu_state = &zephyr_get_arc_state,
367 },
368 {
369 .target_name = NULL
370 }
371 };
372
373 static const struct symbol_table_elem zephyr_symbol_list[] = {
374 {
375 .symbol_name = "_kernel",
376 .optional = false
377 },
378 {
379 .symbol_name = "_kernel_thread_info_offsets",
380 .optional = false
381 },
382 {
383 .symbol_name = "_kernel_thread_info_size_t_size",
384 .optional = false
385 },
386 {
387 .symbol_name = "_kernel_thread_info_num_offsets",
388 .optional = true
389 },
390 {
391 .symbol_name = NULL
392 }
393 };
394
395 static bool zephyr_detect_rtos(struct target *target)
396 {
397 if (!target->rtos->symbols) {
398 LOG_INFO("Zephyr: no symbols while detecting RTOS");
399 return false;
400 }
401
402 for (enum zephyr_symbol_values symbol = ZEPHYR_VAL__KERNEL;
403 symbol != ZEPHYR_VAL_COUNT; symbol++) {
404 LOG_INFO("Zephyr: does it have symbol %d (%s)?", symbol,
405 target->rtos->symbols[symbol].optional ? "optional" : "mandatory");
406
407 if (target->rtos->symbols[symbol].optional)
408 continue;
409 if (target->rtos->symbols[symbol].address == 0)
410 return false;
411 }
412
413 LOG_INFO("Zephyr: all mandatory symbols found");
414
415 return true;
416 }
417
418 static int zephyr_create(struct target *target)
419 {
420 const char *name;
421
422 name = target_type_name(target);
423
424 LOG_INFO("Zephyr: looking for target: %s", name);
425
426 /* ARC specific, check if EM target has security subsystem
427 * In case of ARC_HAS_SECURE zephyr option enabled
428 * the thread stack contains blink,sec_stat,status32 register
429 * values. If ARC_HAS_SECURE is disabled, only blink and status32
430 * register values are saved on stack. */
431 if (!strcmp(name, "arcv2")) {
432 uint32_t value;
433 struct arc_common *arc = target_to_arc(target);
434 /* Reading SEC_BUILD bcr */
435 CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, ARC_AUX_SEC_BUILD_REG, &value));
436 if (value != 0) {
437 LOG_DEBUG("ARC EM board has security subsystem, changing offsets");
438 arc_cpu_saved[ARC_REG_NUM - 1].offset = 8;
439 /* After reading callee registers in stack
440 * now blink,sec_stat,status32 registers
441 * are located. */
442 arc_cpu_saved_stacking.stack_registers_size = 12;
443 }
444 }
445
446 for (struct zephyr_params *p = zephyr_params_list; p->target_name; p++) {
447 if (!strcmp(p->target_name, name)) {
448 LOG_INFO("Zephyr: target known, params at %p", p);
449 target->rtos->rtos_specific_params = p;
450 return ERROR_OK;
451 }
452 }
453
454 LOG_ERROR("Could not find target in Zephyr compatibility list");
455 return ERROR_FAIL;
456 }
457
458 struct zephyr_array {
459 void *ptr;
460 size_t elements;
461 };
462
463 static void zephyr_array_init(struct zephyr_array *array)
464 {
465 array->ptr = NULL;
466 array->elements = 0;
467 }
468
469 static void zephyr_array_free(struct zephyr_array *array)
470 {
471 free(array->ptr);
472 zephyr_array_init(array);
473 }
474
475 static void *zephyr_array_append(struct zephyr_array *array, size_t size)
476 {
477 if (!(array->elements % 16)) {
478 void *ptr = realloc(array->ptr, (array->elements + 16) * size);
479
480 if (!ptr) {
481 LOG_ERROR("Out of memory");
482 return NULL;
483 }
484
485 array->ptr = ptr;
486 }
487
488 return (unsigned char *)array->ptr + (array->elements++) * size;
489 }
490
491 static void *zephyr_array_detach_ptr(struct zephyr_array *array)
492 {
493 void *ptr = array->ptr;
494
495 zephyr_array_init(array);
496
497 return ptr;
498 }
499
500 static uint32_t zephyr_kptr(const struct rtos *rtos, enum zephyr_offsets off)
501 {
502 const struct zephyr_params *params = rtos->rtos_specific_params;
503
504 return rtos->symbols[ZEPHYR_VAL__KERNEL].address + params->offsets[off];
505 }
506
507 static int zephyr_fetch_thread(const struct rtos *rtos,
508 struct zephyr_thread *thread, uint32_t ptr)
509 {
510 const struct zephyr_params *param = rtos->rtos_specific_params;
511 int retval;
512
513 thread->ptr = ptr;
514
515 retval = target_read_u32(rtos->target, ptr + param->offsets[OFFSET_T_ENTRY],
516 &thread->entry);
517 if (retval != ERROR_OK)
518 return retval;
519
520 retval = target_read_u32(rtos->target,
521 ptr + param->offsets[OFFSET_T_NEXT_THREAD],
522 &thread->next_ptr);
523 if (retval != ERROR_OK)
524 return retval;
525
526 retval = target_read_u32(rtos->target,
527 ptr + param->offsets[OFFSET_T_STACK_POINTER],
528 &thread->stack_pointer);
529 if (retval != ERROR_OK)
530 return retval;
531
532 retval = target_read_u8(rtos->target, ptr + param->offsets[OFFSET_T_STATE],
533 &thread->state);
534 if (retval != ERROR_OK)
535 return retval;
536
537 retval = target_read_u8(rtos->target,
538 ptr + param->offsets[OFFSET_T_USER_OPTIONS],
539 &thread->user_options);
540 if (retval != ERROR_OK)
541 return retval;
542
543 uint8_t prio;
544 retval = target_read_u8(rtos->target,
545 ptr + param->offsets[OFFSET_T_PRIO], &prio);
546 if (retval != ERROR_OK)
547 return retval;
548 thread->prio = prio;
549
550 thread->name[0] = '\0';
551 if (param->offsets[OFFSET_T_NAME] != UNIMPLEMENTED) {
552 retval = target_read_buffer(rtos->target,
553 ptr + param->offsets[OFFSET_T_NAME],
554 sizeof(thread->name) - 1, (uint8_t *)thread->name);
555 if (retval != ERROR_OK)
556 return retval;
557
558 thread->name[sizeof(thread->name) - 1] = '\0';
559 }
560
561 LOG_DEBUG("Fetched thread%" PRIx32 ": {entry@0x%" PRIx32
562 ", state=%" PRIu8 ", useropts=%" PRIu8 ", prio=%" PRId8 "}",
563 ptr, thread->entry, thread->state, thread->user_options, thread->prio);
564
565 return ERROR_OK;
566 }
567
568 static int zephyr_fetch_thread_list(struct rtos *rtos, uint32_t current_thread)
569 {
570 struct zephyr_array thread_array;
571 struct zephyr_thread thread;
572 struct thread_detail *td;
573 int64_t curr_id = -1;
574 uint32_t curr;
575 int retval;
576
577 retval = target_read_u32(rtos->target, zephyr_kptr(rtos, OFFSET_K_THREADS),
578 &curr);
579 if (retval != ERROR_OK) {
580 LOG_ERROR("Could not fetch current thread pointer");
581 return retval;
582 }
583
584 zephyr_array_init(&thread_array);
585
586 for (; curr; curr = thread.next_ptr) {
587 retval = zephyr_fetch_thread(rtos, &thread, curr);
588 if (retval != ERROR_OK)
589 goto error;
590
591 td = zephyr_array_append(&thread_array, sizeof(*td));
592 if (!td)
593 goto error;
594
595 td->threadid = thread.ptr;
596 td->exists = true;
597
598 if (thread.name[0])
599 td->thread_name_str = strdup(thread.name);
600 else
601 td->thread_name_str = alloc_printf("thr_%" PRIx32 "_%" PRIx32,
602 thread.entry, thread.ptr);
603 td->extra_info_str = alloc_printf("prio:%" PRId8 ",useropts:%" PRIu8,
604 thread.prio, thread.user_options);
605 if (!td->thread_name_str || !td->extra_info_str)
606 goto error;
607
608 if (td->threadid == current_thread)
609 curr_id = (int64_t)thread_array.elements - 1;
610 }
611
612 LOG_DEBUG("Got information for %zu threads", thread_array.elements);
613
614 rtos_free_threadlist(rtos);
615
616 rtos->thread_count = (int)thread_array.elements;
617 rtos->thread_details = zephyr_array_detach_ptr(&thread_array);
618
619 rtos->current_threadid = curr_id;
620 rtos->current_thread = current_thread;
621
622 return ERROR_OK;
623
624 error:
625 td = thread_array.ptr;
626 for (size_t i = 0; i < thread_array.elements; i++) {
627 free(td[i].thread_name_str);
628 free(td[i].extra_info_str);
629 }
630
631 zephyr_array_free(&thread_array);
632
633 return ERROR_FAIL;
634 }
635
636 static int zephyr_update_threads(struct rtos *rtos)
637 {
638 struct zephyr_params *param;
639 int retval;
640
641 if (!rtos->rtos_specific_params)
642 return ERROR_FAIL;
643
644 param = (struct zephyr_params *)rtos->rtos_specific_params;
645
646 if (!rtos->symbols) {
647 LOG_ERROR("No symbols for Zephyr");
648 return ERROR_FAIL;
649 }
650
651 if (rtos->symbols[ZEPHYR_VAL__KERNEL].address == 0) {
652 LOG_ERROR("Can't obtain kernel struct from Zephyr");
653 return ERROR_FAIL;
654 }
655
656 if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address == 0) {
657 LOG_ERROR("Please build Zephyr with CONFIG_OPENOCD option set");
658 return ERROR_FAIL;
659 }
660
661 retval = target_read_u8(rtos->target,
662 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_SIZE_T_SIZE].address,
663 &param->size_width);
664 if (retval != ERROR_OK) {
665 LOG_ERROR("Couldn't determine size of size_t from host");
666 return retval;
667 }
668
669 if (param->size_width != 4) {
670 LOG_ERROR("Only size_t of 4 bytes are supported");
671 return ERROR_FAIL;
672 }
673
674 if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address) {
675 retval = target_read_u32(rtos->target,
676 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address,
677 &param->num_offsets);
678 if (retval != ERROR_OK) {
679 LOG_ERROR("Couldn't not fetch number of offsets from Zephyr");
680 return retval;
681 }
682
683 if (param->num_offsets <= OFFSET_T_STACK_POINTER) {
684 LOG_ERROR("Number of offsets too small");
685 return ERROR_FAIL;
686 }
687 } else {
688 retval = target_read_u32(rtos->target,
689 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address,
690 &param->offsets[OFFSET_VERSION]);
691 if (retval != ERROR_OK) {
692 LOG_ERROR("Couldn't not fetch offsets from Zephyr");
693 return retval;
694 }
695
696 if (param->offsets[OFFSET_VERSION] > 1) {
697 LOG_ERROR("Unexpected OpenOCD support version %" PRIu32,
698 param->offsets[OFFSET_VERSION]);
699 return ERROR_FAIL;
700 }
701 switch (param->offsets[OFFSET_VERSION]) {
702 case 0:
703 param->num_offsets = OFFSET_T_STACK_POINTER + 1;
704 break;
705 case 1:
706 param->num_offsets = OFFSET_T_COOP_FLOAT + 1;
707 break;
708 }
709 }
710 /* We can fetch the whole array for version 0, as they're supposed
711 * to grow only */
712 uint32_t address;
713 address = rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address;
714 for (size_t i = 0; i < OFFSET_MAX; i++, address += param->size_width) {
715 if (i >= param->num_offsets) {
716 param->offsets[i] = UNIMPLEMENTED;
717 continue;
718 }
719
720 retval = target_read_u32(rtos->target, address, &param->offsets[i]);
721 if (retval != ERROR_OK) {
722 LOG_ERROR("Could not fetch offsets from Zephyr");
723 return ERROR_FAIL;
724 }
725 }
726
727 LOG_DEBUG("Zephyr OpenOCD support version %" PRId32,
728 param->offsets[OFFSET_VERSION]);
729
730 uint32_t current_thread;
731 retval = target_read_u32(rtos->target,
732 zephyr_kptr(rtos, OFFSET_K_CURR_THREAD), &current_thread);
733 if (retval != ERROR_OK) {
734 LOG_ERROR("Could not obtain current thread ID");
735 return retval;
736 }
737
738 retval = zephyr_fetch_thread_list(rtos, current_thread);
739 if (retval != ERROR_OK) {
740 LOG_ERROR("Could not obtain thread list");
741 return retval;
742 }
743
744 return ERROR_OK;
745 }
746
747 static int zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
748 struct rtos_reg **reg_list, int *num_regs)
749 {
750 struct zephyr_params *params;
751 struct rtos_reg *callee_saved_reg_list = NULL;
752 target_addr_t addr;
753 int retval;
754
755 LOG_INFO("Getting thread %" PRId64 " reg list", thread_id);
756
757 if (!rtos)
758 return ERROR_FAIL;
759
760 if (thread_id == 0)
761 return ERROR_FAIL;
762
763 params = rtos->rtos_specific_params;
764 if (!params)
765 return ERROR_FAIL;
766
767 addr = thread_id + params->offsets[OFFSET_T_STACK_POINTER]
768 - params->callee_saved_stacking->register_offsets[0].offset;
769
770 retval = params->get_cpu_state(rtos, &addr, params, callee_saved_reg_list, reg_list, num_regs);
771
772 free(callee_saved_reg_list);
773
774 return retval;
775 }
776
777 static int zephyr_get_symbol_list_to_lookup(struct symbol_table_elem **symbol_list)
778 {
779 *symbol_list = malloc(sizeof(zephyr_symbol_list));
780 if (!*symbol_list) {
781 LOG_ERROR("Out of memory");
782 return ERROR_FAIL;
783 }
784
785 memcpy(*symbol_list, zephyr_symbol_list, sizeof(zephyr_symbol_list));
786 return ERROR_OK;
787 }
788
789 const struct rtos_type zephyr_rtos = {
790 .name = "Zephyr",
791
792 .detect_rtos = zephyr_detect_rtos,
793 .create = zephyr_create,
794 .update_threads = zephyr_update_threads,
795 .get_thread_reg_list = zephyr_get_thread_reg_list,
796 .get_symbol_list_to_lookup = zephyr_get_symbol_list_to_lookup,
797 };

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)