xref: /linux/arch/x86/include/asm/stacktrace.h (revision 3d02a9c48d479eb58841805baaf93c5a084b6010)
1c9cf4dbbSFrederic Weisbecker /*
2c9cf4dbbSFrederic Weisbecker  *  Copyright (C) 1991, 1992  Linus Torvalds
3c9cf4dbbSFrederic Weisbecker  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4c9cf4dbbSFrederic Weisbecker  */
5c9cf4dbbSFrederic Weisbecker 
61965aae3SH. Peter Anvin #ifndef _ASM_X86_STACKTRACE_H
71965aae3SH. Peter Anvin #define _ASM_X86_STACKTRACE_H
8bb898558SAl Viro 
9c9cf4dbbSFrederic Weisbecker #include <linux/uaccess.h>
109c0729dcSSoeren Sandmann Pedersen #include <linux/ptrace.h>
117b32aeadSBrian Gerst #include <asm/switch_to.h>
12c9cf4dbbSFrederic Weisbecker 
13cb76c939SJosh Poimboeuf enum stack_type {
14cb76c939SJosh Poimboeuf 	STACK_TYPE_UNKNOWN,
15cb76c939SJosh Poimboeuf 	STACK_TYPE_TASK,
16cb76c939SJosh Poimboeuf 	STACK_TYPE_IRQ,
17cb76c939SJosh Poimboeuf 	STACK_TYPE_SOFTIRQ,
18cb76c939SJosh Poimboeuf 	STACK_TYPE_EXCEPTION,
19cb76c939SJosh Poimboeuf 	STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
20cb76c939SJosh Poimboeuf };
21cb76c939SJosh Poimboeuf 
22cb76c939SJosh Poimboeuf struct stack_info {
23cb76c939SJosh Poimboeuf 	enum stack_type type;
24cb76c939SJosh Poimboeuf 	unsigned long *begin, *end, *next_sp;
25cb76c939SJosh Poimboeuf };
26cb76c939SJosh Poimboeuf 
27cb76c939SJosh Poimboeuf bool in_task_stack(unsigned long *stack, struct task_struct *task,
28cb76c939SJosh Poimboeuf 		   struct stack_info *info);
29cb76c939SJosh Poimboeuf 
30cb76c939SJosh Poimboeuf int get_stack_info(unsigned long *stack, struct task_struct *task,
31cb76c939SJosh Poimboeuf 		   struct stack_info *info, unsigned long *visit_mask);
32cb76c939SJosh Poimboeuf 
33*3d02a9c4SJosh Poimboeuf const char *stack_type_name(enum stack_type type);
34cb76c939SJosh Poimboeuf 
35cb76c939SJosh Poimboeuf static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
36cb76c939SJosh Poimboeuf {
37cb76c939SJosh Poimboeuf 	void *begin = info->begin;
38cb76c939SJosh Poimboeuf 	void *end   = info->end;
39cb76c939SJosh Poimboeuf 
40cb76c939SJosh Poimboeuf 	return (info->type != STACK_TYPE_UNKNOWN &&
41cb76c939SJosh Poimboeuf 		addr >= begin && addr < end &&
42cb76c939SJosh Poimboeuf 		addr + len > begin && addr + len <= end);
43cb76c939SJosh Poimboeuf }
44cb76c939SJosh Poimboeuf 
45c9cf4dbbSFrederic Weisbecker #ifdef CONFIG_X86_32
46c9cf4dbbSFrederic Weisbecker #define STACKSLOTS_PER_LINE 8
47c9cf4dbbSFrederic Weisbecker #else
48c9cf4dbbSFrederic Weisbecker #define STACKSLOTS_PER_LINE 4
49c9cf4dbbSFrederic Weisbecker #endif
50c9cf4dbbSFrederic Weisbecker 
519c0729dcSSoeren Sandmann Pedersen #ifdef CONFIG_FRAME_POINTER
524b8afafbSJosh Poimboeuf static inline unsigned long *
534b8afafbSJosh Poimboeuf get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
549c0729dcSSoeren Sandmann Pedersen {
559c0729dcSSoeren Sandmann Pedersen 	if (regs)
564b8afafbSJosh Poimboeuf 		return (unsigned long *)regs->bp;
579c0729dcSSoeren Sandmann Pedersen 
5881539169SJosh Poimboeuf 	if (task == current)
594b8afafbSJosh Poimboeuf 		return __builtin_frame_address(0);
609c0729dcSSoeren Sandmann Pedersen 
614b8afafbSJosh Poimboeuf 	return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
629c0729dcSSoeren Sandmann Pedersen }
639c0729dcSSoeren Sandmann Pedersen #else
644b8afafbSJosh Poimboeuf static inline unsigned long *
654b8afafbSJosh Poimboeuf get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
669c0729dcSSoeren Sandmann Pedersen {
674b8afafbSJosh Poimboeuf 	return NULL;
689c0729dcSSoeren Sandmann Pedersen }
694b8afafbSJosh Poimboeuf #endif /* CONFIG_FRAME_POINTER */
704b8afafbSJosh Poimboeuf 
714b8afafbSJosh Poimboeuf static inline unsigned long *
724b8afafbSJosh Poimboeuf get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
734b8afafbSJosh Poimboeuf {
744b8afafbSJosh Poimboeuf 	if (regs)
754b8afafbSJosh Poimboeuf 		return (unsigned long *)kernel_stack_pointer(regs);
764b8afafbSJosh Poimboeuf 
7781539169SJosh Poimboeuf 	if (task == current)
784b8afafbSJosh Poimboeuf 		return __builtin_frame_address(0);
794b8afafbSJosh Poimboeuf 
804b8afafbSJosh Poimboeuf 	return (unsigned long *)task->thread.sp;
814b8afafbSJosh Poimboeuf }
829c0729dcSSoeren Sandmann Pedersen 
83e18bcccdSJosh Poimboeuf void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
84e18bcccdSJosh Poimboeuf 			unsigned long *stack, char *log_lvl);
85c9cf4dbbSFrederic Weisbecker 
86c9cf4dbbSFrederic Weisbecker extern unsigned int code_bytes;
87c9cf4dbbSFrederic Weisbecker 
88c9cf4dbbSFrederic Weisbecker /* The form of the top of the frame on the stack */
89c9cf4dbbSFrederic Weisbecker struct stack_frame {
90c9cf4dbbSFrederic Weisbecker 	struct stack_frame *next_frame;
91c9cf4dbbSFrederic Weisbecker 	unsigned long return_address;
92c9cf4dbbSFrederic Weisbecker };
93c9cf4dbbSFrederic Weisbecker 
94c9cf4dbbSFrederic Weisbecker struct stack_frame_ia32 {
95c9cf4dbbSFrederic Weisbecker     u32 next_frame;
96c9cf4dbbSFrederic Weisbecker     u32 return_address;
97c9cf4dbbSFrederic Weisbecker };
98c9cf4dbbSFrederic Weisbecker 
99b0f82b81SFrederic Weisbecker static inline unsigned long caller_frame_pointer(void)
100c9cf4dbbSFrederic Weisbecker {
101c9cf4dbbSFrederic Weisbecker 	struct stack_frame *frame;
102c9cf4dbbSFrederic Weisbecker 
1034b8afafbSJosh Poimboeuf 	frame = __builtin_frame_address(0);
104c9cf4dbbSFrederic Weisbecker 
105c9cf4dbbSFrederic Weisbecker #ifdef CONFIG_FRAME_POINTER
106b0f82b81SFrederic Weisbecker 	frame = frame->next_frame;
107c9cf4dbbSFrederic Weisbecker #endif
108c9cf4dbbSFrederic Weisbecker 
109c9cf4dbbSFrederic Weisbecker 	return (unsigned long)frame;
110c9cf4dbbSFrederic Weisbecker }
111c9cf4dbbSFrederic Weisbecker 
1121965aae3SH. Peter Anvin #endif /* _ASM_X86_STACKTRACE_H */
113