1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/export.h>
14#include <linux/sched.h>
15#include <linux/stacktrace.h>
16#include <asm/ptrace.h>
17#include <asm/processor.h>
18
19
20
21
22static void save_context_stack(struct stack_trace *trace, unsigned long sp,
23 struct task_struct *tsk, int savesched)
24{
25 for (;;) {
26 unsigned long *stack = (unsigned long *) sp;
27 unsigned long newsp, ip;
28
29 if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
30 return;
31
32 newsp = stack[0];
33 ip = stack[STACK_FRAME_LR_SAVE];
34
35 if (savesched || !in_sched_functions(ip)) {
36 if (!trace->skip)
37 trace->entries[trace->nr_entries++] = ip;
38 else
39 trace->skip--;
40 }
41
42 if (trace->nr_entries >= trace->max_entries)
43 return;
44
45 sp = newsp;
46 }
47}
48
49void save_stack_trace(struct stack_trace *trace)
50{
51 unsigned long sp;
52
53 sp = current_stack_pointer();
54
55 save_context_stack(trace, sp, current, 1);
56}
57EXPORT_SYMBOL_GPL(save_stack_trace);
58
59void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
60{
61 save_context_stack(trace, tsk->thread.ksp, tsk, 0);
62}
63EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
64