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

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)