1 /* 2 * Stack trace management functions 3 * 4 * Copyright IBM Corp. 2006 5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> 6 */ 7 8 #include <linux/sched.h> 9 #include <linux/stacktrace.h> 10 #include <linux/kallsyms.h> 11 #include <linux/module.h> 12 13 static int __save_address(void *data, unsigned long address, int nosched) 14 { 15 struct stack_trace *trace = data; 16 17 if (nosched && in_sched_functions(address)) 18 return 0; 19 if (trace->skip > 0) { 20 trace->skip--; 21 return 0; 22 } 23 if (trace->nr_entries < trace->max_entries) { 24 trace->entries[trace->nr_entries++] = address; 25 return 0; 26 } 27 return 1; 28 } 29 30 static int save_address(void *data, unsigned long address) 31 { 32 return __save_address(data, address, 0); 33 } 34 35 static int save_address_nosched(void *data, unsigned long address) 36 { 37 return __save_address(data, address, 1); 38 } 39 40 void save_stack_trace(struct stack_trace *trace) 41 { 42 unsigned long sp; 43 44 sp = current_stack_pointer(); 45 dump_trace(save_address, trace, NULL, sp); 46 if (trace->nr_entries < trace->max_entries) 47 trace->entries[trace->nr_entries++] = ULONG_MAX; 48 } 49 EXPORT_SYMBOL_GPL(save_stack_trace); 50 51 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 52 { 53 unsigned long sp; 54 55 sp = tsk->thread.ksp; 56 if (tsk == current) 57 sp = current_stack_pointer(); 58 dump_trace(save_address_nosched, trace, tsk, sp); 59 if (trace->nr_entries < trace->max_entries) 60 trace->entries[trace->nr_entries++] = ULONG_MAX; 61 } 62 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 63 64 void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 65 { 66 unsigned long sp; 67 68 sp = kernel_stack_pointer(regs); 69 dump_trace(save_address, trace, NULL, sp); 70 if (trace->nr_entries < trace->max_entries) 71 trace->entries[trace->nr_entries++] = ULONG_MAX; 72 } 73 EXPORT_SYMBOL_GPL(save_stack_trace_regs); 74