rtos: rename CamelCase symbols
[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 = "hla_target",
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 {
353 .target_name = "arcv2",
354 .pointer_width = 4,
355 .callee_saved_stacking = &arc_callee_saved_stacking,
356 .cpu_saved_nofp_stacking = &arc_cpu_saved_stacking,
357 .get_cpu_state = &zephyr_get_arc_state,
358 },
359 {
360 .target_name = NULL
361 }
362 };
363
364 static const struct symbol_table_elem zephyr_symbol_list[] = {
365 {
366 .symbol_name = "_kernel",
367 .optional = false
368 },
369 {
370 .symbol_name = "_kernel_openocd_offsets",
371 .optional = false
372 },
373 {
374 .symbol_name = "_kernel_openocd_size_t_size",
375 .optional = false
376 },
377 {
378 .symbol_name = "_kernel_openocd_num_offsets",
379 .optional = true
380 },
381 {
382 .symbol_name = NULL
383 }
384 };
385
386 static bool zephyr_detect_rtos(struct target *target)
387 {
388 if (target->rtos->symbols == NULL) {
389 LOG_INFO("Zephyr: no symbols while detecting RTOS");
390 return false;
391 }
392
393 for (enum zephyr_symbol_values symbol = ZEPHYR_VAL__KERNEL;
394 symbol != ZEPHYR_VAL_COUNT; symbol++) {
395 LOG_INFO("Zephyr: does it have symbol %d (%s)?", symbol,
396 target->rtos->symbols[symbol].optional ? "optional" : "mandatory");
397
398 if (target->rtos->symbols[symbol].optional)
399 continue;
400 if (target->rtos->symbols[symbol].address == 0)
401 return false;
402 }
403
404 LOG_INFO("Zephyr: all mandatory symbols found");
405
406 return true;
407 }
408
409 static int zephyr_create(struct target *target)
410 {
411 const char *name;
412
413 name = target_type_name(target);
414
415 LOG_INFO("Zephyr: looking for target: %s", name);
416
417 /* ARC specific, check if EM target has security subsystem
418 * In case of ARC_HAS_SECURE zephyr option enabled
419 * the thread stack contains blink,sec_stat,status32 register
420 * values. If ARC_HAS_SECURE is disabled, only blink and status32
421 * register values are saved on stack. */
422 if (!strcmp(name, "arcv2")) {
423 uint32_t value;
424 struct arc_common *arc = target_to_arc(target);
425 /* Reading SEC_BUILD bcr */
426 CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, ARC_AUX_SEC_BUILD_REG, &value));
427 if (value != 0) {
428 LOG_DEBUG("ARC EM board has security subsystem, changing offsets");
429 arc_cpu_saved[ARC_REG_NUM - 1].offset = 8;
430 /* After reading callee registers in stack
431 * now blink,sec_stat,status32 registers
432 * are located. */
433 arc_cpu_saved_stacking.stack_registers_size = 12;
434 }
435 }
436
437 for (struct zephyr_params *p = zephyr_params_list; p->target_name; p++) {
438 if (!strcmp(p->target_name, name)) {
439 LOG_INFO("Zephyr: target known, params at %p", p);
440 target->rtos->rtos_specific_params = p;
441 return ERROR_OK;
442 }
443 }
444
445 LOG_ERROR("Could not find target in Zephyr compatibility list");
446 return ERROR_FAIL;
447 }
448
449 struct zephyr_array {
450 void *ptr;
451 size_t elements;
452 };
453
454 static void zephyr_array_init(struct zephyr_array *array)
455 {
456 array->ptr = NULL;
457 array->elements = 0;
458 }
459
460 static void zephyr_array_free(struct zephyr_array *array)
461 {
462 free(array->ptr);
463 zephyr_array_init(array);
464 }
465
466 static void *zephyr_array_append(struct zephyr_array *array, size_t size)
467 {
468 if (!(array->elements % 16)) {
469 void *ptr = realloc(array->ptr, (array->elements + 16) * size);
470
471 if (!ptr) {
472 LOG_ERROR("Out of memory");
473 return NULL;
474 }
475
476 array->ptr = ptr;
477 }
478
479 return (unsigned char *)array->ptr + (array->elements++) * size;
480 }
481
482 static void *zephyr_array_detach_ptr(struct zephyr_array *array)
483 {
484 void *ptr = array->ptr;
485
486 zephyr_array_init(array);
487
488 return ptr;
489 }
490
491 static uint32_t zephyr_kptr(const struct rtos *rtos, enum zephyr_offsets off)
492 {
493 const struct zephyr_params *params = rtos->rtos_specific_params;
494
495 return rtos->symbols[ZEPHYR_VAL__KERNEL].address + params->offsets[off];
496 }
497
498 static int zephyr_fetch_thread(const struct rtos *rtos,
499 struct zephyr_thread *thread, uint32_t ptr)
500 {
501 const struct zephyr_params *param = rtos->rtos_specific_params;
502 int retval;
503
504 thread->ptr = ptr;
505
506 retval = target_read_u32(rtos->target, ptr + param->offsets[OFFSET_T_ENTRY],
507 &thread->entry);
508 if (retval != ERROR_OK)
509 return retval;
510
511 retval = target_read_u32(rtos->target,
512 ptr + param->offsets[OFFSET_T_NEXT_THREAD],
513 &thread->next_ptr);
514 if (retval != ERROR_OK)
515 return retval;
516
517 retval = target_read_u32(rtos->target,
518 ptr + param->offsets[OFFSET_T_STACK_POINTER],
519 &thread->stack_pointer);
520 if (retval != ERROR_OK)
521 return retval;
522
523 retval = target_read_u8(rtos->target, ptr + param->offsets[OFFSET_T_STATE],
524 &thread->state);
525 if (retval != ERROR_OK)
526 return retval;
527
528 retval = target_read_u8(rtos->target,
529 ptr + param->offsets[OFFSET_T_USER_OPTIONS],
530 &thread->user_options);
531 if (retval != ERROR_OK)
532 return retval;
533
534 uint8_t prio;
535 retval = target_read_u8(rtos->target,
536 ptr + param->offsets[OFFSET_T_PRIO], &prio);
537 if (retval != ERROR_OK)
538 return retval;
539 thread->prio = prio;
540
541 thread->name[0] = '\0';
542 if (param->offsets[OFFSET_T_NAME] != UNIMPLEMENTED) {
543 retval = target_read_buffer(rtos->target,
544 ptr + param->offsets[OFFSET_T_NAME],
545 sizeof(thread->name) - 1, (uint8_t *)thread->name);
546 if (retval != ERROR_OK)
547 return retval;
548
549 thread->name[sizeof(thread->name) - 1] = '\0';
550 }
551
552 LOG_DEBUG("Fetched thread%" PRIx32 ": {entry@0x%" PRIx32
553 ", state=%" PRIu8 ", useropts=%" PRIu8 ", prio=%" PRId8 "}",
554 ptr, thread->entry, thread->state, thread->user_options, thread->prio);
555
556 return ERROR_OK;
557 }
558
559 static int zephyr_fetch_thread_list(struct rtos *rtos, uint32_t current_thread)
560 {
561 struct zephyr_array thread_array;
562 struct zephyr_thread thread;
563 struct thread_detail *td;
564 int64_t curr_id = -1;
565 uint32_t curr;
566 int retval;
567
568 retval = target_read_u32(rtos->target, zephyr_kptr(rtos, OFFSET_K_THREADS),
569 &curr);
570 if (retval != ERROR_OK) {
571 LOG_ERROR("Could not fetch current thread pointer");
572 return retval;
573 }
574
575 zephyr_array_init(&thread_array);
576
577 for (; curr; curr = thread.next_ptr) {
578 retval = zephyr_fetch_thread(rtos, &thread, curr);
579 if (retval != ERROR_OK)
580 goto error;
581
582 td = zephyr_array_append(&thread_array, sizeof(*td));
583 if (!td)
584 goto error;
585
586 td->threadid = thread.ptr;
587 td->exists = true;
588
589 if (thread.name[0])
590 td->thread_name_str = strdup(thread.name);
591 else
592 td->thread_name_str = alloc_printf("thr_%" PRIx32 "_%" PRIx32,
593 thread.entry, thread.ptr);
594 td->extra_info_str = alloc_printf("prio:%" PRId8 ",useropts:%" PRIu8,
595 thread.prio, thread.user_options);
596 if (!td->thread_name_str || !td->extra_info_str)
597 goto error;
598
599 if (td->threadid == current_thread)
600 curr_id = (int64_t)thread_array.elements - 1;
601 }
602
603 LOG_DEBUG("Got information for %zu threads", thread_array.elements);
604
605 rtos_free_threadlist(rtos);
606
607 rtos->thread_count = (int)thread_array.elements;
608 rtos->thread_details = zephyr_array_detach_ptr(&thread_array);
609
610 rtos->current_threadid = curr_id;
611 rtos->current_thread = current_thread;
612
613 return ERROR_OK;
614
615 error:
616 td = thread_array.ptr;
617 for (size_t i = 0; i < thread_array.elements; i++) {
618 free(td[i].thread_name_str);
619 free(td[i].extra_info_str);
620 }
621
622 zephyr_array_free(&thread_array);
623
624 return ERROR_FAIL;
625 }
626
627 static int zephyr_update_threads(struct rtos *rtos)
628 {
629 struct zephyr_params *param;
630 int retval;
631
632 if (!rtos->rtos_specific_params)
633 return ERROR_FAIL;
634
635 param = (struct zephyr_params *)rtos->rtos_specific_params;
636
637 if (!rtos->symbols) {
638 LOG_ERROR("No symbols for Zephyr");
639 return ERROR_FAIL;
640 }
641
642 if (rtos->symbols[ZEPHYR_VAL__KERNEL].address == 0) {
643 LOG_ERROR("Can't obtain kernel struct from Zephyr");
644 return ERROR_FAIL;
645 }
646
647 if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address == 0) {
648 LOG_ERROR("Please build Zephyr with CONFIG_OPENOCD option set");
649 return ERROR_FAIL;
650 }
651
652 retval = target_read_u8(rtos->target,
653 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_SIZE_T_SIZE].address,
654 &param->size_width);
655 if (retval != ERROR_OK) {
656 LOG_ERROR("Couldn't determine size of size_t from host");
657 return retval;
658 }
659
660 if (param->size_width != 4) {
661 LOG_ERROR("Only size_t of 4 bytes are supported");
662 return ERROR_FAIL;
663 }
664
665 if (rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address) {
666 retval = target_read_u32(rtos->target,
667 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_NUM_OFFSETS].address,
668 &param->num_offsets);
669 if (retval != ERROR_OK) {
670 LOG_ERROR("Couldn't not fetch number of offsets from Zephyr");
671 return retval;
672 }
673
674 if (param->num_offsets <= OFFSET_T_STACK_POINTER) {
675 LOG_ERROR("Number of offsets too small");
676 return ERROR_FAIL;
677 }
678 } else {
679 retval = target_read_u32(rtos->target,
680 rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address,
681 &param->offsets[OFFSET_VERSION]);
682 if (retval != ERROR_OK) {
683 LOG_ERROR("Couldn't not fetch offsets from Zephyr");
684 return retval;
685 }
686
687 if (param->offsets[OFFSET_VERSION] > 1) {
688 LOG_ERROR("Unexpected OpenOCD support version %" PRIu32,
689 param->offsets[OFFSET_VERSION]);
690 return ERROR_FAIL;
691 }
692 switch (param->offsets[OFFSET_VERSION]) {
693 case 0:
694 param->num_offsets = OFFSET_T_STACK_POINTER + 1;
695 break;
696 case 1:
697 param->num_offsets = OFFSET_T_COOP_FLOAT + 1;
698 break;
699 }
700 }
701 /* We can fetch the whole array for version 0, as they're supposed
702 * to grow only */
703 uint32_t address;
704 address = rtos->symbols[ZEPHYR_VAL__KERNEL_OPENOCD_OFFSETS].address;
705 for (size_t i = 0; i < OFFSET_MAX; i++, address += param->size_width) {
706 if (i >= param->num_offsets) {
707 param->offsets[i] = UNIMPLEMENTED;
708 continue;
709 }
710
711 retval = target_read_u32(rtos->target, address, &param->offsets[i]);
712 if (retval != ERROR_OK) {
713 LOG_ERROR("Could not fetch offsets from Zephyr");
714 return ERROR_FAIL;
715 }
716 }
717
718 LOG_DEBUG("Zephyr OpenOCD support version %" PRId32,
719 param->offsets[OFFSET_VERSION]);
720
721 uint32_t current_thread;
722 retval = target_read_u32(rtos->target,
723 zephyr_kptr(rtos, OFFSET_K_CURR_THREAD), &current_thread);
724 if (retval != ERROR_OK) {
725 LOG_ERROR("Could not obtain current thread ID");
726 return retval;
727 }
728
729 retval = zephyr_fetch_thread_list(rtos, current_thread);
730 if (retval != ERROR_OK) {
731 LOG_ERROR("Could not obtain thread list");
732 return retval;
733 }
734
735 return ERROR_OK;
736 }
737
738 static int zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
739 struct rtos_reg **reg_list, int *num_regs)
740 {
741 struct zephyr_params *params;
742 struct rtos_reg *callee_saved_reg_list = NULL;
743 target_addr_t addr;
744 int retval;
745
746 LOG_INFO("Getting thread %" PRId64 " reg list", thread_id);
747
748 if (rtos == NULL)
749 return ERROR_FAIL;
750
751 if (thread_id == 0)
752 return ERROR_FAIL;
753
754 params = rtos->rtos_specific_params;
755 if (params == NULL)
756 return ERROR_FAIL;
757
758 addr = thread_id + params->offsets[OFFSET_T_STACK_POINTER]
759 - params->callee_saved_stacking->register_offsets[0].offset;
760
761 retval = params->get_cpu_state(rtos, &addr, params, callee_saved_reg_list, reg_list, num_regs);
762
763 free(callee_saved_reg_list);
764
765 return retval;
766 }
767
768 static int zephyr_get_symbol_list_to_lookup(struct symbol_table_elem **symbol_list)
769 {
770 *symbol_list = malloc(sizeof(zephyr_symbol_list));
771 if (!*symbol_list) {
772 LOG_ERROR("Out of memory");
773 return ERROR_FAIL;
774 }
775
776 memcpy(*symbol_list, zephyr_symbol_list, sizeof(zephyr_symbol_list));
777 return ERROR_OK;
778 }
779
780 struct rtos_type zephyr_rtos = {
781 .name = "Zephyr",
782
783 .detect_rtos = zephyr_detect_rtos,
784 .create = zephyr_create,
785 .update_threads = zephyr_update_threads,
786 .get_thread_reg_list = zephyr_get_thread_reg_list,
787 .get_symbol_list_to_lookup = zephyr_get_symbol_list_to_lookup,
788 };

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)