diff -X dontdiff -urp kern_oldest/arch/i386/kernel/traps.c kern_fix/arch/i386/kernel/traps.c --- kern_oldest/arch/i386/kernel/traps.c 2006-05-01 11:56:31.000000000 -0700 +++ kern_fix/arch/i386/kernel/traps.c 2006-05-01 14:56:40.000000000 -0700 @@ -133,6 +133,80 @@ static inline int kernel_text_address(un #endif +#if CONFIG_FRAME_POINTER +void show_stack_frame_params (int param_count, unsigned long params[]) +{ + int i; + unsigned long *p, task_addr, stack_base; + + if (param_count <= 0) + return; + + task_addr = (unsigned long) current; + stack_base = task_addr + THREAD_SIZE - 1; + + printk(" ("); + + for (i = 0, p = params; + ((param_count - i) > 1) && (p >= task_addr) && (p <= stack_base); + i++, p++) { + printk("0x%x, ", *p); + + if ((i % 4) == 3) + printk("\n "); + } + + if ((p >= task_addr) && (p <= stack_base)) + printk("0x%x)\n", *p); +} + +void frame_pointer_walk(unsigned long *stack) +{ + int i; + unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr, + eip, stack_base; + /* static to not take up stackspace; if we race here too bad */ + static char buffer[512]; + + addr = (unsigned long) stack; + task_addr = (unsigned long) current; + stack_base = task_addr + THREAD_SIZE - 1; + + /* Simply return if we are doing a stack trace for any task other + * than the currently executing task. To trace another task, we + * would need an %ebp register value for that task. + */ + if (((addr < task_addr) || (addr > stack_base))) { + return; + } + + frame_ptr = (unsigned long *) (&stack - 2); + + for (; ; ) { + next_frame_ptr = (unsigned long *) (*frame_ptr); + addr = (unsigned long) next_frame_ptr; + + /* Stop when we reach a frame pointer that points to a + * location clearly outside our own kernel stack. + */ + if ((addr < task_addr) || (addr > stack_base)) + break; + + eip_ptr = frame_ptr + 1; + eip = *eip_ptr; + + if (kernel_text_address(eip)) { + lookup_symbol(eip, buffer, 512); + show_stack_frame_params(4, frame_ptr + 2); + printk("[<%08lx>] %s (0x%x)\n", eip, buffer, + eip_ptr); + } + + frame_ptr = next_frame_ptr; + } +} +#endif + void show_trace(unsigned long * stack) { #if !CONFIG_FRAME_POINTER @@ -151,16 +225,7 @@ void show_trace(unsigned long * stack) * a 100% exact backtrace, up until the entry frame: */ #if CONFIG_FRAME_POINTER -#define DO(n) \ - addr = (int)__builtin_return_address(n); \ - if (!kernel_text_address(addr)) \ - goto out; \ - lookup_symbol(addr, buffer, 512); \ - printk("[<%08lx>] %s\n", addr, buffer); - - DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(7); DO(8); DO(9); - DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(17); DO(18); DO(19); -out: + frame_pointer_walk(stack); #else i = 1; limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3; @@ -168,7 +233,7 @@ out: addr = *stack++; if (kernel_text_address(addr)) { lookup_symbol(addr, buffer, 512); - printk("[<%08lx>] %s (0x%p)\n", addr,buffer,stack-1); + printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1); i++; } } @@ -244,7 +309,7 @@ void show_registers(struct pt_regs *regs lookup_symbol(regs->eip, buffer, 512); printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags); - printk("\nEIP is at %s (" UTS_RELEASE ARCHIT ")\n",buffer); + printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer); printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",