Main Page | Modules | Directories | File List | Globals | Related Pages

stack.c

Go to the documentation of this file.
00001 #ifndef _STACK_C_ /* -*- linux-c -*- */
00002 #define _STACK_C_
00003 
00004 
00005 /** @file stack.c
00006  * @brief Stack Tracing Functions
00007  */
00008 
00009 /** @addtogroup stack Stack Tracing Functions
00010  * @{
00011  */
00012 
00013 #include "sym.c"
00014 
00015 static int (*_stp_kta)(unsigned long addr)=(void *)KTA;
00016 
00017 #ifdef __x86_64__
00018 static void __stp_stack_print (unsigned long *stack, int verbose, int levels)
00019 {
00020         unsigned long addr;
00021 
00022         if (verbose)
00023                 _stp_printf ("trace for %d (%s)\n", current->pid, current->comm);
00024 
00025         while (((long) stack & (THREAD_SIZE-1)) != 0) {
00026                 addr = *stack++;
00027                 if (_stp_kta(addr)) {
00028                         if (verbose) {
00029                                 _stp_symbol_print (addr);
00030                                 _stp_print ("\n");
00031                         } else
00032                                 _stp_printf ("0x%lx ", addr);
00033                 }
00034         }
00035         _stp_print_flush();
00036 }
00037 
00038 
00039 static void __stp_stack_sprint (String str, unsigned long *stack, int verbose, int levels)
00040 {
00041         unsigned long addr;
00042         while (((long) stack & (THREAD_SIZE-1)) != 0) {
00043                 addr = *stack++;
00044                 if (_stp_kta(addr)) {
00045                         if (verbose)
00046                                 _stp_symbol_sprint (str, addr);
00047                         else
00048                                 _stp_sprintf (str, "0x%lx ", addr);
00049                 }
00050         }
00051 }
00052 
00053 #else  /* i386 */
00054 
00055 static inline int valid_stack_ptr (struct thread_info *tinfo, void *p)
00056 {
00057         return  p > (void *)tinfo &&
00058                 p < (void *)tinfo + THREAD_SIZE - 3;
00059 }
00060 
00061 static inline unsigned long _stp_print_context_stack (
00062         struct thread_info *tinfo,
00063         unsigned long *stack, 
00064         unsigned long ebp )
00065 {
00066         unsigned long addr;
00067 
00068 #ifdef  CONFIG_FRAME_POINTER
00069         while (valid_stack_ptr(tinfo, (void *)ebp)) {
00070                 addr = *(unsigned long *)(ebp + 4);
00071                 _stp_symbol_print (addr);
00072                 _stp_print_cstr("\n");
00073                 ebp = *(unsigned long *)ebp;
00074         }
00075 #else
00076         while (valid_stack_ptr(tinfo, stack)) {
00077                 addr = *stack++;
00078                 if (_stp_kta (addr)) {
00079                         _stp_symbol_print (addr);
00080                         _stp_print_cstr ("\n");
00081                 }
00082         }
00083 #endif
00084         _stp_print_flush();
00085         return ebp;
00086 }
00087 
00088 static inline unsigned long _stp_sprint_context_stack (
00089         String str,
00090         struct thread_info *tinfo,
00091         unsigned long *stack, 
00092         unsigned long ebp )
00093 {
00094         unsigned long addr;
00095 
00096 #ifdef  CONFIG_FRAME_POINTER
00097         while (valid_stack_ptr(tinfo, (void *)ebp)) {
00098                 addr = *(unsigned long *)(ebp + 4);
00099                 _stp_symbol_sprint (str, addr);
00100                 _stp_string_cat ("\n");
00101                 ebp = *(unsigned long *)ebp;
00102         }
00103 #else
00104         while (valid_stack_ptr(tinfo, stack)) {
00105                 addr = *stack++;
00106                 if (_stp_kta (addr)) {
00107                         _stp_symbol_sprint (addr);
00108                         _stp_string_cat ("\n");
00109                 }
00110         }
00111 #endif
00112         return ebp;
00113 }
00114 
00115 static void __stp_stack_print (unsigned long *stack, int verbose, int levels)
00116 {
00117         unsigned long ebp;
00118 
00119         /* Grab ebp right from our regs */
00120         asm ("movl %%ebp, %0" : "=r" (ebp) : );
00121 
00122         while (stack) {
00123                 struct thread_info *context = (struct thread_info *)
00124                         ((unsigned long)stack & (~(THREAD_SIZE - 1)));
00125                 ebp = _stp_print_context_stack (context, stack, ebp);
00126                 stack = (unsigned long*)context->previous_esp;
00127         }
00128 }
00129 
00130 static void __stp_stack_sprint (String str, unsigned long *stack, int verbose, int levels)
00131 {
00132         unsigned long ebp;
00133 
00134         /* Grab ebp right from our regs */
00135         asm ("movl %%ebp, %0" : "=r" (ebp) : );
00136 
00137         while (stack) {
00138                 struct thread_info *context = (struct thread_info *)
00139                         ((unsigned long)stack & (~(THREAD_SIZE - 1)));
00140                 ebp = _stp_sprint_context_stack (str, context, stack, ebp);
00141                 stack = (unsigned long*)context->previous_esp;
00142         }
00143 }
00144 
00145 #endif /* i386 */
00146 
00147 /** Print stack dump.
00148  * Prints a stack dump to the print buffer.
00149  * @param verbose Verbosity
00150  * @param levels Number of levels to trace.
00151  * @todo Implement verbosity and levels parameters.
00152  * @bug levels parameter is not functional
00153  */
00154 
00155 void _stp_stack_print (int verbose, int levels)
00156 {
00157   unsigned long stack;
00158   __stp_stack_print (&stack, verbose, levels);
00159 }
00160 
00161 /** Writes stack dump to a String
00162  *
00163  * @param str String
00164  * @param verbose Verbosity
00165  * @param levels Number of levels to trace.
00166  * @returns Same String as was input.
00167  * @todo Implement verbosity and levels parameters.
00168  * @bug levels parameter is not functional
00169  */
00170 
00171 String _stp_stack_sprint (String str, int verbose, int levels)
00172 {
00173   unsigned long stack;
00174   __stp_stack_sprint (str, &stack, verbose, levels);
00175   _stp_log ("sss: str=%s\n", str->buf);
00176   return str;
00177 }
00178 
00179 /** @} */
00180 #endif /* _STACK_C_ */