unwind.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  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 int
  182. unw_read_encptr (uint8_t enc, const unsigned char **ptr,
  183. uintptr_t pc, uintptr_t *out)
  184. {
  185. const unsigned char *p = *ptr;
  186. if (enc == DW_EH_PE_omit)
  187. {
  188. *out = 0;
  189. return (0);
  190. }
  191. else if (enc == DW_EH_PE_aligned)
  192. {
  193. size_t size = sizeof (uintptr_t) - 1;
  194. p = (const unsigned char *)(((uintptr_t)p + size) & ~size);
  195. if (unw_read_safe ((uintptr_t)p, out) != 0)
  196. return (-EFAULT);
  197. *ptr = p + sizeof (uintptr_t);
  198. return (0);
  199. }
  200. uintptr_t base;
  201. switch (enc & 0x70)
  202. {
  203. case DW_EH_PE_absptr:
  204. base = 0;
  205. break;
  206. case DW_EH_PE_pcrel:
  207. base = pc;
  208. break;
  209. default:
  210. return (-EINVAL);
  211. }
  212. if ((enc & 0x7) == 0)
  213. #ifdef __LP64__
  214. enc |= DW_EH_PE_udata8;
  215. #else
  216. enc |= DW_EH_PE_udata4;
  217. #endif
  218. uintptr_t ret;
  219. switch (enc & 0xf)
  220. {
  221. case DW_EH_PE_uleb128:
  222. ret = base + unw_read_uleb (&p);
  223. break;
  224. case DW_EH_PE_sleb128:
  225. ret = base + unw_read_sleb (&p);
  226. break;
  227. #define UNW_UDATA(type, enc_val) \
  228. case DW_EH_PE_##enc_val: \
  229. { \
  230. type tmp; \
  231. memcpy (&tmp, p, sizeof (tmp)); \
  232. p += sizeof (tmp); \
  233. ret = base + tmp; \
  234. } \
  235. break
  236. UNW_UDATA (uint16_t, udata2);
  237. UNW_UDATA (int16_t, sdata2);
  238. UNW_UDATA (uint32_t, udata4);
  239. UNW_UDATA (int32_t, sdata4);
  240. UNW_UDATA (uint64_t, udata8);
  241. UNW_UDATA (int64_t, sdata8);
  242. #undef UNW_UDATA
  243. default:
  244. return (-EINVAL);
  245. }
  246. if ((enc & DW_EH_PE_indirect) &&
  247. unw_read_safe (ret, &ret) != 0)
  248. return (-EFAULT);
  249. *ptr = p;
  250. *out = ret;
  251. return (0);
  252. }
  253. static int
  254. unw_cursor_set_column (struct unw_cursor *cursor, size_t column,
  255. int rule, uintptr_t val)
  256. {
  257. if (column >= ARRAY_SIZE (cursor->cols.rules))
  258. return (-EFAULT);
  259. cursor->cols.rules[column] = rule;
  260. cursor->cols.values[column].reg = val;
  261. return (0);
  262. }
  263. static uintptr_t
  264. unw_cursor_pc (const struct unw_cursor *cursor)
  265. {
  266. return (cursor->mctx->regs[CPU_UNWIND_PC_REG]);
  267. }
  268. static void
  269. unw_cursor_set_pc (struct unw_cursor *cursor, uintptr_t pc)
  270. {
  271. cursor->mctx->regs[CPU_UNWIND_PC_REG] = pc;
  272. }
  273. static void
  274. unw_cursor_set_sp (struct unw_cursor *cursor, uintptr_t sp)
  275. {
  276. cursor->mctx->regs[UNW_SP_REGISTER] = sp;
  277. }
  278. #define UNW_CURSOR_SET_COLUMN(cursor, column, rule, val) \
  279. do \
  280. { \
  281. int error_ = unw_cursor_set_column (cursor, column, rule, \
  282. (uintptr_t)(val)); \
  283. if (error_) \
  284. return (error_); \
  285. } \
  286. while (0)
  287. static int
  288. unw_run_dw (struct unw_cursor *cursor, const struct unw_cie *cie,
  289. const unsigned char *ops, uintptr_t pc)
  290. {
  291. struct unw_frame_regs free_regs[4];
  292. uint32_t free_idx = 0;
  293. intptr_t sarg;
  294. uintptr_t regno, arg = unw_read_uleb (&ops);
  295. _Auto ops_end = ops + arg;
  296. while (pc < unw_cursor_pc (cursor) && ops < ops_end)
  297. {
  298. uint8_t operand = 0, op = *ops++;
  299. if (op & 0xc0)
  300. {
  301. operand = op & 0x3f;
  302. op &= ~0x3f;
  303. }
  304. switch (op)
  305. {
  306. case DW_CFA_set_loc:
  307. if (unw_read_encptr (cie->code_enc, &ops, pc, &pc) < 0)
  308. return (-1);
  309. break;
  310. case DW_CFA_advance_loc:
  311. pc += operand * cie->code_align;
  312. break;
  313. case DW_CFA_advance_loc1:
  314. pc += (*ops++) * cie->code_align;
  315. break;
  316. case DW_CFA_advance_loc2:
  317. {
  318. uint16_t off;
  319. memcpy (&off, ops, sizeof (off));
  320. ops += sizeof (off);
  321. pc += off * cie->code_align;
  322. break;
  323. }
  324. case DW_CFA_advance_loc4:
  325. {
  326. uint32_t off;
  327. memcpy (&off, ops, sizeof (off));
  328. ops += sizeof (off);
  329. pc += off * cie->code_align;
  330. break;
  331. }
  332. case DW_CFA_def_cfa:
  333. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  334. cursor->cols.cfa.off = unw_read_uleb (&ops);
  335. cursor->cols.cfa.rule = DW_RULE_REG;
  336. break;
  337. case DW_CFA_def_cfa_sf:
  338. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  339. cursor->cols.cfa.off = unw_read_sleb (&ops) * cie->data_align;
  340. cursor->cols.cfa.rule = DW_RULE_REG;
  341. break;
  342. case DW_CFA_def_cfa_offset:
  343. cursor->cols.cfa.off = unw_read_uleb (&ops);
  344. break;
  345. case DW_CFA_def_cfa_register:
  346. cursor->cols.cfa.reg = unw_read_uleb (&ops);
  347. cursor->cols.cfa.rule = DW_RULE_REG;
  348. break;
  349. case DW_CFA_offset:
  350. arg = unw_read_uleb (&ops);
  351. unw_cursor_set_column (cursor, operand, DW_RULE_OFFSET,
  352. arg * cie->data_align);
  353. break;
  354. case DW_CFA_offset_extended:
  355. regno = unw_read_uleb (&ops);
  356. arg = unw_read_uleb (&ops);
  357. unw_cursor_set_column (cursor, regno, DW_RULE_OFFSET,
  358. arg * cie->data_align);
  359. break;
  360. case DW_CFA_offset_extended_sf:
  361. regno = unw_read_uleb (&ops);
  362. sarg = unw_read_sleb (&ops);
  363. unw_cursor_set_column (cursor, regno, DW_RULE_OFFSET,
  364. sarg * cie->data_align);
  365. break;
  366. case DW_CFA_undefined:
  367. case DW_CFA_same_value:
  368. regno = unw_read_uleb (&ops);
  369. unw_cursor_set_column (cursor, regno, op == DW_CFA_undefined ?
  370. DW_RULE_UNDEF : DW_RULE_SAME, 0);
  371. break;
  372. case DW_CFA_register:
  373. regno = unw_read_uleb (&ops);
  374. arg = unw_read_uleb (&ops);
  375. unw_cursor_set_column (cursor, regno, DW_RULE_REG, arg);
  376. break;
  377. case DW_CFA_nop:
  378. break;
  379. case DW_CFA_GNU_args_size:
  380. (void)unw_read_uleb (&ops);
  381. break;
  382. case DW_CFA_remember_state:
  383. if (free_idx >= ARRAY_SIZE (free_regs))
  384. return (-ENOMEM);
  385. free_regs[free_idx++] = cursor->cols;
  386. break;
  387. case DW_CFA_restore_state:
  388. if (! free_idx)
  389. return (-EINVAL);
  390. cursor->cols = free_regs[--free_idx];
  391. break;
  392. case DW_CFA_restore:
  393. if (operand >= ARRAY_SIZE (cursor->cols.rules))
  394. return (-EFAULT);
  395. cursor->cols.rules[operand] = DW_RULE_SAME;
  396. break;
  397. default:
  398. return (-EINVAL);
  399. }
  400. }
  401. return (0);
  402. }
  403. static int
  404. unw_apply_regs (struct unw_cursor *cursor, const struct unw_cie *cie)
  405. {
  406. _Auto cols = &cursor->cols;
  407. // Compute the CFA first, as further expressions may depend on it.
  408. if (cols->cfa.reg >= ARRAY_SIZE (cursor->mctx->regs))
  409. return (-EFAULT);
  410. else if (cols->cfa.rule != DW_RULE_REG)
  411. return (-EINVAL);
  412. uintptr_t *regs = cursor->mctx->regs,
  413. cfa = regs[cols->cfa.reg] + cols->cfa.off;
  414. for (size_t i = 0; i < ARRAY_SIZE (cols->rules); ++i)
  415. switch (cols->rules[i])
  416. {
  417. case DW_RULE_UNDEF:
  418. case DW_RULE_SAME:
  419. break;
  420. case DW_RULE_OFFSET:
  421. if (unw_read_safe (cfa + cols->values[i].off, &regs[i]) != 0)
  422. return (-EFAULT);
  423. break;
  424. case DW_RULE_REG:
  425. {
  426. _Auto rx = cols->values[i].reg;
  427. if (unlikely (rx >= ARRAY_SIZE (cursor->mctx->regs)) ||
  428. unw_read_safe (regs[rx], &regs[i]) != 0)
  429. return (-EFAULT);
  430. break;
  431. }
  432. default:
  433. return (-EINVAL);
  434. }
  435. if (cie->ret_addr >= ARRAY_SIZE (cols->rules))
  436. return (-EINVAL);
  437. else if (cols->rules[cie->ret_addr] == DW_RULE_UNDEF)
  438. {
  439. unw_cursor_set_pc (cursor, 0);
  440. return (0);
  441. }
  442. void *pc = UNW_RA (regs[cie->ret_addr]);
  443. unw_cursor_set_pc (cursor, (uintptr_t)pc);
  444. unw_cursor_set_sp (cursor, cfa);
  445. return (pc != 0);
  446. }
  447. static int
  448. unw_cursor_step (struct unw_cursor *cursor)
  449. {
  450. _Auto gd = unw_globals_ptr;
  451. _Auto fde = unw_fde_lookup (unw_cursor_pc (cursor) - 1, gd);
  452. if (! fde)
  453. return (-1);
  454. uintptr_t initial_loc = fde->base_off + gd->base_addr;
  455. _Auto cie = &gd->cies[fde->idxs & 0xff];
  456. // Run the CIE initialization ops.
  457. int rv = unw_run_dw (cursor, cie, gd->ops + cie->ops_idx, initial_loc);
  458. if (rv < 0)
  459. return (rv);
  460. // Run the FDE ops to unwind the stack.
  461. rv = unw_run_dw (cursor, cie, gd->ops + (fde->idxs >> 8), initial_loc);
  462. if (rv == 0)
  463. // If successful, set the registers to their new values.
  464. rv = unw_apply_regs (cursor, cie);
  465. // Clear the cursor for the next run.
  466. unw_cursor_clear (cursor);
  467. return (rv);
  468. }
  469. int
  470. unw_backtrace (struct unw_mcontext *mctx,
  471. int (*fn) (struct unw_mcontext *, void *), void *arg)
  472. {
  473. struct unw_cursor cursor;
  474. if (! mctx)
  475. {
  476. mctx = alloca (sizeof (*mctx));
  477. cpu_unw_mctx_save (mctx->regs);
  478. }
  479. unw_cursor_init_mctx (&cursor, mctx);
  480. while (1)
  481. {
  482. int error = fn (cursor.mctx, arg);
  483. if (error)
  484. return (error);
  485. else if (unw_cursor_step (&cursor) <= 0)
  486. return (0);
  487. }
  488. }
  489. static int
  490. unw_show_stacktrace (struct unw_mcontext *mctx, void *arg)
  491. {
  492. uintptr_t pc = mctx->regs[CPU_UNWIND_PC_REG];
  493. const struct symbol *sym = symbol_lookup (pc);
  494. uint32_t index = (*(uint32_t *)arg)++;
  495. if (! sym)
  496. printf ("#%02u [%#010lx]\n", index, pc);
  497. else
  498. printf ("#%02u [%#010lx] %s+%#lx/%#lx\n", index, pc,
  499. sym->name, pc - sym->addr, sym->size);
  500. return (0);
  501. }
  502. void
  503. unw_stacktrace (struct unw_mcontext *mctx)
  504. {
  505. uint32_t index = 0;
  506. unw_backtrace (mctx, unw_show_stacktrace, &index);
  507. }
  508. int
  509. (unw_fixup_save) (struct unw_fixup_t *fx, void *frame)
  510. {
  511. fx->sp = (uintptr_t)__builtin_dwarf_cfa ();
  512. fx->bp = (uintptr_t)frame;
  513. fx->pc = (uintptr_t)UNW_RA (__builtin_return_address (0));
  514. struct thread *self = thread_self ();
  515. fx->prev = &self->fixup;
  516. fx->next = *fx->prev;
  517. self->fixup = fx;
  518. return (0);
  519. }
  520. #define unw_cursor_frame(cursor) ((cursor)->mctx->regs[CPU_UNWIND_FRAME_REG])
  521. static int
  522. unw_fixup_step_until (struct unw_fixup_t *fixup, struct unw_cursor *cursor)
  523. {
  524. while (1)
  525. {
  526. if (unw_cursor_frame (cursor) == fixup->bp)
  527. return (0);
  528. else if (unw_cursor_step (cursor) <= 0)
  529. return (-1);
  530. }
  531. }
  532. void
  533. unw_fixup_restore (struct unw_fixup_t *fixup,
  534. struct unw_mcontext *mctx, int retval)
  535. {
  536. struct unw_cursor cursor;
  537. unw_cursor_init_mctx (&cursor, mctx);
  538. if (unw_fixup_step_until (fixup, &cursor) < 0)
  539. return;
  540. unw_cursor_set_pc (&cursor, fixup->pc);
  541. unw_cursor_set_sp (&cursor, fixup->sp);
  542. cpu_unw_mctx_set_frame (cursor.mctx->regs, retval);
  543. __builtin_unreachable ();
  544. }
  545. void
  546. unw_fixup_jmp (struct unw_fixup_t *fixup, int retval)
  547. {
  548. __builtin_unwind_init ();
  549. struct unw_cursor cursor;
  550. struct unw_mcontext mctx;
  551. cpu_unw_mctx_save (mctx.regs);
  552. unw_cursor_init_mctx (&cursor, &mctx);
  553. if (unw_fixup_step_until (fixup, &cursor) == 0)
  554. {
  555. unw_cursor_set_sp (&cursor, fixup->sp);
  556. unw_cursor_set_pc (&cursor, fixup->pc);
  557. cpu_unw_mctx_jmp (cursor.mctx->regs, retval);
  558. }
  559. __builtin_unreachable ();
  560. }