00001
00002
00003 #ifdef __x86_64__
00004
00005 #include <linux/kallsyms.h>
00006
00007 static int _stp_printk_address(unsigned long address)
00008 {
00009 unsigned long offset = 0, symsize;
00010 const char *symname;
00011 char *modname;
00012 char *delim = ":";
00013 char namebuf[128];
00014
00015 symname = _stp_kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
00016 if (!symname)
00017 return printk("[<%016lx>]", address);
00018 if (!modname)
00019 modname = delim = "";
00020 return printk("<%016lx>{%s%s%s%s%+ld}",
00021 address,delim,modname,delim,symname,offset);
00022 }
00023
00024 void _stp_show_trace(unsigned long *stack)
00025 {
00026 unsigned long addr;
00027 unsigned long *irqstack, *irqstack_end, *estack_end;
00028 const int cpu = safe_smp_processor_id();
00029 int i;
00030
00031 printk("\nCall Trace:");
00032 i = 0;
00033
00034 estack_end = in_exception_stack(cpu, (unsigned long)stack);
00035 if (estack_end) {
00036 while (stack < estack_end) {
00037 addr = *stack++;
00038 if (__kernel_text_address(addr)) {
00039 i += printk_address(addr);
00040 i += printk(" ");
00041 if (i > 50) {
00042 printk("\n");
00043 i = 0;
00044 }
00045 }
00046 }
00047 i += printk(" <EOE> ");
00048 i += 7;
00049 stack = (unsigned long *) estack_end[-2];
00050 }
00051
00052 irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr);
00053 irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE + 64);
00054
00055 if (stack >= irqstack && stack < irqstack_end) {
00056 printk("<IRQ> ");
00057 while (stack < irqstack_end) {
00058 addr = *stack++;
00059 /*
00060 * If the address is either in the text segment of the
00061 * kernel, or in the region which contains vmalloc'ed
00062 * memory, it *may* be the address of a calling
00063 * routine; if so, print it so that someone tracing
00064 * down the cause of the crash will be able to figure
00065 * out the call path that was taken.
00066 */
00067 if (__kernel_text_address(addr)) {
00068 i += printk_address(addr);
00069 i += printk(" ");
00070 if (i > 50) {
00071 printk("\n ");
00072 i = 0;
00073 }
00074 }
00075 }
00076 stack = (unsigned long *) (irqstack_end[-1]);
00077 printk(" <EOI> ");
00078 i += 7;
00079 }
00080
00081 while (((long) stack & (THREAD_SIZE-1)) != 0) {
00082 addr = *stack++;
00083 if (__kernel_text_address(addr)) {
00084 i += printk_address(addr);
00085 i += printk(" ");
00086 if (i > 50) {
00087 printk("\n ");
00088 i = 0;
00089 }
00090 }
00091 }
00092 printk("\n");
00093 }
00094
00095 void _stp_dump_stack(void)
00096 {
00097 unsigned long dummy;
00098 show_trace(&dummy);
00099 }
00100
00101 #else /* i386 */
00102
00103 static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
00104 {
00105 return p > (void *)tinfo &&
00106 p < (void *)tinfo + THREAD_SIZE - 3;
00107 }
00108
00109 int __kernel_text_address(unsigned long addr)
00110 {
00111 if (core_kernel_text(addr))
00112 return 1;
00113 return __module_text_address(addr) != NULL;
00114 }
00115
00116 static inline unsigned long _stp_print_context_stack(struct thread_info *tinfo,
00117 unsigned long *stack, unsigned long ebp)
00118 {
00119 unsigned long addr;
00120
00121 #ifdef CONFIG_FRAME_POINTER
00122 while (valid_stack_ptr(tinfo, (void *)ebp)) {
00123 addr = *(unsigned long *)(ebp + 4);
00124 _stp_print_buf(" [<%08lx>] ", addr);
00125 _stp_print_symbol("%s", addr);
00126 _stp_print_buf("\n");
00127 ebp = *(unsigned long *)ebp;
00128 }
00129 #else
00130 while (valid_stack_ptr(tinfo, stack)) {
00131 addr = *stack++;
00132 if (__kernel_text_address(addr)) {
00133 _stp_print_buf(" [<%08lx>]", addr);
00134 _stp_print_symbol(" %s", addr);
00135 _stp_print_buf("\n");
00136 }
00137 }
00138 #endif
00139 return ebp;
00140 }
00141
00142 void show_trace(struct task_struct *task, unsigned long * stack)
00143 {
00144 unsigned long ebp;
00145
00146 if (!task)
00147 task = current;
00148
00149 if (task == current) {
00150 /* Grab ebp right from our regs */
00151 asm ("movl %%ebp, %0" : "=r" (ebp) : );
00152 } else {
00153 /* ebp is the last reg pushed by switch_to */
00154 ebp = *(unsigned long *) task->thread.esp;
00155 }
00156
00157 while (1) {
00158 struct thread_info *context;
00159 context = (struct thread_info *)
00160 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
00161 ebp = _stp_print_context_stack(context, stack, ebp);
00162 stack = (unsigned long*)context->previous_esp;
00163 if (!stack)
00164 break;
00165 _stp_print_buf(" =======================\n");
00166 }
00167 }
00168
00169 void dump_stack(void)
00170 {
00171 unsigned long stack;
00172 show_trace(current, &stack);
00173 }
00174 #endif