#ifndef _ASM_X86_UNWIND_H #define _ASM_X86_UNWIND_H #include #include #include #include struct unwind_state { struct stack_info stack_info; unsigned long stack_mask; struct task_struct *task; int graph_idx; #ifdef CONFIG_FRAME_POINTER unsigned long *bp; #else unsigned long *sp; #endif }; void __unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame); bool unwind_next_frame(struct unwind_state *state); static inline bool unwind_done(struct unwind_state *state) { return state->stack_info.type == STACK_TYPE_UNKNOWN; } static inline void unwind_start(struct unwind_state *state, struct task_struct *task, struct pt_regs *regs, unsigned long *first_frame) { first_frame = first_frame ? : get_stack_pointer(task, regs); __unwind_start(state, task, regs, first_frame); } #ifdef CONFIG_FRAME_POINTER static inline unsigned long *unwind_get_return_address_ptr(struct unwind_state *state) { if (unwind_done(state)) return NULL; return state->bp + 1; } unsigned long unwind_get_return_address(struct unwind_state *state); #else /* !CONFIG_FRAME_POINTER */ static inline unsigned long *unwind_get_return_address_ptr(struct unwind_state *state) { return NULL; } static inline unsigned long unwind_get_return_address(struct unwind_state *state) { if (unwind_done(state)) return 0; return ftrace_graph_ret_addr(state->task, &state->graph_idx, *state->sp, state->sp); } #endif /* CONFIG_FRAME_POINTER */ #endif /* _ASM_X86_UNWIND_H */