stacktrace.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /*
  2. * Stack trace management functions
  3. *
  4. * Copyright IBM Corp. 2006
  5. * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  6. */
  7. #include <linux/sched.h>
  8. #include <linux/sched/debug.h>
  9. #include <linux/stacktrace.h>
  10. #include <linux/kallsyms.h>
  11. #include <linux/export.h>
  12. static int __save_address(void *data, unsigned long address, int nosched)
  13. {
  14. struct stack_trace *trace = data;
  15. if (nosched && in_sched_functions(address))
  16. return 0;
  17. if (trace->skip > 0) {
  18. trace->skip--;
  19. return 0;
  20. }
  21. if (trace->nr_entries < trace->max_entries) {
  22. trace->entries[trace->nr_entries++] = address;
  23. return 0;
  24. }
  25. return 1;
  26. }
  27. static int save_address(void *data, unsigned long address, int reliable)
  28. {
  29. return __save_address(data, address, 0);
  30. }
  31. static int save_address_nosched(void *data, unsigned long address, int reliable)
  32. {
  33. return __save_address(data, address, 1);
  34. }
  35. void save_stack_trace(struct stack_trace *trace)
  36. {
  37. unsigned long sp;
  38. sp = current_stack_pointer();
  39. dump_trace(save_address, trace, NULL, sp);
  40. if (trace->nr_entries < trace->max_entries)
  41. trace->entries[trace->nr_entries++] = ULONG_MAX;
  42. }
  43. EXPORT_SYMBOL_GPL(save_stack_trace);
  44. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  45. {
  46. unsigned long sp;
  47. sp = tsk->thread.ksp;
  48. if (tsk == current)
  49. sp = current_stack_pointer();
  50. dump_trace(save_address_nosched, trace, tsk, sp);
  51. if (trace->nr_entries < trace->max_entries)
  52. trace->entries[trace->nr_entries++] = ULONG_MAX;
  53. }
  54. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
  55. void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
  56. {
  57. unsigned long sp;
  58. sp = kernel_stack_pointer(regs);
  59. dump_trace(save_address, trace, NULL, sp);
  60. if (trace->nr_entries < trace->max_entries)
  61. trace->entries[trace->nr_entries++] = ULONG_MAX;
  62. }
  63. EXPORT_SYMBOL_GPL(save_stack_trace_regs);