1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <linux/kallsyms.h> 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/sched.h> 10 #include "sysrq.h" 11 12 /* Catch non-i386 SUBARCH's. */ 13 #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) 14 void show_trace(struct task_struct *task, unsigned long * stack) 15 { 16 unsigned long addr; 17 18 if (!stack) { 19 stack = (unsigned long*) &stack; 20 WARN_ON(1); 21 } 22 23 printk(KERN_INFO "Call Trace: \n"); 24 while (((long) stack & (THREAD_SIZE-1)) != 0) { 25 addr = *stack; 26 if (__kernel_text_address(addr)) { 27 printk(KERN_INFO "%08lx: [<%08lx>]", 28 (unsigned long) stack, addr); 29 print_symbol(KERN_CONT " %s", addr); 30 printk(KERN_CONT "\n"); 31 } 32 stack++; 33 } 34 printk(KERN_INFO "\n"); 35 } 36 #endif 37 38 /* 39 * stack dumps generator - this is used by arch-independent code. 40 * And this is identical to i386 currently. 41 */ 42 void dump_stack(void) 43 { 44 unsigned long stack; 45 46 show_trace(current, &stack); 47 } 48 EXPORT_SYMBOL(dump_stack); 49 50 /*Stolen from arch/i386/kernel/traps.c */ 51 static const int kstack_depth_to_print = 24; 52 53 /* This recently started being used in arch-independent code too, as in 54 * kernel/sched.c.*/ 55 void show_stack(struct task_struct *task, unsigned long *esp) 56 { 57 unsigned long *stack; 58 int i; 59 60 if (esp == NULL) { 61 if (task != current && task != NULL) { 62 esp = (unsigned long *) KSTK_ESP(task); 63 } else { 64 esp = (unsigned long *) &esp; 65 } 66 } 67 68 stack = esp; 69 for (i = 0; i < kstack_depth_to_print; i++) { 70 if (kstack_end(stack)) 71 break; 72 if (i && ((i % 8) == 0)) 73 printk(KERN_INFO " "); 74 printk(KERN_CONT "%08lx ", *stack++); 75 } 76 77 show_trace(task, esp); 78 } 79