2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Copyright (C) 2013 Richard Weinberger <richard@nod.at>
4 * Copyright (C) 2014 Google Inc., Author: Daniel Walter <dwalter@google.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/kallsyms.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/stacktrace.h>
15 #include <linux/module.h>
16 #include <linux/uaccess.h>
17 #include <asm/stacktrace.h>
19 void dump_trace(struct task_struct
*tsk
,
20 const struct stacktrace_ops
*ops
,
24 unsigned long *sp
, bp
, addr
;
25 struct pt_regs
*segv_regs
= tsk
->thread
.segv_regs
;
26 struct stack_frame
*frame
;
28 bp
= get_frame_pointer(tsk
, segv_regs
);
29 sp
= get_stack_pointer(tsk
, segv_regs
);
31 frame
= (struct stack_frame
*)bp
;
32 while (((long) sp
& (THREAD_SIZE
-1)) != 0) {
34 if (__kernel_text_address(addr
)) {
36 if ((unsigned long) sp
== bp
+ sizeof(long)) {
37 frame
= frame
? frame
->next_frame
: NULL
;
38 bp
= (unsigned long)frame
;
41 ops
->address(data
, addr
, reliable
);
47 static void save_addr(void *data
, unsigned long address
, int reliable
)
49 struct stack_trace
*trace
= data
;
53 if (trace
->nr_entries
>= trace
->max_entries
)
56 trace
->entries
[trace
->nr_entries
++] = address
;
59 static const struct stacktrace_ops dump_ops
= {
63 static void __save_stack_trace(struct task_struct
*tsk
, struct stack_trace
*trace
)
65 dump_trace(tsk
, &dump_ops
, trace
);
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(current
, trace
);
74 EXPORT_SYMBOL_GPL(save_stack_trace
);
76 void save_stack_trace_tsk(struct task_struct
*tsk
, struct stack_trace
*trace
)
78 __save_stack_trace(tsk
, trace
);
80 EXPORT_SYMBOL_GPL(save_stack_trace_tsk
);