stacktrace.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /*
  2. * Stack trace management functions
  3. *
  4. * Copyright (C) 2009 Helge Deller <deller@gmx.de>
  5. * based on arch/x86/kernel/stacktrace.c by Ingo Molnar <mingo@redhat.com>
  6. * and parisc unwind functions by Randolph Chung <tausq@debian.org>
  7. *
  8. * TODO: Userspace stacktrace (CONFIG_USER_STACKTRACE_SUPPORT)
  9. */
  10. #include <linux/module.h>
  11. #include <linux/stacktrace.h>
  12. #include <asm/unwind.h>
  13. static void dump_trace(struct task_struct *task, struct stack_trace *trace)
  14. {
  15. struct unwind_frame_info info;
  16. /* initialize unwind info */
  17. if (task == current) {
  18. unsigned long sp;
  19. struct pt_regs r;
  20. HERE:
  21. asm volatile ("copy %%r30, %0" : "=r"(sp));
  22. memset(&r, 0, sizeof(struct pt_regs));
  23. r.iaoq[0] = (unsigned long)&&HERE;
  24. r.gr[2] = (unsigned long)__builtin_return_address(0);
  25. r.gr[30] = sp;
  26. unwind_frame_init(&info, task, &r);
  27. } else {
  28. unwind_frame_init_from_blocked_task(&info, task);
  29. }
  30. /* unwind stack and save entries in stack_trace struct */
  31. trace->nr_entries = 0;
  32. while (trace->nr_entries < trace->max_entries) {
  33. if (unwind_once(&info) < 0 || info.ip == 0)
  34. break;
  35. if (__kernel_text_address(info.ip))
  36. trace->entries[trace->nr_entries++] = info.ip;
  37. }
  38. }
  39. /*
  40. * Save stack-backtrace addresses into a stack_trace buffer.
  41. */
  42. void save_stack_trace(struct stack_trace *trace)
  43. {
  44. dump_trace(current, trace);
  45. if (trace->nr_entries < trace->max_entries)
  46. trace->entries[trace->nr_entries++] = ULONG_MAX;
  47. }
  48. EXPORT_SYMBOL_GPL(save_stack_trace);
  49. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  50. {
  51. dump_trace(tsk, trace);
  52. if (trace->nr_entries < trace->max_entries)
  53. trace->entries[trace->nr_entries++] = ULONG_MAX;
  54. }
  55. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);