stacktrace.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * arch/sh/kernel/stacktrace.c
  3. *
  4. * Stack trace management functions
  5. *
  6. * Copyright (C) 2006 - 2008 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/sched.h>
  13. #include <linux/sched/debug.h>
  14. #include <linux/stacktrace.h>
  15. #include <linux/thread_info.h>
  16. #include <linux/module.h>
  17. #include <asm/unwinder.h>
  18. #include <asm/ptrace.h>
  19. #include <asm/stacktrace.h>
  20. static int save_stack_stack(void *data, char *name)
  21. {
  22. return 0;
  23. }
  24. /*
  25. * Save stack-backtrace addresses into a stack_trace buffer.
  26. */
  27. static void save_stack_address(void *data, unsigned long addr, int reliable)
  28. {
  29. struct stack_trace *trace = data;
  30. if (!reliable)
  31. return;
  32. if (trace->skip > 0) {
  33. trace->skip--;
  34. return;
  35. }
  36. if (trace->nr_entries < trace->max_entries)
  37. trace->entries[trace->nr_entries++] = addr;
  38. }
  39. static const struct stacktrace_ops save_stack_ops = {
  40. .stack = save_stack_stack,
  41. .address = save_stack_address,
  42. };
  43. void save_stack_trace(struct stack_trace *trace)
  44. {
  45. unsigned long *sp = (unsigned long *)current_stack_pointer;
  46. unwind_stack(current, NULL, sp, &save_stack_ops, trace);
  47. if (trace->nr_entries < trace->max_entries)
  48. trace->entries[trace->nr_entries++] = ULONG_MAX;
  49. }
  50. EXPORT_SYMBOL_GPL(save_stack_trace);
  51. static void
  52. save_stack_address_nosched(void *data, unsigned long addr, int reliable)
  53. {
  54. struct stack_trace *trace = (struct stack_trace *)data;
  55. if (!reliable)
  56. return;
  57. if (in_sched_functions(addr))
  58. return;
  59. if (trace->skip > 0) {
  60. trace->skip--;
  61. return;
  62. }
  63. if (trace->nr_entries < trace->max_entries)
  64. trace->entries[trace->nr_entries++] = addr;
  65. }
  66. static const struct stacktrace_ops save_stack_ops_nosched = {
  67. .stack = save_stack_stack,
  68. .address = save_stack_address_nosched,
  69. };
  70. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  71. {
  72. unsigned long *sp = (unsigned long *)tsk->thread.sp;
  73. unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace);
  74. if (trace->nr_entries < trace->max_entries)
  75. trace->entries[trace->nr_entries++] = ULONG_MAX;
  76. }
  77. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);