2006-11-17 00:38:57 +03:00
# include <linux/sched.h>
# include <linux/stacktrace.h>
# include <linux/thread_info.h>
2008-07-08 16:15:40 +04:00
# include <linux/module.h>
2006-11-17 00:38:57 +03:00
# include <asm/ptrace.h>
2008-03-25 06:06:24 +03:00
# include <asm/stacktrace.h>
2006-11-17 00:38:57 +03:00
2007-05-08 11:23:29 +04:00
void save_stack_trace ( struct stack_trace * trace )
2006-11-17 00:38:57 +03:00
{
unsigned long ksp , fp , thread_base ;
2007-05-08 11:23:29 +04:00
struct thread_info * tp = task_thread_info ( current ) ;
2006-11-17 00:38:57 +03:00
2008-03-25 06:06:24 +03:00
stack_trace_flush ( ) ;
2007-05-08 11:23:29 +04:00
__asm__ __volatile__ (
" mov %%fp, %0 "
: " =r " ( ksp )
) ;
2006-11-17 00:38:57 +03:00
fp = ksp + STACK_BIAS ;
thread_base = ( unsigned long ) tp ;
do {
2008-05-22 05:15:53 +04:00
struct sparc_stackf * sf ;
2008-04-24 14:28:52 +04:00
struct pt_regs * regs ;
unsigned long pc ;
2006-11-17 00:38:57 +03:00
/* Bogus frame pointer? */
if ( fp < ( thread_base + sizeof ( struct thread_info ) ) | |
2008-08-08 10:04:37 +04:00
fp > ( thread_base + THREAD_SIZE - sizeof ( struct sparc_stackf ) ) )
2006-11-17 00:38:57 +03:00
break ;
2008-05-22 05:15:53 +04:00
sf = ( struct sparc_stackf * ) fp ;
regs = ( struct pt_regs * ) ( sf + 1 ) ;
2008-04-24 14:28:52 +04:00
2008-08-08 10:04:37 +04:00
if ( ( ( unsigned long ) regs < =
( thread_base + THREAD_SIZE - sizeof ( * regs ) ) ) & &
( regs - > magic & ~ 0x1ff ) = = PT_REGS_MAGIC ) {
2008-05-22 05:15:53 +04:00
if ( ! ( regs - > tstate & TSTATE_PRIV ) )
break ;
2008-04-24 14:28:52 +04:00
pc = regs - > tpc ;
fp = regs - > u_regs [ UREG_I6 ] + STACK_BIAS ;
} else {
2008-05-22 05:15:53 +04:00
pc = sf - > callers_pc ;
fp = ( unsigned long ) sf - > fp + STACK_BIAS ;
2008-04-24 14:28:52 +04:00
}
2006-11-17 00:38:57 +03:00
if ( trace - > skip > 0 )
trace - > skip - - ;
else
2008-04-24 14:28:52 +04:00
trace - > entries [ trace - > nr_entries + + ] = pc ;
2006-11-17 00:38:57 +03:00
} while ( trace - > nr_entries < trace - > max_entries ) ;
}
2008-07-03 11:17:55 +04:00
EXPORT_SYMBOL_GPL ( save_stack_trace ) ;