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 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 void 50 stack_reader_dump(struct task_struct *task, struct pt_regs *regs, 51 unsigned long *sp, const struct stacktrace_ops *ops, 52 void *data) 53 { 54 struct thread_info *context; 55 int graph = 0; 56 57 context = (struct thread_info *) 58 ((unsigned long)sp & (~(THREAD_SIZE - 1))); 59 60 while (!kstack_end(sp)) { 61 unsigned long addr = *sp++; 62 63 if (__kernel_text_address(addr)) { 64 ops->address(data, addr, 1); 65 66 print_ftrace_graph_addr(addr, data, ops, 67 context, &graph); 68 } 69 } 70 } 71 72 static int print_trace_stack(void *data, char *name) 73 { 74 printk("%s <%s> ", (char *)data, name); 75 return 0; 76 } 77 78 /* 79 * Print one address/symbol entries per line. 80 */ 81 static void print_trace_address(void *data, unsigned long addr, int reliable) 82 { 83 printk(data); 84 printk_address(addr, reliable); 85 } 86 87 static const struct stacktrace_ops print_trace_ops = { 88 .stack = print_trace_stack, 89 .address = print_trace_address, 90 }; 91 92 void show_trace(struct task_struct *tsk, unsigned long *sp, 93 struct pt_regs *regs) 94 { 95 if (regs && user_mode(regs)) 96 return; 97 98 printk("\nCall trace:\n"); 99 100 unwind_stack(tsk, regs, sp, &print_trace_ops, ""); 101 102 printk("\n"); 103 104 if (!tsk) 105 tsk = current; 106 107 debug_show_held_locks(tsk); 108 } 109