1 #include <linux/sched.h>
2 #include <linux/sched/debug.h>
3 #include <linux/stacktrace.h>
4 #include <asm/stacktrace.h>
6 void walk_stackframe(unsigned long sp
,
7 int (*fn
)(unsigned long addr
, void *data
),
10 unsigned long high
= ALIGN(sp
, THREAD_SIZE
);
12 for (; sp
<= high
- 4; sp
+= 4) {
13 unsigned long addr
= *(unsigned long *) sp
;
15 if (!kernel_text_address(addr
))
23 struct stack_trace_data
{
24 struct stack_trace
*trace
;
25 unsigned int no_sched_functions
;
29 #ifdef CONFIG_STACKTRACE
31 static int save_trace(unsigned long addr
, void *d
)
33 struct stack_trace_data
*data
= d
;
34 struct stack_trace
*trace
= data
->trace
;
36 if (data
->no_sched_functions
&& in_sched_functions(addr
))
44 trace
->entries
[trace
->nr_entries
++] = addr
;
46 return trace
->nr_entries
>= trace
->max_entries
;
49 void save_stack_trace_tsk(struct task_struct
*tsk
, struct stack_trace
*trace
)
51 struct stack_trace_data data
;
55 data
.skip
= trace
->skip
;
58 data
.no_sched_functions
= 1;
61 data
.no_sched_functions
= 0;
65 walk_stackframe(sp
, save_trace
, &data
);
66 if (trace
->nr_entries
< trace
->max_entries
)
67 trace
->entries
[trace
->nr_entries
++] = ULONG_MAX
;
70 void save_stack_trace(struct stack_trace
*trace
)
72 save_stack_trace_tsk(current
, trace
);
74 EXPORT_SYMBOL_GPL(save_stack_trace
);
76 #endif /* CONFIG_STACKTRACE */