2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 * Copyright (C) 2009 Matt Fleming
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>
12 void printk_address(unsigned long address
, int reliable
)
14 printk(" [<%p>] %s%pS\n", (void *) address
,
15 reliable
? "" : "? ", (void *) address
);
18 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
20 print_ftrace_graph_addr(unsigned long addr
, void *data
,
21 const struct stacktrace_ops
*ops
,
22 struct thread_info
*tinfo
, int *graph
)
24 struct task_struct
*task
= tinfo
->task
;
25 unsigned long ret_addr
;
26 int index
= task
->curr_ret_stack
;
28 if (addr
!= (unsigned long)return_to_handler
)
31 if (!task
->ret_stack
|| index
< *graph
)
35 ret_addr
= task
->ret_stack
[index
].ret
;
37 ops
->address(data
, ret_addr
, 1);
43 print_ftrace_graph_addr(unsigned long addr
, void *data
,
44 const struct stacktrace_ops
*ops
,
45 struct thread_info
*tinfo
, int *graph
)
50 stack_reader_dump(struct task_struct
*task
, struct pt_regs
*regs
,
51 unsigned long *sp
, const struct stacktrace_ops
*ops
,
54 struct thread_info
*context
;
57 context
= (struct thread_info
*)
58 ((unsigned long)sp
& (~(THREAD_SIZE
- 1)));
60 while (!kstack_end(sp
)) {
61 unsigned long addr
= *sp
++;
63 if (__kernel_text_address(addr
)) {
64 ops
->address(data
, addr
, 1);
66 print_ftrace_graph_addr(addr
, data
, ops
,
72 static int print_trace_stack(void *data
, char *name
)
74 printk("%s <%s> ", (char *)data
, name
);
79 * Print one address/symbol entries per line.
81 static void print_trace_address(void *data
, unsigned long addr
, int reliable
)
84 printk_address(addr
, reliable
);
87 static const struct stacktrace_ops print_trace_ops
= {
88 .stack
= print_trace_stack
,
89 .address
= print_trace_address
,
92 void show_trace(struct task_struct
*tsk
, unsigned long *sp
,
95 if (regs
&& user_mode(regs
))
98 printk("\nCall trace:\n");
100 unwind_stack(tsk
, regs
, sp
, &print_trace_ops
, "");
107 debug_show_held_locks(tsk
);