backtrace.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-06-02 Jesven the first version
  9. */
  10. #include <rtthread.h>
  11. #include <backtrace.h>
  12. #define BT_NESTING_MAX 100
  13. static int unwind_frame(struct bt_frame *frame)
  14. {
  15. unsigned long fp = frame->fp;
  16. if ((fp & 0x7)
  17. #ifdef RT_USING_LWP
  18. || fp < KERNEL_VADDR_START
  19. #endif
  20. )
  21. {
  22. return 1;
  23. }
  24. frame->fp = *(unsigned long *)fp;
  25. frame->pc = *(unsigned long *)(fp + 8);
  26. return 0;
  27. }
  28. static void walk_unwind(unsigned long pc, unsigned long fp)
  29. {
  30. struct bt_frame frame;
  31. unsigned long lr = pc;
  32. int nesting = 0;
  33. frame.fp = fp;
  34. while (nesting < BT_NESTING_MAX)
  35. {
  36. rt_kprintf(" %p", (void *)lr);
  37. if (unwind_frame(&frame))
  38. {
  39. break;
  40. }
  41. lr = frame.pc;
  42. nesting++;
  43. }
  44. }
  45. void backtrace(unsigned long pc, unsigned long lr, unsigned long fp)
  46. {
  47. rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc);
  48. walk_unwind(lr, fp);
  49. rt_kprintf("\n");
  50. }
  51. int rt_backtrace(void)
  52. {
  53. unsigned long pc = (unsigned long)backtrace;
  54. unsigned long ra = (unsigned long)__builtin_return_address(0U);
  55. unsigned long fr = (unsigned long)__builtin_frame_address(0U);
  56. backtrace(pc, ra, fr);
  57. return 0;
  58. }
  59. MSH_CMD_EXPORT_ALIAS(rt_backtrace, bt_test, backtrace test);