2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 * Copyright (C) 2009 Matt Fleming
5 * Copyright (C) 2002 - 2012 Paul Mundt
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
11 #include <linux/kallsyms.h>
12 #include <linux/ftrace.h>
13 #include <linux/debug_locks.h>
14 #include <linux/kdebug.h>
15 #include <linux/export.h>
16 #include <linux/uaccess.h>
17 #include <asm/unwinder.h>
18 #include <asm/stacktrace.h>
20 void dump_mem(const char *str
, unsigned long bottom
, unsigned long top
)
25 printk("%s(0x%08lx to 0x%08lx)\n", str
, bottom
, top
);
27 for (p
= bottom
& ~31; p
< top
; ) {
28 printk("%04lx: ", p
& 0xffff);
30 for (i
= 0; i
< 8; i
++, p
+= 4) {
33 if (p
< bottom
|| p
>= top
)
36 if (__get_user(val
, (unsigned int __user
*)p
)) {
47 void printk_address(unsigned long address
, int reliable
)
49 printk(" [<%p>] %s%pS\n", (void *) address
,
50 reliable
? "" : "? ", (void *) address
);
53 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
55 print_ftrace_graph_addr(unsigned long addr
, void *data
,
56 const struct stacktrace_ops
*ops
,
57 struct thread_info
*tinfo
, int *graph
)
59 struct task_struct
*task
= tinfo
->task
;
60 unsigned long ret_addr
;
61 int index
= task
->curr_ret_stack
;
63 if (addr
!= (unsigned long)return_to_handler
)
66 if (!task
->ret_stack
|| index
< *graph
)
70 ret_addr
= task
->ret_stack
[index
].ret
;
72 ops
->address(data
, ret_addr
, 1);
78 print_ftrace_graph_addr(unsigned long addr
, void *data
,
79 const struct stacktrace_ops
*ops
,
80 struct thread_info
*tinfo
, int *graph
)
85 stack_reader_dump(struct task_struct
*task
, struct pt_regs
*regs
,
86 unsigned long *sp
, const struct stacktrace_ops
*ops
,
89 struct thread_info
*context
;
92 context
= (struct thread_info
*)
93 ((unsigned long)sp
& (~(THREAD_SIZE
- 1)));
95 while (!kstack_end(sp
)) {
96 unsigned long addr
= *sp
++;
98 if (__kernel_text_address(addr
)) {
99 ops
->address(data
, addr
, 1);
101 print_ftrace_graph_addr(addr
, data
, ops
,
107 static int print_trace_stack(void *data
, char *name
)
109 printk("%s <%s> ", (char *)data
, name
);
114 * Print one address/symbol entries per line.
116 static void print_trace_address(void *data
, unsigned long addr
, int reliable
)
118 printk("%s", (char *)data
);
119 printk_address(addr
, reliable
);
122 static const struct stacktrace_ops print_trace_ops
= {
123 .stack
= print_trace_stack
,
124 .address
= print_trace_address
,
127 void show_trace(struct task_struct
*tsk
, unsigned long *sp
,
128 struct pt_regs
*regs
)
130 if (regs
&& user_mode(regs
))
133 printk("\nCall trace:\n");
135 unwind_stack(tsk
, regs
, sp
, &print_trace_ops
, "");
142 debug_show_held_locks(tsk
);
145 void show_stack(struct task_struct
*tsk
, unsigned long *sp
)
152 sp
= (unsigned long *)current_stack_pointer
;
154 sp
= (unsigned long *)tsk
->thread
.sp
;
156 stack
= (unsigned long)sp
;
157 dump_mem("Stack: ", stack
, THREAD_SIZE
+
158 (unsigned long)task_stack_page(tsk
));
159 show_trace(tsk
, sp
, NULL
);