2006-12-04 12:17:28 +03:00
/*
* arch / sh / kernel / stacktrace . c
*
* Stack trace management functions
*
2008-09-12 20:44:03 +04:00
* Copyright ( C ) 2006 - 2008 Paul Mundt
2006-12-04 12:17:28 +03:00
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/sched.h>
2017-02-08 20:51:35 +03:00
# include <linux/sched/debug.h>
2006-12-04 12:17:28 +03:00
# include <linux/stacktrace.h>
# include <linux/thread_info.h>
2008-07-15 01:32:32 +04:00
# include <linux/module.h>
2009-08-12 01:43:20 +04:00
# include <asm/unwinder.h>
2006-12-04 12:17:28 +03:00
# include <asm/ptrace.h>
2009-08-07 19:11:19 +04:00
# include <asm/stacktrace.h>
static int save_stack_stack ( void * data , char * name )
{
return 0 ;
}
2006-12-04 12:17:28 +03:00
/*
* Save stack - backtrace addresses into a stack_trace buffer .
*/
2009-08-07 19:11:19 +04:00
static void save_stack_address ( void * data , unsigned long addr , int reliable )
{
struct stack_trace * trace = data ;
2009-08-14 20:05:46 +04:00
if ( ! reliable )
return ;
2009-08-07 19:11:19 +04:00
if ( trace - > skip > 0 ) {
trace - > skip - - ;
return ;
}
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = addr ;
}
static const struct stacktrace_ops save_stack_ops = {
. stack = save_stack_stack ,
. address = save_stack_address ,
} ;
2007-05-09 13:55:14 +04:00
void save_stack_trace ( struct stack_trace * trace )
2006-12-04 12:17:28 +03:00
{
2007-05-08 11:23:29 +04:00
unsigned long * sp = ( unsigned long * ) current_stack_pointer ;
2006-12-04 12:17:28 +03:00
2009-08-12 01:43:20 +04:00
unwind_stack ( current , NULL , sp , & save_stack_ops , trace ) ;
2009-08-14 20:11:37 +04:00
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = ULONG_MAX ;
2006-12-04 12:17:28 +03:00
}
2008-07-03 11:17:55 +04:00
EXPORT_SYMBOL_GPL ( save_stack_trace ) ;
2008-09-12 20:44:03 +04:00
2009-08-07 19:11:19 +04:00
static void
save_stack_address_nosched ( void * data , unsigned long addr , int reliable )
{
struct stack_trace * trace = ( struct stack_trace * ) data ;
2009-08-14 20:05:46 +04:00
if ( ! reliable )
return ;
2009-08-07 19:11:19 +04:00
if ( in_sched_functions ( addr ) )
return ;
if ( trace - > skip > 0 ) {
trace - > skip - - ;
return ;
}
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = addr ;
}
static const struct stacktrace_ops save_stack_ops_nosched = {
. stack = save_stack_stack ,
. address = save_stack_address_nosched ,
} ;
2008-09-12 20:44:03 +04:00
void save_stack_trace_tsk ( struct task_struct * tsk , struct stack_trace * trace )
{
unsigned long * sp = ( unsigned long * ) tsk - > thread . sp ;
2009-08-12 01:43:20 +04:00
unwind_stack ( current , NULL , sp , & save_stack_ops_nosched , trace ) ;
2009-08-14 20:11:37 +04:00
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = ULONG_MAX ;
2008-09-12 20:44:03 +04:00
}
EXPORT_SYMBOL_GPL ( save_stack_trace_tsk ) ;