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 10 #include <asm/stacktrace.h> 11 12 void printk_address(unsigned long address, int reliable) 13 { 14 printk(" [<%p>] %s%pS\n", (void *) address, 15 reliable ? "" : "? ", (void *) address); 16 } 17 18 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 19 static void 20 print_ftrace_graph_addr(unsigned long addr, void *data, 21 const struct stacktrace_ops *ops, 22 struct thread_info *tinfo, int *graph) 23 { 24 struct task_struct *task = tinfo->task; 25 unsigned long ret_addr; 26 int index = task->curr_ret_stack; 27 28 if (addr != (unsigned long)return_to_handler) 29 return; 30 31 if (!task->ret_stack || index < *graph) 32 return; 33 34 index -= *graph; 35 ret_addr = task->ret_stack[index].ret; 36 37 ops->address(data, ret_addr, 1); 38 39 (*graph)++; 40 } 41 #else 42 static inline void 43 print_ftrace_graph_addr(unsigned long addr, void *data, 44 const struct stacktrace_ops *ops, 45 struct thread_info *tinfo, int *graph) 46 { } 47 #endif 48 49 /* 50 * Unwind the call stack and pass information to the stacktrace_ops 51 * functions. 52 */ 53 void dump_trace(struct task_struct *task, struct pt_regs *regs, 54 unsigned long *sp, const struct stacktrace_ops *ops, 55 void *data) 56 { 57 struct thread_info *context; 58 int graph = 0; 59 60 context = (struct thread_info *) 61 ((unsigned long)sp & (~(THREAD_SIZE - 1))); 62 63 while (!kstack_end(sp)) { 64 unsigned long addr = *sp++; 65 66 if (__kernel_text_address(addr)) { 67 ops->address(data, addr, 0); 68 69 print_ftrace_graph_addr(addr, data, ops, 70 context, &graph); 71 } 72 } 73 } 74 EXPORT_SYMBOL(dump_trace); 75 76 77 static void 78 print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) 79 { 80 printk(data); 81 print_symbol(msg, symbol); 82 printk("\n"); 83 } 84 85 static void print_trace_warning(void *data, char *msg) 86 { 87 printk("%s%s\n", (char *)data, msg); 88 } 89 90 static int print_trace_stack(void *data, char *name) 91 { 92 printk("%s <%s> ", (char *)data, name); 93 return 0; 94 } 95 96 /* 97 * Print one address/symbol entries per line. 98 */ 99 static void print_trace_address(void *data, unsigned long addr, int reliable) 100 { 101 printk(data); 102 printk_address(addr, reliable); 103 } 104 105 static const struct stacktrace_ops print_trace_ops = { 106 .warning = print_trace_warning, 107 .warning_symbol = print_trace_warning_symbol, 108 .stack = print_trace_stack, 109 .address = print_trace_address, 110 }; 111 112 void show_trace(struct task_struct *tsk, unsigned long *sp, 113 struct pt_regs *regs) 114 { 115 if (regs && user_mode(regs)) 116 return; 117 118 printk("\nCall trace:\n"); 119 120 dump_trace(tsk, regs, sp, &print_trace_ops, ""); 121 122 printk("\n"); 123 124 if (!tsk) 125 tsk = current; 126 127 debug_show_held_locks(tsk); 128 } 129