unwind_prologue.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2022 Loongson Technology Corporation Limited
  4. */
  5. #include <linux/kallsyms.h>
  6. #include <asm/inst.h>
  7. #include <asm/ptrace.h>
  8. #include <asm/unwind.h>
  9. unsigned long unwind_get_return_address(struct unwind_state *state)
  10. {
  11. if (unwind_done(state))
  12. return 0;
  13. else if (state->type)
  14. return state->pc;
  15. else if (state->first)
  16. return state->pc;
  17. return *(unsigned long *)(state->sp);
  18. }
  19. EXPORT_SYMBOL_GPL(unwind_get_return_address);
  20. static bool unwind_by_guess(struct unwind_state *state)
  21. {
  22. struct stack_info *info = &state->stack_info;
  23. unsigned long addr;
  24. for (state->sp += sizeof(unsigned long);
  25. state->sp < info->end;
  26. state->sp += sizeof(unsigned long)) {
  27. addr = *(unsigned long *)(state->sp);
  28. if (__kernel_text_address(addr))
  29. return true;
  30. }
  31. return false;
  32. }
  33. static bool unwind_by_prologue(struct unwind_state *state)
  34. {
  35. struct stack_info *info = &state->stack_info;
  36. union loongarch_instruction *ip, *ip_end;
  37. long frame_ra = -1;
  38. unsigned long frame_size = 0;
  39. unsigned long size, offset, pc = state->pc;
  40. if (state->sp >= info->end || state->sp < info->begin)
  41. return false;
  42. if (!kallsyms_lookup_size_offset(pc, &size, &offset))
  43. return false;
  44. ip = (union loongarch_instruction *)(pc - offset);
  45. ip_end = (union loongarch_instruction *)pc;
  46. while (ip < ip_end) {
  47. if (is_stack_alloc_ins(ip)) {
  48. frame_size = (1 << 12) - ip->reg2i12_format.immediate;
  49. ip++;
  50. break;
  51. }
  52. ip++;
  53. }
  54. if (!frame_size) {
  55. if (state->first)
  56. goto first;
  57. return false;
  58. }
  59. while (ip < ip_end) {
  60. if (is_ra_save_ins(ip)) {
  61. frame_ra = ip->reg2i12_format.immediate;
  62. break;
  63. }
  64. if (is_branch_ins(ip))
  65. break;
  66. ip++;
  67. }
  68. if (frame_ra < 0) {
  69. if (state->first) {
  70. state->sp = state->sp + frame_size;
  71. goto first;
  72. }
  73. return false;
  74. }
  75. if (state->first)
  76. state->first = false;
  77. state->pc = *(unsigned long *)(state->sp + frame_ra);
  78. state->sp = state->sp + frame_size;
  79. return !!__kernel_text_address(state->pc);
  80. first:
  81. state->first = false;
  82. if (state->pc == state->ra)
  83. return false;
  84. state->pc = state->ra;
  85. return !!__kernel_text_address(state->ra);
  86. }
  87. void unwind_start(struct unwind_state *state, struct task_struct *task,
  88. struct pt_regs *regs)
  89. {
  90. memset(state, 0, sizeof(*state));
  91. state->type = UNWINDER_PROLOGUE;
  92. if (regs) {
  93. state->sp = regs->regs[3];
  94. state->pc = regs->csr_era;
  95. state->ra = regs->regs[1];
  96. if (!__kernel_text_address(state->pc))
  97. state->type = UNWINDER_GUESS;
  98. } else if (task && task != current) {
  99. state->sp = thread_saved_fp(task);
  100. state->pc = thread_saved_ra(task);
  101. state->ra = 0;
  102. } else {
  103. state->sp = (unsigned long)__builtin_frame_address(0);
  104. state->pc = (unsigned long)__builtin_return_address(0);
  105. state->ra = 0;
  106. }
  107. state->task = task;
  108. state->first = true;
  109. get_stack_info(state->sp, state->task, &state->stack_info);
  110. if (!unwind_done(state) && !__kernel_text_address(state->pc))
  111. unwind_next_frame(state);
  112. }
  113. EXPORT_SYMBOL_GPL(unwind_start);
  114. bool unwind_next_frame(struct unwind_state *state)
  115. {
  116. struct stack_info *info = &state->stack_info;
  117. struct pt_regs *regs;
  118. unsigned long pc;
  119. if (unwind_done(state))
  120. return false;
  121. do {
  122. switch (state->type) {
  123. case UNWINDER_GUESS:
  124. state->first = false;
  125. if (unwind_by_guess(state))
  126. return true;
  127. break;
  128. case UNWINDER_PROLOGUE:
  129. if (unwind_by_prologue(state))
  130. return true;
  131. if (info->type == STACK_TYPE_IRQ &&
  132. info->end == state->sp) {
  133. regs = (struct pt_regs *)info->next_sp;
  134. pc = regs->csr_era;
  135. if (user_mode(regs) || !__kernel_text_address(pc))
  136. return false;
  137. state->pc = pc;
  138. state->sp = regs->regs[3];
  139. state->ra = regs->regs[1];
  140. state->first = true;
  141. get_stack_info(state->sp, state->task, info);
  142. return true;
  143. }
  144. }
  145. state->sp = info->next_sp;
  146. } while (!get_stack_info(state->sp, state->task, info));
  147. return false;
  148. }
  149. EXPORT_SYMBOL_GPL(unwind_next_frame);