diff options
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 2bf8b55..0d4005dc 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -100,13 +100,13 @@ int register_die_notifier(struct notifier_block *nb) vmalloc_sync_all(); return atomic_notifier_chain_register(&i386die_chain, nb); } -EXPORT_SYMBOL(register_die_notifier); +EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */ int unregister_die_notifier(struct notifier_block *nb) { return atomic_notifier_chain_unregister(&i386die_chain, nb); } -EXPORT_SYMBOL(unregister_die_notifier); +EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) { @@ -187,10 +187,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, if (unwind_init_blocked(&info, task) == 0) unw_ret = show_trace_unwind(&info, log_lvl); } - if (unw_ret > 0) { - if (call_trace > 0) + if (unw_ret > 0 && !arch_unw_user_mode(&info)) { +#ifdef CONFIG_STACK_UNWIND + print_symbol("DWARF2 unwinder stuck at %s\n", + UNW_PC(&info)); + if (call_trace == 1) { + printk("Leftover inexact backtrace:\n"); + if (UNW_SP(&info)) + stack = (void *)UNW_SP(&info); + } else if (call_trace > 1) return; - printk("%sLegacy call trace:\n", log_lvl); + else + printk("Full inexact backtrace again:\n"); +#else + printk("Inexact backtrace:\n"); +#endif } } @@ -324,35 +335,35 @@ void show_registers(struct pt_regs *regs) static void handle_BUG(struct pt_regs *regs) { + unsigned long eip = regs->eip; unsigned short ud2; - unsigned short line; - char *file; - char c; - unsigned long eip; - - eip = regs->eip; if (eip < PAGE_OFFSET) - goto no_bug; + return; if (__get_user(ud2, (unsigned short __user *)eip)) - goto no_bug; + return; if (ud2 != 0x0b0f) - goto no_bug; - if (__get_user(line, (unsigned short __user *)(eip + 2))) - goto bug; - if (__get_user(file, (char * __user *)(eip + 4)) || - (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) - file = "<bad filename>"; + return; printk(KERN_EMERG "------------[ cut here ]------------\n"); - printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); -no_bug: - return; +#ifdef CONFIG_DEBUG_BUGVERBOSE + do { + unsigned short line; + char *file; + char c; + + if (__get_user(line, (unsigned short __user *)(eip + 2))) + break; + if (__get_user(file, (char * __user *)(eip + 4)) || + (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) + file = "<bad filename>"; - /* Here we know it was a BUG but file-n-line is unavailable */ -bug: - printk(KERN_EMERG "Kernel BUG\n"); + printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); + return; + } while (0); +#endif + printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); } /* This is gone through when something in the kernel @@ -442,11 +453,9 @@ void die(const char * str, struct pt_regs * regs, long err) if (in_interrupt()) panic("Fatal exception in interrupt"); - if (panic_on_oops) { - printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); - ssleep(5); - panic("Fatal exception"); - } + if (panic_on_oops) + panic("Fatal exception: panic_on_oops"); + oops_exit(); do_exit(SIGSEGV); } @@ -1238,8 +1247,10 @@ static int __init call_trace_setup(char *s) call_trace = -1; else if (strcmp(s, "both") == 0) call_trace = 0; - else if (strcmp(s, "new") == 0) + else if (strcmp(s, "newfallback") == 0) call_trace = 1; + else if (strcmp(s, "new") == 2) + call_trace = 2; return 1; } __setup("call_trace=", call_trace_setup); |