diff options
author | Franck Bui-Huu <vagabon.xyz@gmail.com> | 2006-08-03 03:29:21 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-09-27 08:37:29 -0400 |
commit | 4d157d5eac29d7d5559fdcabf20f3961bc5cb3e7 (patch) | |
tree | 82662abbe473e5bd0be973e2a8ceb8b63082da55 /arch/mips/kernel/traps.c | |
parent | 0cceb4aa9acf6192a5f02134e764b1feeea8b9de (diff) |
[MIPS] Improve unwind_stack()
This patch allows unwind_stack() to return ra for leaf function.
But it tries to detects cases where get_frame_info() wrongly
consider nested function as a leaf one.
It also pass 'unsinged long *sp' instead of 'unsigned long **sp'
as second parameter. The code looks cleaner.
Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 303f00843021..ab77034921c4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -74,8 +74,9 @@ void (*board_ejtag_handler_setup)(void); | |||
74 | void (*board_bind_eic_interrupt)(int irq, int regset); | 74 | void (*board_bind_eic_interrupt)(int irq, int regset); |
75 | 75 | ||
76 | 76 | ||
77 | static void show_raw_backtrace(unsigned long *sp) | 77 | static void show_raw_backtrace(unsigned long reg29) |
78 | { | 78 | { |
79 | unsigned long *sp = (unsigned long *)reg29; | ||
79 | unsigned long addr; | 80 | unsigned long addr; |
80 | 81 | ||
81 | printk("Call Trace:"); | 82 | printk("Call Trace:"); |
@@ -99,30 +100,29 @@ static int __init set_raw_show_trace(char *str) | |||
99 | } | 100 | } |
100 | __setup("raw_show_trace", set_raw_show_trace); | 101 | __setup("raw_show_trace", set_raw_show_trace); |
101 | 102 | ||
102 | extern unsigned long unwind_stack(struct task_struct *task, | 103 | extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, |
103 | unsigned long **sp, unsigned long pc); | 104 | unsigned long pc, unsigned long ra); |
105 | |||
104 | static void show_backtrace(struct task_struct *task, struct pt_regs *regs) | 106 | static void show_backtrace(struct task_struct *task, struct pt_regs *regs) |
105 | { | 107 | { |
106 | unsigned long *sp = (long *)regs->regs[29]; | 108 | unsigned long sp = regs->regs[29]; |
109 | unsigned long ra = regs->regs[31]; | ||
107 | unsigned long pc = regs->cp0_epc; | 110 | unsigned long pc = regs->cp0_epc; |
108 | int top = 1; | ||
109 | 111 | ||
110 | if (raw_show_trace || !__kernel_text_address(pc)) { | 112 | if (raw_show_trace || !__kernel_text_address(pc)) { |
111 | show_raw_backtrace(sp); | 113 | show_raw_backtrace(sp); |
112 | return; | 114 | return; |
113 | } | 115 | } |
114 | printk("Call Trace:\n"); | 116 | printk("Call Trace:\n"); |
115 | while (__kernel_text_address(pc)) { | 117 | do { |
116 | print_ip_sym(pc); | 118 | print_ip_sym(pc); |
117 | pc = unwind_stack(task, &sp, pc); | 119 | pc = unwind_stack(task, &sp, pc, ra); |
118 | if (top && pc == 0) | 120 | ra = 0; |
119 | pc = regs->regs[31]; /* leaf? */ | 121 | } while (pc); |
120 | top = 0; | ||
121 | } | ||
122 | printk("\n"); | 122 | printk("\n"); |
123 | } | 123 | } |
124 | #else | 124 | #else |
125 | #define show_backtrace(task, r) show_raw_backtrace((long *)(r)->regs[29]); | 125 | #define show_backtrace(task, r) show_raw_backtrace((r)->regs[29]); |
126 | #endif | 126 | #endif |
127 | 127 | ||
128 | /* | 128 | /* |