You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

789 lines
21 KiB

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