2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Copyright (C) 2013 Richard Weinberger <richrd@nod.at>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/kallsyms.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <asm/sysrq.h>
18 struct stack_frame
*next_frame
;
19 unsigned long return_address
;
22 static void do_stack_trace(unsigned long *sp
, unsigned long bp
)
26 struct stack_frame
*frame
= (struct stack_frame
*)bp
;
28 printk(KERN_INFO
"Call Trace:\n");
29 while (((long) sp
& (THREAD_SIZE
-1)) != 0) {
31 if (__kernel_text_address(addr
)) {
33 if ((unsigned long) sp
== bp
+ sizeof(long)) {
34 frame
= frame
? frame
->next_frame
: NULL
;
35 bp
= (unsigned long)frame
;
39 printk(KERN_INFO
" [<%08lx>]", addr
);
40 printk(KERN_CONT
" %s", reliable
? "" : "? ");
41 print_symbol(KERN_CONT
"%s", addr
);
42 printk(KERN_CONT
"\n");
46 printk(KERN_INFO
"\n");
49 static unsigned long get_frame_pointer(struct task_struct
*task
,
50 struct pt_regs
*segv_regs
)
52 if (!task
|| task
== current
)
53 return segv_regs
? PT_REGS_BP(segv_regs
) : current_bp();
55 return KSTK_EBP(task
);
58 static unsigned long *get_stack_pointer(struct task_struct
*task
,
59 struct pt_regs
*segv_regs
)
61 if (!task
|| task
== current
)
62 return segv_regs
? (unsigned long *)PT_REGS_SP(segv_regs
) : current_sp();
64 return (unsigned long *)KSTK_ESP(task
);
67 void show_stack(struct task_struct
*task
, unsigned long *stack
)
69 unsigned long *sp
= stack
, bp
= 0;
70 struct pt_regs
*segv_regs
= current
->thread
.segv_regs
;
73 if (!segv_regs
&& os_is_signal_stack()) {
74 printk(KERN_ERR
"Received SIGSEGV in SIGSEGV handler,"
75 " aborting stack trace!\n");
79 #ifdef CONFIG_FRAME_POINTER
80 bp
= get_frame_pointer(task
, segv_regs
);
84 sp
= get_stack_pointer(task
, segv_regs
);
86 printk(KERN_INFO
"Stack:\n");
88 for (i
= 0; i
< 3 * STACKSLOTS_PER_LINE
; i
++) {
89 if (kstack_end(stack
))
91 if (i
&& ((i
% STACKSLOTS_PER_LINE
) == 0))
92 printk(KERN_CONT
"\n");
93 printk(KERN_CONT
" %08lx", *stack
++);
95 printk(KERN_CONT
"\n");
97 do_stack_trace(sp
, bp
);