Stack trace without forcing oops (was 2.2.14pre5: kmem_grow: Called nonatomically)

Keith Owens (kaos@ocs.com.au)
Sun, 21 Nov 1999 20:11:51 +1100


On Sat, 20 Nov 1999 14:38:40 +0100 (CET),
Ingo Molnar <mingo@chiara.csoma.elte.hu> wrote:
>On Thu, 18 Nov 1999, Dominik Kubla wrote:
>> Hmm... nice! Is there a way to get a stacktrace without forcing an oops?
>nevertheless just changing show_task() or die_if_kernel() to not crash the
>the process if called in some special way could indeed be a welcome
>addition - but i believe only if it doesnt increase maintainance efforts.

Easier than that. Break the stack dump code from show_registers() into
a separate routine, patch below. Any code that needs a back trace for
debugging can call show_stack(NULL). This also fixes a long standing
bug where the i386 stack was not completely printed if it went into the
second stack page.

This patch is only for i386. It would be nice if all architectures had
a standard show_stack() routine. Against 2.3.28.

Index: 28.1/arch/i386/kernel/i386_ksyms.c
--- 28.1/arch/i386/kernel/i386_ksyms.c Fri, 12 Nov 1999 18:53:00 +1100 keith (linux-2.3/w/37_i386_ksyms 1.9 644)
+++ 28.1(w)/arch/i386/kernel/i386_ksyms.c Sun, 21 Nov 1999 13:33:31 +1100 keith (linux-2.3/w/37_i386_ksyms 1.9 644)
@@ -130,3 +130,4 @@
#endif

EXPORT_SYMBOL(get_wchan);
+EXPORT_SYMBOL(show_stack); /* For adhoc debugging in modules */
Index: 28.1/arch/i386/kernel/traps.c
--- 28.1/arch/i386/kernel/traps.c Sat, 23 Oct 1999 15:35:04 +1000 keith (linux-2.3/x/0_traps.c 1.7 644)
+++ 28.1(w)/arch/i386/kernel/traps.c Sun, 21 Nov 1999 19:58:17 +1100 keith (linux-2.3/x/0_traps.c 1.7 644)
@@ -129,13 +129,59 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)

+/* Separate show_stack() so adhoc debugging code can use it */
+void show_stack(const unsigned long *esp)
+{
+ int i;
+ unsigned long *stack, *save_stack, addr, module_start, module_end;
+ printk("Stack: ");
+ /* show_registers passes a real esp, adhoc debugging passes NULL */
+ if (esp)
+ stack = (unsigned long *) esp;
+ else
+ asm("movl %%esp,%0": "=m" (stack));
+ save_stack = stack;
+ for(i=0; i < kstack_depth_to_print; i++) {
+ if (((long) stack & ~PAGE_MASK) == 0)
+ break;
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("%08lx ", *stack++);
+ }
+ printk("\nCall Trace: ");
+ stack = save_stack;
+ i = 1;
+ module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
+ module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+ module_end = module_start + MODULE_RANGE;
+ while (((long) stack & ~PAGE_MASK) != 0) {
+ addr = *stack++;
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (((addr >= (unsigned long) &_stext) &&
+ (addr <= (unsigned long) &_etext)) ||
+ ((addr >= module_start) && (addr <= module_end))) {
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("[<%08lx>] ", addr);
+ i++;
+ }
+ }
+ printk("\n");
+}
+
static void show_registers(struct pt_regs *regs)
{
int i;
int in_kernel = 1;
unsigned long esp;
unsigned short ss;
- unsigned long *stack, addr, module_start, module_end;

esp = (unsigned long) (1+regs);
ss = __KERNEL_DS;
@@ -152,52 +198,19 @@
regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff, ss);
- printk("Process %s (pid: %d, stackpage=%08lx)",
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, 4096+(unsigned long)current);
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
if (in_kernel) {
- printk("\nStack: ");
- stack = (unsigned long *) esp;
- for(i=0; i < kstack_depth_to_print; i++) {
- if (((long) stack & 4095) == 0)
- break;
- if (i && ((i % 8) == 0))
- printk("\n ");
- printk("%08lx ", *stack++);
- }
- printk("\nCall Trace: ");
- stack = (unsigned long *) esp;
- i = 1;
- module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
- module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
- module_end = module_start + MODULE_RANGE;
- while (((long) stack & 4095) != 0) {
- addr = *stack++;
- /*
- * If the address is either in the text segment of the
- * kernel, or in the region which contains vmalloc'ed
- * memory, it *may* be the address of a calling
- * routine; if so, print it so that someone tracing
- * down the cause of the crash will be able to figure
- * out the call path that was taken.
- */
- if (((addr >= (unsigned long) &_stext) &&
- (addr <= (unsigned long) &_etext)) ||
- ((addr >= module_start) && (addr <= module_end))) {
- if (i && ((i % 8) == 0))
- printk("\n ");
- printk("[<%08lx>] ", addr);
- i++;
- }
- }
- printk("\nCode: ");
+ show_stack(&esp);
+ printk("Code: ");
for(i=0;i<20;i++)
printk("%02x ", ((unsigned char *)regs->eip)[i]);
+ printk("\n");
}
- printk("\n");
}

spinlock_t die_lock;
Index: 28.1/include/linux/kernel.h
--- 28.1/include/linux/kernel.h Sat, 23 Oct 1999 15:35:04 +1000 keith (linux-2.3/F/b/4_kernel.h 1.7 644)
+++ 28.1(w)/include/linux/kernel.h Sun, 21 Nov 1999 14:08:36 +1100 keith (linux-2.3/F/b/4_kernel.h 1.7 644)
@@ -42,6 +42,7 @@
#define FASTCALL(x) x
#endif

+extern void show_stack(const unsigned long *); /* For adhoc debugging */
extern void math_error(void);
extern struct notifier_block *panic_notifier_list;
NORET_TYPE void panic(const char * fmt, ...)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/