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/sched/debug.h>
15 #include <linux/sched/task_stack.h>
16 #include <linux/kdebug.h>
17 #include <linux/export.h>
18 #include <linux/uaccess.h>
19 #include <asm/unwinder.h>
20 #include <asm/stacktrace.h>
22 void dump_mem(const char *str
, unsigned long bottom
, unsigned long top
)
27 printk("%s(0x%08lx to 0x%08lx)\n", str
, bottom
, top
);
29 for (p
= bottom
& ~31; p
< top
; ) {
30 printk("%04lx: ", p
& 0xffff);
32 for (i
= 0; i
< 8; i
++, p
+= 4) {
35 if (p
< bottom
|| p
>= top
)
38 if (__get_user(val
, (unsigned int __user
*)p
)) {
49 void printk_address(unsigned long address
, int reliable
)
51 printk(" [<%p>] %s%pS\n", (void *) address
,
52 reliable
? "" : "? ", (void *) address
);
55 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
57 print_ftrace_graph_addr(unsigned long addr
, void *data
,
58 const struct stacktrace_ops
*ops
,
59 struct thread_info
*tinfo
, int *graph
)
61 struct task_struct
*task
= tinfo
->task
;
62 unsigned long ret_addr
;
63 int index
= task
->curr_ret_stack
;
65 if (addr
!= (unsigned long)return_to_handler
)
68 if (!task
->ret_stack
|| index
< *graph
)
72 ret_addr
= task
->ret_stack
[index
].ret
;
74 ops
->address(data
, ret_addr
, 1);
80 print_ftrace_graph_addr(unsigned long addr
, void *data
,
81 const struct stacktrace_ops
*ops
,
82 struct thread_info
*tinfo
, int *graph
)
87 stack_reader_dump(struct task_struct
*task
, struct pt_regs
*regs
,
88 unsigned long *sp
, const struct stacktrace_ops
*ops
,
91 struct thread_info
*context
;
94 context
= (struct thread_info
*)
95 ((unsigned long)sp
& (~(THREAD_SIZE
- 1)));
97 while (!kstack_end(sp
)) {
98 unsigned long addr
= *sp
++;
100 if (__kernel_text_address(addr
)) {
101 ops
->address(data
, addr
, 1);
103 print_ftrace_graph_addr(addr
, data
, ops
,
109 static int print_trace_stack(void *data
, char *name
)
111 printk("%s <%s> ", (char *)data
, name
);
116 * Print one address/symbol entries per line.
118 static void print_trace_address(void *data
, unsigned long addr
, int reliable
)
120 printk("%s", (char *)data
);
121 printk_address(addr
, reliable
);
124 static const struct stacktrace_ops print_trace_ops
= {
125 .stack
= print_trace_stack
,
126 .address
= print_trace_address
,
129 void show_trace(struct task_struct
*tsk
, unsigned long *sp
,
130 struct pt_regs
*regs
)
132 if (regs
&& user_mode(regs
))
135 printk("\nCall trace:\n");
137 unwind_stack(tsk
, regs
, sp
, &print_trace_ops
, "");
144 debug_show_held_locks(tsk
);
147 void show_stack(struct task_struct
*tsk
, unsigned long *sp
)
154 sp
= (unsigned long *)current_stack_pointer
;
156 sp
= (unsigned long *)tsk
->thread
.sp
;
158 stack
= (unsigned long)sp
;
159 dump_mem("Stack: ", stack
, THREAD_SIZE
+
160 (unsigned long)task_stack_page(tsk
));
161 show_trace(tsk
, sp
, NULL
);