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