blob: c4b6d1cafa4659caa82c660eda69ab2a52720ebf [file] [log] [blame]
Josh Poimboeuf7c7900f2016-09-16 14:18:12 -05001#ifndef _ASM_X86_UNWIND_H
2#define _ASM_X86_UNWIND_H
3
4#include <linux/sched.h>
5#include <linux/ftrace.h>
6#include <asm/ptrace.h>
7#include <asm/stacktrace.h>
8
9struct unwind_state {
10 struct stack_info stack_info;
11 unsigned long stack_mask;
12 struct task_struct *task;
13 int graph_idx;
14#ifdef CONFIG_FRAME_POINTER
15 unsigned long *bp;
16#else
17 unsigned long *sp;
18#endif
19};
20
21void __unwind_start(struct unwind_state *state, struct task_struct *task,
22 struct pt_regs *regs, unsigned long *first_frame);
23
24bool unwind_next_frame(struct unwind_state *state);
25
26static inline bool unwind_done(struct unwind_state *state)
27{
28 return state->stack_info.type == STACK_TYPE_UNKNOWN;
29}
30
31static inline
32void unwind_start(struct unwind_state *state, struct task_struct *task,
33 struct pt_regs *regs, unsigned long *first_frame)
34{
35 first_frame = first_frame ? : get_stack_pointer(task, regs);
36
37 __unwind_start(state, task, regs, first_frame);
38}
39
40#ifdef CONFIG_FRAME_POINTER
41
42static inline
43unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
44{
45 if (unwind_done(state))
46 return NULL;
47
48 return state->bp + 1;
49}
50
51unsigned long unwind_get_return_address(struct unwind_state *state);
52
53#else /* !CONFIG_FRAME_POINTER */
54
55static inline
56unsigned long *unwind_get_return_address_ptr(struct unwind_state *state)
57{
58 return NULL;
59}
60
61static inline
62unsigned long unwind_get_return_address(struct unwind_state *state)
63{
64 if (unwind_done(state))
65 return 0;
66
67 return ftrace_graph_ret_addr(state->task, &state->graph_idx,
68 *state->sp, state->sp);
69}
70
71#endif /* CONFIG_FRAME_POINTER */
72
73#endif /* _ASM_X86_UNWIND_H */