aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-08-30 13:37:11 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-08-30 19:05:15 -0400
commitea424055b771a165c9abd3ae109255a3b825c745 (patch)
tree228f3bf4f392a8ce45d78a1ea8cfd8bd6f1f4f5b /arch/i386
parent61171b8dbd36b0cc34d3813a59a8e4dc2984414d (diff)
[PATCH] x86: Make backtracer fallback logic more bullet-proof
The unwinder fallback logic still had potential for falling through to the legacy stack trace code without printing an indication (at once serving as a separator) of this. Further, the stack pointer retrieval for the fallback should be as restrictive as possible (in order to avoid having the legacy stack tracer try to access invalid memory). The patch tightens that, but this could certainly be further improved. Also making the call_trace command line option now conditional upon CONFIG_STACK_UNWIND (as it's meaningless otherwise). Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/traps.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 82e0fd02af1c..7e9edafffd8a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void);
92asmlinkage void machine_check(void); 92asmlinkage void machine_check(void);
93 93
94static int kstack_depth_to_print = 24; 94static int kstack_depth_to_print = 24;
95#ifdef CONFIG_STACK_UNWIND
95static int call_trace = 1; 96static int call_trace = 1;
97#else
98#define call_trace (-1)
99#endif
96ATOMIC_NOTIFIER_HEAD(i386die_chain); 100ATOMIC_NOTIFIER_HEAD(i386die_chain);
97 101
98int register_die_notifier(struct notifier_block *nb) 102int register_die_notifier(struct notifier_block *nb)
@@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
187 if (unwind_init_blocked(&info, task) == 0) 191 if (unwind_init_blocked(&info, task) == 0)
188 unw_ret = show_trace_unwind(&info, log_lvl); 192 unw_ret = show_trace_unwind(&info, log_lvl);
189 } 193 }
190 if (unw_ret > 0 && !arch_unw_user_mode(&info)) { 194 if (unw_ret > 0) {
191#ifdef CONFIG_STACK_UNWIND 195 if (call_trace == 1 && !arch_unw_user_mode(&info)) {
192 print_symbol("DWARF2 unwinder stuck at %s\n", 196 print_symbol("DWARF2 unwinder stuck at %s\n",
193 UNW_PC(&info)); 197 UNW_PC(&info));
194 if (call_trace == 1) { 198 if (UNW_SP(&info) >= PAGE_OFFSET) {
195 printk("Leftover inexact backtrace:\n"); 199 printk("Leftover inexact backtrace:\n");
196 if (UNW_SP(&info))
197 stack = (void *)UNW_SP(&info); 200 stack = (void *)UNW_SP(&info);
198 } else if (call_trace > 1) 201 } else
202 printk("Full inexact backtrace again:\n");
203 } else if (call_trace >= 1)
199 return; 204 return;
200 else 205 else
201 printk("Full inexact backtrace again:\n"); 206 printk("Full inexact backtrace again:\n");
202#else 207 } else
203 printk("Inexact backtrace:\n"); 208 printk("Inexact backtrace:\n");
204#endif
205 }
206 } 209 }
207 210
208 if (task == current) { 211 if (task == current) {
@@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s)
1241} 1244}
1242__setup("kstack=", kstack_setup); 1245__setup("kstack=", kstack_setup);
1243 1246
1247#ifdef CONFIG_STACK_UNWIND
1244static int __init call_trace_setup(char *s) 1248static int __init call_trace_setup(char *s)
1245{ 1249{
1246 if (strcmp(s, "old") == 0) 1250 if (strcmp(s, "old") == 0)
@@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s)
1254 return 1; 1258 return 1;
1255} 1259}
1256__setup("call_trace=", call_trace_setup); 1260__setup("call_trace=", call_trace_setup);
1261#endif