unwind.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*
  2. * Copyright (c) 2022 Agustina Arzille.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <kern/symbol.h>
  19. #include <kern/thread.h>
  20. #include <kern/unwind.h>
  21. #include <machine/cpu.h>
  22. #include <machine/pmap.h>
  23. // Miscelaneous constants used by the DWARF unwinder.
  24. #define DW_EH_PE_absptr 0x00
  25. #define DW_EH_PE_signed 0x09
  26. #define DW_EH_PE_pcrel 0x10
  27. #define DW_EH_PE_aligned 0x50
  28. #define DW_EH_PE_indirect 0x80
  29. #define DW_EH_PE_omit 0xff
  30. // Encoding types for DWARF.
  31. enum
  32. {
  33. DW_EH_PE_uleb128 = 0x01,
  34. DW_EH_PE_udata2,
  35. DW_EH_PE_udata4,
  36. DW_EH_PE_udata8,
  37. DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed,
  38. DW_EH_PE_sdata2,
  39. DW_EH_PE_sdata4,
  40. DW_EH_PE_sdata8
  41. };
  42. // Register save states.
  43. enum
  44. {
  45. DW_RULE_SAME,
  46. DW_RULE_UNDEF,
  47. DW_RULE_OFFSET,
  48. DW_RULE_REG,
  49. };
  50. // DWARF opcodes.
  51. #define DW_CFA_nop 0x00
  52. #define DW_CFA_set_loc 0x01
  53. #define DW_CFA_advance_loc1 0x02
  54. #define DW_CFA_advance_loc2 0x03
  55. #define DW_CFA_advance_loc4 0x04
  56. #define DW_CFA_offset_extended 0x05
  57. #define DW_CFA_undefined 0x07
  58. #define DW_CFA_same_value 0x08
  59. #define DW_CFA_register 0x09
  60. #define DW_CFA_remember_state 0x0a
  61. #define DW_CFA_restore_state 0x0b
  62. #define DW_CFA_def_cfa 0x0c
  63. #define DW_CFA_def_cfa_register 0x0d
  64. #define DW_CFA_def_cfa_offset 0x0e
  65. #define DW_CFA_offset_extended_sf 0x11
  66. #define DW_CFA_def_cfa_sf 0x12
  67. #define DW_CFA_def_cfa_offset_sf 0x13
  68. #define DW_CFA_val_offset 0x14
  69. #define DW_CFA_val_offset_sf 0x15
  70. #define DW_CFA_GNU_args_size 0x2e
  71. #define DW_CFA_advance_loc 0x40
  72. #define DW_CFA_offset 0x80
  73. #define DW_CFA_restore 0xc0
  74. #define UNW_SP_REGISTER __builtin_dwarf_sp_column ()
  75. #define UNW_RA(x) __builtin_extract_return_addr ((void *)(x))
  76. const struct unw_globals *volatile unw_globals_ptr __weak;
  77. /*
  78. * A register save state can be defined in terms of:
  79. * - Another register.
  80. * - An offset within the CFA.
  81. * - An arbitrary expression (Not yet supported).
  82. */
  83. struct unw_frame_regs
  84. {
  85. uint8_t rules[CPU_UNWIND_REGISTERS];
  86. union
  87. {
  88. uint16_t reg;
  89. int16_t off;
  90. } values[CPU_UNWIND_REGISTERS];
  91. struct
  92. {
  93. int rule;
  94. uint16_t reg;
  95. int16_t off;
  96. } cfa;
  97. };
  98. struct unw_cursor
  99. {
  100. struct unw_mcontext *mctx;
  101. struct unw_frame_regs cols;
  102. };
  103. static void
  104. unw_cursor_clear (struct unw_cursor *cursor)
  105. {
  106. memset (&cursor->cols, 0, sizeof (cursor->cols));
  107. }
  108. static void
  109. unw_cursor_init_mctx (struct unw_cursor *cursor, struct unw_mcontext *mctx)
  110. {
  111. unw_cursor_clear (cursor);
  112. cursor->mctx = mctx;
  113. }
  114. static const struct unw_fde*
  115. unw_fde_lookup (uintptr_t pc, const struct unw_globals *globals)
  116. {
  117. if (pc < globals->base_addr)
  118. return (NULL);
  119. uint32_t base = (uint32_t)(pc - globals->base_addr);
  120. const struct unw_fde *fdes = globals->fdes;
  121. // Binary search over the FDE's.
  122. for (uint32_t n = globals->nr_fdes; n > 0; )
  123. {
  124. _Auto fde = &fdes[n / 2];
  125. if (base < fde->base_off)
  126. n /= 2;
  127. else if (base > fde->base_off + fde->addr_range)
  128. {
  129. fdes = fde + 1;
  130. n -= n / 2 + 1;
  131. }
  132. else
  133. return (fde);
  134. }
  135. return (NULL);
  136. }
  137. static uintptr_t
  138. unw_read_uleb (const unsigned char **ptr)
  139. {
  140. // Read an unsigned LEB-128 value and update the source pointer.
  141. const unsigned char *p = *ptr;
  142. for (uintptr_t ret = 0, shift = 0 ; ; shift += 7)
  143. {
  144. uintptr_t byte = *p++;
  145. ret |= (byte & 0x7f) << shift;
  146. if (!(byte & 0x80))
  147. {
  148. *ptr = p;
  149. return (ret);
  150. }
  151. }
  152. }
  153. static intptr_t
  154. unw_read_sleb (const unsigned char **ptr)
  155. {
  156. // Read a signed LEB-128 value and update the source pointer.
  157. intptr_t ret = 0;
  158. uint32_t shift = 0, byte;
  159. const unsigned char *p = *ptr;
  160. do
  161. {
  162. byte = *p++;
  163. ret |= ((uintptr_t)byte & 0x7f) << shift;
  164. shift += 7;
  165. }
  166. while (byte & 0x80);
  167. if (shift < 8 * sizeof (ret) && (byte & 0x40))
  168. ret |= -(((uintptr_t)1) << shift);
  169. *ptr = p;
  170. return (ret);
  171. }
  172. static int
  173. unw_read_safe (uintptr_t addr, uintptr_t *out)
  174. {
  175. if (addr < PMAP_START_KERNEL_ADDRESS ||
  176. addr > PMAP_END_KERNEL_ADDRESS)
  177. return (-EFAULT);
  178. *out = *(uintptr_t *)addr;
  179. return (0);
  180. }
  181. static void
  182. unw_fast_cpy (void *dst, const void *src, size_t size)
  183. {
  184. for (size_t i = 0; i < size; ++i)
  185. ((char *)dst)[i] = ((const char *)src)[i];
  186. }
  187. static int
  188. unw_read_encptr (uint8_t enc, const unsigned char **ptr,
  189. uintptr_t pc, uintptr_t *out)
  190. {
  191. const unsigned char *p = *ptr;
  192. if (enc == DW_EH_PE_omit)
  193. {
  194. *out = 0;
  195. return (0);
  196. }
  197. else if (enc == DW_EH_PE_aligned)
  198. {
  199. size_t size = sizeof (uintptr_t) - 1;
  200. p = (const unsigned char *)(((uintptr_t)p + size) & ~size);
  201. if (unw_read_safe ((uintptr_t)p, out) != 0)
  202. return (-EFAULT);
  203. *ptr = p + sizeof (uintptr_t);
  204. return (0);
  205. }
  206. uintptr_t base;
  207. switch (enc & 0x70)
  208. {
  209. case DW_EH_PE_absptr:
  210. base = 0;
  211. break;
  212. case DW_EH_PE_pcrel:
  213. base = pc;
  214. break;
  215. default:
  216. return (-EINVAL);
  217. }
  218. if ((enc & 0x7) == 0)
  219. #ifdef __LP64__
  220. enc |= DW_EH_PE_udata8;
  221. #else
  222. enc |= DW_EH_PE_udata4;
  223. #endif
  224. uintptr_t ret;
  225. switch (enc & 0xf)
  226. {
  227. case DW_EH_PE_uleb128:
  228. ret = base + unw_read_uleb (&p);
  229. break;
  230. case DW_EH_PE_sleb128:
  231. ret = base + unw_read_sleb (&p);
  232. break;
  233. #define UNW_UDATA(type, enc_val) \
  234. case DW_EH_PE_##enc_val: \
  235. { \
  236. type tmp; \
  237. unw_fast_cpy (&tmp, p, sizeof (tmp)); \
  238. p += sizeof (tmp); \
  239. ret = base + tmp; \
  240. } \
  241. break
  242. UNW_UDATA (uint16_t, udata2);
  243. UNW_UDATA (int16_t, sdata2);
  244. UNW_UDATA (uint32_t, udata4);
  245. UNW_UDATA (int32_t, sdata4);
  246. UNW_UDATA (uint64_t, udata8);
  247. UNW_UDATA (int64_t, sdata8);
  248. #undef UNW_UDATA
  249. default:
  250. return (-EINVAL);
  251. }
  252. if ((enc & DW_EH_PE_indirect) &&
  253. unw_read_safe (ret, &ret) != 0)
  254. return (-EFAULT);
  255. *ptr = p;
  256. *out = ret;
  257. return (0);
  258. }
  259. static int
  260. unw_cursor_set_column (struct unw_cursor *cursor, size_t column,
  261. int rule, uintptr_t val)
  262. {
  263. if (column >= ARRAY_SIZE (cursor->cols.rules))
  264. return (-EFAULT);
  265. cursor->cols.rules[column] = rule;
  266. cursor->cols.values[column].reg = val;
  267. return (0);
  268. }
  269. static uintptr_t
  270. unw_cursor_pc (const struct unw_cursor *cursor)
  271. {
  272. return (cursor->mctx->regs[CPU_UNWIND_PC_REG]);
  273. }
  274. static void
  275. unw_cursor_set_pc (struct unw_cursor *cursor, uintptr_t pc)
  276. {
  277. cursor->mctx->regs[CPU_UNWIND_PC_REG] = pc;
  278. }
  279. static uintptr_t
  280. unw_cursor_sp (const struct unw_cursor *cursor)
  281. {
  282. return (cursor->mctx->regs[UNW_SP_REGISTER]);
  283. }
  284. static void
  285. unw_cursor_set_sp (struct unw_cursor *cursor, uintptr_t sp)
  286. {
  287. cursor->mctx->regs[UNW_SP_REGISTER] = sp;
  288. }
  289. static uintptr_t
  290. unw_cursor_bp (const struct unw_cursor *cursor)
  291. {
  292. return (cursor->mctx->regs[CPU_UNWIND_FRAME_REG]);
  293. }
  294. static void
  295. unw_cursor_set_bp (struct unw_cursor *cursor, uintptr_t bp)
  296. {
  297. cursor->mctx->regs[CPU_UNWIND_FRAME_REG] = bp;
  298. }
  299. #define UNW_CURSOR_SET_COLUMN(cursor, column, rule, val) \
  300. do \
  301. { \
  302. int error_ = unw_cursor_set_column (cursor, column, rule, \
  303. (uintptr_t)(val)); \
  304. if (error_) \
  305. return (error_); \
  306. } \
  307. while (0)
  308. static int
  309. unw_run_dw (struct unw_cursor *cursor, const struct unw_cie *cie,
  310. const unsigned char *ops, uintptr_t pc)
  311. {
  312. struct unw_frame_regs free_regs[4];
  313. uint32_t free_idx = 0;
  314. intptr_t sarg;
  315. uintptr_t regno, arg = unw_read_uleb (&ops);
  316. _Auto ops_end = ops + arg;
  317. while (pc < unw_cursor_pc (cursor) && ops < ops_end)
  318. {
  319. uint8_t operand = 0, op = *ops++;
  320. if (op & 0xc0)
  321. {
  322. operand = op & 0x3f;
  323. op &= ~0x3f;
  324. }
  325. switch (op)
  326. {
  327. case DW_CFA_set_loc:
  328. if (unw_read_encptr (cie->code_enc, &ops, pc, &pc) < 0)
  329. return (-1);
  330. break;
  331. case DW_CFA_advance_loc:
  332. pc += operand * cie->code_align;
  333. break;
  334. case DW_CFA_advance_loc1:
  335. pc += (*ops++) * cie->code_align;
  336. break;
  337. case DW_CFA_advance_loc2:
  338. {
  339. uint16_t off;
  340. unw_fast_cpy (&off, ops, sizeof (off));
  341. ops += sizeof (off);
  342. pc += off * cie->code_align;
  343. break;
  344. }
  345. case DW_CFA_advance_loc4:
  346. {
  347. uint32_t off;
  348. unw_fast_cpy (&off, ops, sizeof (off));
  349. ops += sizeof (off);
  350. pc += off * cie->code_align;
  351. break;
  352. }
  353. case DW_CFA_def_cfa:
  354. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  355. cursor->cols.cfa.off = unw_read_uleb (&ops);
  356. cursor->cols.cfa.rule = DW_RULE_REG;
  357. break;
  358. case DW_CFA_def_cfa_sf:
  359. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  360. cursor->cols.cfa.off = unw_read_sleb (&ops) * cie->data_align;
  361. cursor->cols.cfa.rule = DW_RULE_REG;
  362. break;
  363. case DW_CFA_def_cfa_offset:
  364. cursor->cols.cfa.off = unw_read_uleb (&ops);
  365. break;
  366. case DW_CFA_def_cfa_register:
  367. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  368. cursor->cols.cfa.rule = DW_RULE_REG;
  369. break;
  370. case DW_CFA_offset:
  371. arg = unw_read_uleb (&ops);
  372. unw_cursor_set_column (cursor, operand, DW_RULE_OFFSET,
  373. arg * cie->data_align);
  374. break;
  375. case DW_CFA_offset_extended:
  376. regno = unw_read_uleb (&ops);
  377. arg = unw_read_uleb (&ops);
  378. unw_cursor_set_column (cursor, regno, DW_RULE_OFFSET,
  379. arg * cie->data_align);
  380. break;
  381. case DW_CFA_offset_extended_sf:
  382. regno = unw_read_uleb (&ops);
  383. sarg = unw_read_sleb (&ops);
  384. unw_cursor_set_column (cursor, regno, DW_RULE_OFFSET,
  385. sarg * cie->data_align);
  386. break;
  387. case DW_CFA_undefined:
  388. case DW_CFA_same_value:
  389. regno = unw_read_uleb (&ops);
  390. unw_cursor_set_column (cursor, regno, op == DW_CFA_undefined ?
  391. DW_RULE_UNDEF : DW_RULE_SAME, 0);
  392. break;
  393. case DW_CFA_register:
  394. regno = unw_read_uleb (&ops);
  395. arg = unw_read_uleb (&ops);
  396. unw_cursor_set_column (cursor, regno, DW_RULE_REG, arg);
  397. break;
  398. case DW_CFA_nop:
  399. break;
  400. case DW_CFA_GNU_args_size:
  401. (void)unw_read_uleb (&ops);
  402. break;
  403. case DW_CFA_remember_state:
  404. if (free_idx >= ARRAY_SIZE (free_regs))
  405. return (-ENOMEM);
  406. free_regs[free_idx++] = cursor->cols;
  407. break;
  408. case DW_CFA_restore_state:
  409. if (! free_idx)
  410. return (-EINVAL);
  411. cursor->cols = free_regs[--free_idx];
  412. break;
  413. case DW_CFA_restore:
  414. if (operand >= ARRAY_SIZE (cursor->cols.rules))
  415. return (-EFAULT);
  416. cursor->cols.rules[operand] = DW_RULE_SAME;
  417. break;
  418. default:
  419. return (-EINVAL);
  420. }
  421. }
  422. return (0);
  423. }
  424. static int
  425. unw_apply_regs (struct unw_cursor *cursor, const struct unw_cie *cie)
  426. {
  427. _Auto cols = &cursor->cols;
  428. // Compute the CFA first, as further expressions may depend on it.
  429. if (cols->cfa.rule != DW_RULE_REG)
  430. return (-EINVAL);
  431. else if (cols->cfa.reg >= ARRAY_SIZE (cursor->mctx->regs))
  432. return (-EFAULT);
  433. uintptr_t *regs = cursor->mctx->regs,
  434. cfa = regs[cols->cfa.reg] + cols->cfa.off;
  435. for (size_t i = 0; i < ARRAY_SIZE (cols->rules); ++i)
  436. switch (cols->rules[i])
  437. {
  438. case DW_RULE_UNDEF:
  439. case DW_RULE_SAME:
  440. break;
  441. case DW_RULE_OFFSET:
  442. if (unw_read_safe (cfa + cols->values[i].off, &regs[i]) != 0)
  443. return (-EFAULT);
  444. break;
  445. case DW_RULE_REG:
  446. {
  447. _Auto rx = cols->values[i].reg;
  448. if (unlikely (rx >= ARRAY_SIZE (cursor->mctx->regs)) ||
  449. unw_read_safe (regs[rx], &regs[i]) != 0)
  450. return (-EFAULT);
  451. break;
  452. }
  453. default:
  454. return (-EINVAL);
  455. }
  456. if (cie->ret_addr >= ARRAY_SIZE (cols->rules))
  457. return (-EINVAL);
  458. else if (cols->rules[cie->ret_addr] == DW_RULE_UNDEF)
  459. {
  460. unw_cursor_set_pc (cursor, 0);
  461. return (0);
  462. }
  463. void *pc = UNW_RA (regs[cie->ret_addr]);
  464. unw_cursor_set_pc (cursor, (uintptr_t)pc);
  465. unw_cursor_set_sp (cursor, cfa);
  466. return (pc != 0);
  467. }
  468. static int
  469. unw_cursor_step (struct unw_cursor *cursor)
  470. {
  471. _Auto gd = unw_globals_ptr;
  472. _Auto fde = unw_fde_lookup (unw_cursor_pc (cursor) - 1, gd);
  473. if (! fde)
  474. return (-1);
  475. uintptr_t initial_loc = fde->base_off + gd->base_addr;
  476. _Auto cie = &gd->cies[fde->idxs & 0xff];
  477. // Run the CIE initialization ops.
  478. int rv = unw_run_dw (cursor, cie, gd->ops + cie->ops_idx, initial_loc);
  479. if (rv < 0)
  480. return (rv);
  481. // Run the FDE ops to unwind the stack.
  482. rv = unw_run_dw (cursor, cie, gd->ops + (fde->idxs >> 8), initial_loc);
  483. if (rv == 0)
  484. // If successful, set the registers to their new values.
  485. rv = unw_apply_regs (cursor, cie);
  486. // Clear the cursor for the next run.
  487. unw_cursor_clear (cursor);
  488. return (rv);
  489. }
  490. int
  491. unw_backtrace (struct unw_mcontext *mctx,
  492. int (*fn) (struct unw_mcontext *, void *), void *arg)
  493. {
  494. struct unw_cursor cursor;
  495. if (! mctx)
  496. {
  497. mctx = alloca (sizeof (*mctx));
  498. cpu_unw_mctx_save (mctx->regs);
  499. }
  500. unw_cursor_init_mctx (&cursor, mctx);
  501. while (1)
  502. {
  503. int error = fn (cursor.mctx, arg);
  504. if (error)
  505. return (error);
  506. else if (unw_cursor_step (&cursor) <= 0)
  507. return (0);
  508. }
  509. }
  510. static int
  511. unw_show_stacktrace (struct unw_mcontext *mctx, void *arg)
  512. {
  513. uintptr_t pc = mctx->regs[CPU_UNWIND_PC_REG];
  514. const struct symbol *sym = symbol_lookup (pc);
  515. uint32_t index = (*(uint32_t *)arg)++;
  516. if (! sym)
  517. printf ("#%02u [%#010lx]\n", index, pc);
  518. else
  519. printf ("#%02u [%#010lx] %s+%#lx/%#lx\n", index, pc,
  520. sym->name, pc - sym->addr, sym->size);
  521. return (0);
  522. }
  523. void
  524. unw_stacktrace (struct unw_mcontext *mctx)
  525. {
  526. uint32_t index = 0;
  527. unw_backtrace (mctx, unw_show_stacktrace, &index);
  528. }
  529. int
  530. (unw_fixup_save) (struct unw_fixup_t *fx, void *frame)
  531. {
  532. fx->sp = (uintptr_t)__builtin_dwarf_cfa ();
  533. fx->bp = (uintptr_t)frame;
  534. fx->pc = (uintptr_t)UNW_RA (__builtin_return_address (0));
  535. struct thread *self = thread_self ();
  536. fx->prev = &self->fixup;
  537. fx->next = *fx->prev;
  538. self->fixup = fx;
  539. return (0);
  540. }
  541. static int
  542. unw_fixup_step_until (struct unw_fixup_t *fixup, struct unw_cursor *cursor)
  543. {
  544. while (1)
  545. {
  546. if (unw_cursor_sp (cursor) == fixup->sp ||
  547. (unw_cursor_bp (cursor) == fixup->bp &&
  548. unw_cursor_sp (cursor) > fixup->sp))
  549. return (0);
  550. else if (unw_cursor_step (cursor) <= 0)
  551. return (-1);
  552. }
  553. }
  554. static void
  555. unw_cursor_set_fixup (struct unw_cursor *cursor, const struct unw_fixup_t *fx)
  556. {
  557. unw_cursor_set_pc (cursor, fx->pc);
  558. unw_cursor_set_sp (cursor, fx->sp);
  559. unw_cursor_set_bp (cursor, fx->bp);
  560. }
  561. void
  562. unw_fixup_restore (struct unw_fixup_t *fixup,
  563. struct unw_mcontext *mctx, int retval)
  564. {
  565. struct unw_cursor cursor;
  566. unw_cursor_init_mctx (&cursor, mctx);
  567. if (unw_fixup_step_until (fixup, &cursor) < 0)
  568. return;
  569. unw_cursor_set_fixup (&cursor, fixup);
  570. cpu_unw_mctx_set_frame (cursor.mctx->regs, retval);
  571. __builtin_unreachable ();
  572. }
  573. void
  574. unw_fixup_jmp (struct unw_fixup_t *fixup, int retval)
  575. {
  576. __builtin_unwind_init ();
  577. struct unw_cursor cursor;
  578. struct unw_mcontext mctx;
  579. cpu_unw_mctx_save (mctx.regs);
  580. unw_cursor_init_mctx (&cursor, &mctx);
  581. if (unw_fixup_step_until (fixup, &cursor) == 0)
  582. {
  583. unw_cursor_set_fixup (&cursor, fixup);
  584. cpu_unw_mctx_jmp (cursor.mctx->regs, retval);
  585. }
  586. __builtin_unreachable ();
  587. }