backtrace.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. int backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs, size_t nr_slots)
  7. {
  8. size_t nr_pcs = 0;
  9. while (fp && nr_pcs < nr_slots) {
  10. /* could put some sanity checks in here... */
  11. pcs[nr_pcs++] = pc;
  12. //iprint("PC %p FP %p\n", pc, fp);
  13. if (fp < KTZERO)
  14. break;
  15. /* PC becomes the retaddr - 1. the -1 is to put our PC back inside the
  16. * function that called us. this was necessary in case we called as the
  17. * last instruction in a function (would have to never return). not
  18. * sure how necessary this still is. */
  19. pc = *(uintptr_t*)(fp + sizeof(uintptr_t)) - 1;
  20. fp = *(uintptr_t*)fp;
  21. }
  22. return nr_pcs;
  23. }
  24. #if 0
  25. void backtrace_frame(uintptr_t eip, uintptr_t ebp)
  26. {
  27. char *func_name;
  28. #define MAX_BT_DEPTH 20
  29. uintptr_t pcs[MAX_BT_DEPTH];
  30. size_t nr_pcs = backtrace_list(eip, ebp, pcs, MAX_BT_DEPTH);
  31. for (int i = 0; i < nr_pcs; i++) {
  32. func_name = get_fn_name(pcs[i]);
  33. print("#%02d [<%p>] in %s\n", i + 1, pcs[i], func_name);
  34. kfree(func_name);
  35. }
  36. }
  37. void backtrace(void)
  38. {
  39. uintptr_t ebp, eip;
  40. ebp = read_bp();
  41. /* retaddr is right above ebp on the stack. we subtract an additional 1 to
  42. * make sure the eip we get is actually in the function that called us.
  43. * i had a couple cases early on where call was the last instruction in a
  44. * function, and simply reading the retaddr would point into another
  45. * function (the next one in the object) */
  46. eip = *(uintptr_t*)(ebp + sizeof(uintptr_t)) - 1;
  47. /* jump back a frame (out of backtrace) */
  48. ebp = *(uintptr_t*)ebp;
  49. printk("Stack Backtrace on Core %d:\n", core_id());
  50. backtrace_frame(eip, ebp);
  51. }
  52. #endif