dumpstack.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Copyright (C) 1991, 1992 Linus Torvalds
  3. * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
  4. * Copyright (C) 2009 Matt Fleming
  5. */
  6. #include <linux/kallsyms.h>
  7. #include <linux/ftrace.h>
  8. #include <linux/debug_locks.h>
  9. #include <asm/unwinder.h>
  10. #include <asm/stacktrace.h>
  11. void printk_address(unsigned long address, int reliable)
  12. {
  13. printk(" [<%p>] %s%pS\n", (void *) address,
  14. reliable ? "" : "? ", (void *) address);
  15. }
  16. #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  17. static void
  18. print_ftrace_graph_addr(unsigned long addr, void *data,
  19. const struct stacktrace_ops *ops,
  20. struct thread_info *tinfo, int *graph)
  21. {
  22. struct task_struct *task = tinfo->task;
  23. unsigned long ret_addr;
  24. int index = task->curr_ret_stack;
  25. if (addr != (unsigned long)return_to_handler)
  26. return;
  27. if (!task->ret_stack || index < *graph)
  28. return;
  29. index -= *graph;
  30. ret_addr = task->ret_stack[index].ret;
  31. ops->address(data, ret_addr, 1);
  32. (*graph)++;
  33. }
  34. #else
  35. static inline void
  36. print_ftrace_graph_addr(unsigned long addr, void *data,
  37. const struct stacktrace_ops *ops,
  38. struct thread_info *tinfo, int *graph)
  39. { }
  40. #endif
  41. void
  42. stack_reader_dump(struct task_struct *task, struct pt_regs *regs,
  43. unsigned long *sp, const struct stacktrace_ops *ops,
  44. void *data)
  45. {
  46. struct thread_info *context;
  47. int graph = 0;
  48. context = (struct thread_info *)
  49. ((unsigned long)sp & (~(THREAD_SIZE - 1)));
  50. while (!kstack_end(sp)) {
  51. unsigned long addr = *sp++;
  52. if (__kernel_text_address(addr)) {
  53. ops->address(data, addr, 1);
  54. print_ftrace_graph_addr(addr, data, ops,
  55. context, &graph);
  56. }
  57. }
  58. }
  59. static int print_trace_stack(void *data, char *name)
  60. {
  61. printk("%s <%s> ", (char *)data, name);
  62. return 0;
  63. }
  64. /*
  65. * Print one address/symbol entries per line.
  66. */
  67. static void print_trace_address(void *data, unsigned long addr, int reliable)
  68. {
  69. printk("%s", (char *)data);
  70. printk_address(addr, reliable);
  71. }
  72. static const struct stacktrace_ops print_trace_ops = {
  73. .stack = print_trace_stack,
  74. .address = print_trace_address,
  75. };
  76. void show_trace(struct task_struct *tsk, unsigned long *sp,
  77. struct pt_regs *regs)
  78. {
  79. if (regs && user_mode(regs))
  80. return;
  81. printk("\nCall trace:\n");
  82. unwind_stack(tsk, regs, sp, &print_trace_ops, "");
  83. printk("\n");
  84. if (!tsk)
  85. tsk = current;
  86. debug_show_held_locks(tsk);
  87. }