diff options
Diffstat (limited to 'arch/x86/include/asm/stacktrace.h')
| -rw-r--r-- | arch/x86/include/asm/stacktrace.h | 120 | 
1 files changed, 60 insertions, 60 deletions
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index 0944218af9e2..37f2e0b377ad 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -8,86 +8,86 @@  #include <linux/uaccess.h>  #include <linux/ptrace.h> +#include <asm/switch_to.h> + +enum stack_type { +	STACK_TYPE_UNKNOWN, +	STACK_TYPE_TASK, +	STACK_TYPE_IRQ, +	STACK_TYPE_SOFTIRQ, +	STACK_TYPE_EXCEPTION, +	STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1, +}; -extern int kstack_depth_to_print; - -struct thread_info; -struct stacktrace_ops; - -typedef unsigned long (*walk_stack_t)(struct task_struct *task, -				      unsigned long *stack, -				      unsigned long bp, -				      const struct stacktrace_ops *ops, -				      void *data, -				      unsigned long *end, -				      int *graph); - -extern unsigned long -print_context_stack(struct task_struct *task, -		    unsigned long *stack, unsigned long bp, -		    const struct stacktrace_ops *ops, void *data, -		    unsigned long *end, int *graph); - -extern unsigned long -print_context_stack_bp(struct task_struct *task, -		       unsigned long *stack, unsigned long bp, -		       const struct stacktrace_ops *ops, void *data, -		       unsigned long *end, int *graph); - -/* Generic stack tracer with callbacks */ - -struct stacktrace_ops { -	int (*address)(void *data, unsigned long address, int reliable); -	/* On negative return stop dumping */ -	int (*stack)(void *data, char *name); -	walk_stack_t	walk_stack; +struct stack_info { +	enum stack_type type; +	unsigned long *begin, *end, *next_sp;  }; -void dump_trace(struct task_struct *tsk, struct pt_regs *regs, -		unsigned long *stack, unsigned long bp, -		const struct stacktrace_ops *ops, void *data); +bool in_task_stack(unsigned long *stack, struct task_struct *task, +		   struct stack_info *info); + +int get_stack_info(unsigned long *stack, struct task_struct *task, +		   struct stack_info *info, unsigned long *visit_mask); + +void stack_type_str(enum stack_type type, const char **begin, +		    const char **end); + +static inline bool on_stack(struct stack_info *info, void *addr, size_t len) +{ +	void *begin = info->begin; +	void *end   = info->end; + +	return (info->type != STACK_TYPE_UNKNOWN && +		addr >= begin && addr < end && +		addr + len > begin && addr + len <= end); +} + +extern int kstack_depth_to_print;  #ifdef CONFIG_X86_32  #define STACKSLOTS_PER_LINE 8 -#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)  #else  #define STACKSLOTS_PER_LINE 4 -#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)  #endif  #ifdef CONFIG_FRAME_POINTER -static inline unsigned long -stack_frame(struct task_struct *task, struct pt_regs *regs) +static inline unsigned long * +get_frame_pointer(struct task_struct *task, struct pt_regs *regs)  { -	unsigned long bp; -  	if (regs) -		return regs->bp; +		return (unsigned long *)regs->bp; -	if (task == current) { -		/* Grab bp right from our regs */ -		get_bp(bp); -		return bp; -	} +	if (task == current) +		return __builtin_frame_address(0); -	/* bp is the last reg pushed by switch_to */ -	return *(unsigned long *)task->thread.sp; +	return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;  }  #else -static inline unsigned long -stack_frame(struct task_struct *task, struct pt_regs *regs) +static inline unsigned long * +get_frame_pointer(struct task_struct *task, struct pt_regs *regs)  { -	return 0; +	return NULL; +} +#endif /* CONFIG_FRAME_POINTER */ + +static inline unsigned long * +get_stack_pointer(struct task_struct *task, struct pt_regs *regs) +{ +	if (regs) +		return (unsigned long *)kernel_stack_pointer(regs); + +	if (task == current) +		return __builtin_frame_address(0); + +	return (unsigned long *)task->thread.sp;  } -#endif -extern void -show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, -		   unsigned long *stack, unsigned long bp, char *log_lvl); +void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, +			unsigned long *stack, char *log_lvl); -extern void -show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, -		   unsigned long *sp, unsigned long bp, char *log_lvl); +void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, +			unsigned long *sp, char *log_lvl);  extern unsigned int code_bytes; @@ -106,7 +106,7 @@ static inline unsigned long caller_frame_pointer(void)  {  	struct stack_frame *frame; -	get_bp(frame); +	frame = __builtin_frame_address(0);  #ifdef CONFIG_FRAME_POINTER  	frame = frame->next_frame;  |