stacktrace.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * arch/sh/kernel/stacktrace.c
  4. *
  5. * Stack trace management functions
  6. *
  7. * Copyright (C) 2006 - 2008 Paul Mundt
  8. */
  9. #include <linux/sched.h>
  10. #include <linux/sched/debug.h>
  11. #include <linux/stacktrace.h>
  12. #include <linux/thread_info.h>
  13. #include <linux/module.h>
  14. #include <asm/unwinder.h>
  15. #include <asm/ptrace.h>
  16. #include <asm/stacktrace.h>
  17. /*
  18. * Save stack-backtrace addresses into a stack_trace buffer.
  19. */
  20. static void save_stack_address(void *data, unsigned long addr, int reliable)
  21. {
  22. struct stack_trace *trace = data;
  23. if (!reliable)
  24. return;
  25. if (trace->skip > 0) {
  26. trace->skip--;
  27. return;
  28. }
  29. if (trace->nr_entries < trace->max_entries)
  30. trace->entries[trace->nr_entries++] = addr;
  31. }
  32. static const struct stacktrace_ops save_stack_ops = {
  33. .address = save_stack_address,
  34. };
  35. void save_stack_trace(struct stack_trace *trace)
  36. {
  37. unsigned long *sp = (unsigned long *)current_stack_pointer;
  38. unwind_stack(current, NULL, sp, &save_stack_ops, trace);
  39. }
  40. EXPORT_SYMBOL_GPL(save_stack_trace);
  41. static void
  42. save_stack_address_nosched(void *data, unsigned long addr, int reliable)
  43. {
  44. struct stack_trace *trace = (struct stack_trace *)data;
  45. if (!reliable)
  46. return;
  47. if (in_sched_functions(addr))
  48. return;
  49. if (trace->skip > 0) {
  50. trace->skip--;
  51. return;
  52. }
  53. if (trace->nr_entries < trace->max_entries)
  54. trace->entries[trace->nr_entries++] = addr;
  55. }
  56. static const struct stacktrace_ops save_stack_ops_nosched = {
  57. .address = save_stack_address_nosched,
  58. };
  59. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  60. {
  61. unsigned long *sp = (unsigned long *)tsk->thread.sp;
  62. unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace);
  63. }
  64. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);