1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 * Copyright (C) 2013 Richard Weinberger <richard@nod.at>
5 * Copyright (C) 2014 Google Inc., Author: Daniel Walter <dwalter@google.com>
8 #include <linux/kallsyms.h>
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11 #include <linux/stacktrace.h>
12 #include <linux/module.h>
13 #include <linux/uaccess.h>
14 #include <asm/stacktrace.h>
16 void dump_trace(struct task_struct
*tsk
,
17 const struct stacktrace_ops
*ops
,
21 unsigned long *sp
, bp
, addr
;
22 struct pt_regs
*segv_regs
= tsk
->thread
.segv_regs
;
23 struct stack_frame
*frame
;
25 bp
= get_frame_pointer(tsk
, segv_regs
);
26 sp
= get_stack_pointer(tsk
, segv_regs
);
28 frame
= (struct stack_frame
*)bp
;
29 while (((long) sp
& (THREAD_SIZE
-1)) != 0) {
31 if (__kernel_text_address(addr
)) {
33 if ((unsigned long) sp
== bp
+ sizeof(long)) {
34 frame
= frame
? frame
->next_frame
: NULL
;
35 bp
= (unsigned long)frame
;
38 ops
->address(data
, addr
, reliable
);
44 static void save_addr(void *data
, unsigned long address
, int reliable
)
46 struct stack_trace
*trace
= data
;
50 if (trace
->nr_entries
>= trace
->max_entries
)
53 trace
->entries
[trace
->nr_entries
++] = address
;
56 static const struct stacktrace_ops dump_ops
= {
60 static void __save_stack_trace(struct task_struct
*tsk
, struct stack_trace
*trace
)
62 dump_trace(tsk
, &dump_ops
, trace
);
65 void save_stack_trace(struct stack_trace
*trace
)
67 __save_stack_trace(current
, trace
);
69 EXPORT_SYMBOL_GPL(save_stack_trace
);
71 void save_stack_trace_tsk(struct task_struct
*tsk
, struct stack_trace
*trace
)
73 __save_stack_trace(tsk
, trace
);
75 EXPORT_SYMBOL_GPL(save_stack_trace_tsk
);