1
0

backtrace.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-10-18 Shell Add backtrace support
  9. */
  10. #define DBG_TAG "hw.backtrace"
  11. #define DBG_LVL DBG_INFO
  12. #include <rtdbg.h>
  13. #include <rtthread.h>
  14. #include <mm_aspace.h>
  15. #include "riscv_mmu.h"
  16. #define WORD sizeof(rt_base_t)
  17. #define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id)))
  18. rt_inline rt_err_t _bt_kaddr(rt_ubase_t *fp, struct rt_hw_backtrace_frame *frame)
  19. {
  20. rt_err_t rc;
  21. frame->fp = *(fp - 2);
  22. frame->pc = *(fp - 1);
  23. if ((rt_ubase_t)fp == frame->fp)
  24. {
  25. rc = -RT_ERROR;
  26. }
  27. else
  28. {
  29. rc = RT_EOK;
  30. }
  31. return rc;
  32. }
  33. #ifdef RT_USING_SMART
  34. #include <lwp_arch.h>
  35. #include <lwp_user_mm.h>
  36. rt_inline rt_err_t _bt_uaddr(rt_lwp_t lwp, rt_ubase_t *fp, struct rt_hw_backtrace_frame *frame)
  37. {
  38. rt_err_t rc;
  39. if (lwp_data_get(lwp, &frame->fp, fp - 2, WORD) != WORD)
  40. {
  41. rc = -RT_EFAULT;
  42. }
  43. else if (lwp_data_get(lwp, &frame->pc, fp - 1, WORD) != WORD)
  44. {
  45. rc = -RT_EFAULT;
  46. }
  47. else if ((rt_ubase_t)fp == frame->fp)
  48. {
  49. rc = -RT_ERROR;
  50. }
  51. else
  52. {
  53. frame->pc -= 0;
  54. rc = RT_EOK;
  55. }
  56. return rc;
  57. }
  58. #endif /* RT_USING_SMART */
  59. rt_err_t rt_hw_backtrace_frame_unwind(rt_thread_t thread, struct rt_hw_backtrace_frame *frame)
  60. {
  61. rt_err_t rc = -RT_ERROR;
  62. rt_ubase_t *fp = (rt_ubase_t *)frame->fp;
  63. if (fp && !((long)fp & 0x7))
  64. {
  65. #ifdef RT_USING_SMART
  66. if (thread->lwp)
  67. {
  68. void *lwp = thread->lwp;
  69. void *this_lwp = lwp_self();
  70. if (this_lwp == lwp && rt_hw_mmu_v2p(lwp, fp) != ARCH_MAP_FAILED)
  71. {
  72. rc = _bt_kaddr(fp, frame);
  73. }
  74. else if (lwp_user_accessible_ext(lwp, (void *)fp, WORD))
  75. {
  76. rc = _bt_uaddr(lwp, fp, frame);
  77. }
  78. else
  79. {
  80. rc = -RT_EFAULT;
  81. }
  82. }
  83. else
  84. #endif
  85. if ((rt_kmem_v2p(fp) != ARCH_MAP_FAILED))
  86. {
  87. rc = _bt_kaddr(fp, frame);
  88. }
  89. else
  90. {
  91. rc = -RT_EINVAL;
  92. }
  93. }
  94. else
  95. {
  96. rc = -RT_EFAULT;
  97. }
  98. return rc;
  99. }
  100. rt_err_t rt_hw_backtrace_frame_get(rt_thread_t thread, struct rt_hw_backtrace_frame *frame)
  101. {
  102. rt_err_t rc;
  103. if (!thread || !frame)
  104. {
  105. rc = -RT_EINVAL;
  106. }
  107. else
  108. {
  109. frame->pc = ARCH_CONTEXT_FETCH(thread->sp, 13);
  110. frame->fp = ARCH_CONTEXT_FETCH(thread->sp, 12);
  111. rc = RT_EOK;
  112. }
  113. return rc;
  114. }