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/stacktrace.h>
  9. #include <linux/kallsyms.h>
  10. #include <linux/module.h>
  11. static int __save_address(void *data, unsigned long address, int nosched)
  12. {
  13. struct stack_trace *trace = data;
  14. if (nosched && in_sched_functions(address))
  15. return 0;
  16. if (trace->skip > 0) {
  17. trace->skip--;
  18. return 0;
  19. }
  20. if (trace->nr_entries < trace->max_entries) {
  21. trace->entries[trace->nr_entries++] = address;
  22. return 0;
  23. }
  24. return 1;
  25. }
  26. static int save_address(void *data, unsigned long address, int reliable)
  27. {
  28. return __save_address(data, address, 0);
  29. }
  30. static int save_address_nosched(void *data, unsigned long address, int reliable)
  31. {
  32. return __save_address(data, address, 1);
  33. }
  34. void save_stack_trace(struct stack_trace *trace)
  35. {
  36. unsigned long sp;
  37. sp = current_stack_pointer();
  38. dump_trace(save_address, trace, NULL, sp);
  39. if (trace->nr_entries < trace->max_entries)
  40. trace->entries[trace->nr_entries++] = ULONG_MAX;
  41. }
  42. EXPORT_SYMBOL_GPL(save_stack_trace);
  43. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  44. {
  45. unsigned long sp;
  46. sp = tsk->thread.ksp;
  47. if (tsk == current)
  48. sp = current_stack_pointer();
  49. dump_trace(save_address_nosched, trace, tsk, sp);
  50. if (trace->nr_entries < trace->max_entries)
  51. trace->entries[trace->nr_entries++] = ULONG_MAX;
  52. }
  53. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
  54. void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
  55. {
  56. unsigned long sp;
  57. sp = kernel_stack_pointer(regs);
  58. dump_trace(save_address, trace, NULL, sp);
  59. if (trace->nr_entries < trace->max_entries)
  60. trace->entries[trace->nr_entries++] = ULONG_MAX;
  61. }
  62. EXPORT_SYMBOL_GPL(save_stack_trace_regs);