Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

stack.c

00001 /* -*- linux-c -*- */
00002 
00003 #ifdef __x86_64__
00004 /* ripped out of arch/x86_64/kernel/traps.c */
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

Generated on Tue Mar 22 00:32:02 2005 for SystemTap.