2017-11-24 15:00:32 +01:00
// SPDX-License-Identifier: GPL-2.0
2006-07-03 00:24:41 -07:00
/*
* Stack trace management functions
*
2012-07-20 11:15:04 +02:00
* Copyright IBM Corp . 2006
2006-07-03 00:24:41 -07:00
* Author ( s ) : Heiko Carstens < heiko . carstens @ de . ibm . com >
*/
# include <linux/sched.h>
2017-02-08 18:51:35 +01:00
# include <linux/sched/debug.h>
2006-07-03 00:24:41 -07:00
# include <linux/stacktrace.h>
# include <linux/kallsyms.h>
2017-02-09 15:20:23 -05:00
# include <linux/export.h>
2006-07-03 00:24:41 -07:00
2016-02-09 12:58:54 +01:00
static int __save_address ( void * data , unsigned long address , int nosched )
2006-07-03 00:24:41 -07:00
{
2016-02-09 12:58:54 +01:00
struct stack_trace * trace = data ;
2006-07-03 00:24:41 -07:00
2016-02-09 12:58:54 +01:00
if ( nosched & & in_sched_functions ( address ) )
return 0 ;
if ( trace - > skip > 0 ) {
trace - > skip - - ;
return 0 ;
2006-07-03 00:24:41 -07:00
}
2016-02-09 12:58:54 +01:00
if ( trace - > nr_entries < trace - > max_entries ) {
trace - > entries [ trace - > nr_entries + + ] = address ;
return 0 ;
}
return 1 ;
2006-07-03 00:24:41 -07:00
}
2016-10-17 11:08:31 +02:00
static int save_address ( void * data , unsigned long address , int reliable )
2006-07-03 00:24:41 -07:00
{
2016-02-09 12:58:54 +01:00
return __save_address ( data , address , 0 ) ;
}
2006-07-03 00:24:41 -07:00
2016-10-17 11:08:31 +02:00
static int save_address_nosched ( void * data , unsigned long address , int reliable )
2016-02-09 12:58:54 +01:00
{
return __save_address ( data , address , 1 ) ;
2016-02-01 14:14:04 +01:00
}
void save_stack_trace ( struct stack_trace * trace )
{
unsigned long sp ;
2016-01-31 17:06:16 +01:00
sp = current_stack_pointer ( ) ;
2016-02-09 12:58:54 +01:00
dump_trace ( save_address , trace , NULL , sp ) ;
2016-02-01 14:06:57 +01:00
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = ULONG_MAX ;
2008-02-05 16:50:45 +01:00
}
2008-07-03 09:17:55 +02:00
EXPORT_SYMBOL_GPL ( save_stack_trace ) ;
2008-02-05 16:50:45 +01:00
void save_stack_trace_tsk ( struct task_struct * tsk , struct stack_trace * trace )
{
2016-02-09 12:58:54 +01:00
unsigned long sp ;
2008-02-05 16:50:45 +01:00
2016-01-18 13:12:19 +01:00
sp = tsk - > thread . ksp ;
2016-01-31 17:06:16 +01:00
if ( tsk = = current )
sp = current_stack_pointer ( ) ;
2016-02-09 12:58:54 +01:00
dump_trace ( save_address_nosched , trace , tsk , sp ) ;
2008-02-05 16:50:45 +01:00
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = ULONG_MAX ;
2006-07-03 00:24:41 -07:00
}
2008-07-03 09:17:55 +02:00
EXPORT_SYMBOL_GPL ( save_stack_trace_tsk ) ;
2016-01-29 10:50:28 +05:30
void save_stack_trace_regs ( struct pt_regs * regs , struct stack_trace * trace )
{
unsigned long sp ;
sp = kernel_stack_pointer ( regs ) ;
2016-02-09 12:58:54 +01:00
dump_trace ( save_address , trace , NULL , sp ) ;
2016-01-29 10:50:28 +05:30
if ( trace - > nr_entries < trace - > max_entries )
trace - > entries [ trace - > nr_entries + + ] = ULONG_MAX ;
}
EXPORT_SYMBOL_GPL ( save_stack_trace_regs ) ;