0001
0002
0003
0004
0005
0006
0007 #ifndef _ASM_X86_STACKTRACE_H
0008 #define _ASM_X86_STACKTRACE_H
0009
0010 #include <linux/uaccess.h>
0011 #include <linux/ptrace.h>
0012
0013 #include <asm/cpu_entry_area.h>
0014 #include <asm/switch_to.h>
0015
0016 enum stack_type {
0017 STACK_TYPE_UNKNOWN,
0018 STACK_TYPE_TASK,
0019 STACK_TYPE_IRQ,
0020 STACK_TYPE_SOFTIRQ,
0021 STACK_TYPE_ENTRY,
0022 STACK_TYPE_EXCEPTION,
0023 STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
0024 };
0025
0026 struct stack_info {
0027 enum stack_type type;
0028 unsigned long *begin, *end, *next_sp;
0029 };
0030
0031 bool in_task_stack(unsigned long *stack, struct task_struct *task,
0032 struct stack_info *info);
0033
0034 bool in_entry_stack(unsigned long *stack, struct stack_info *info);
0035
0036 int get_stack_info(unsigned long *stack, struct task_struct *task,
0037 struct stack_info *info, unsigned long *visit_mask);
0038 bool get_stack_info_noinstr(unsigned long *stack, struct task_struct *task,
0039 struct stack_info *info);
0040
0041 static __always_inline
0042 bool get_stack_guard_info(unsigned long *stack, struct stack_info *info)
0043 {
0044
0045 if (get_stack_info_noinstr(stack, current, info))
0046 return false;
0047
0048 return get_stack_info_noinstr((void *)stack + PAGE_SIZE, current, info);
0049 }
0050
0051 const char *stack_type_name(enum stack_type type);
0052
0053 static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
0054 {
0055 void *begin = info->begin;
0056 void *end = info->end;
0057
0058 return (info->type != STACK_TYPE_UNKNOWN &&
0059 addr >= begin && addr < end &&
0060 addr + len > begin && addr + len <= end);
0061 }
0062
0063 #ifdef CONFIG_X86_32
0064 #define STACKSLOTS_PER_LINE 8
0065 #else
0066 #define STACKSLOTS_PER_LINE 4
0067 #endif
0068
0069 #ifdef CONFIG_FRAME_POINTER
0070 static inline unsigned long *
0071 get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
0072 {
0073 if (regs)
0074 return (unsigned long *)regs->bp;
0075
0076 if (task == current)
0077 return __builtin_frame_address(0);
0078
0079 return &((struct inactive_task_frame *)task->thread.sp)->bp;
0080 }
0081 #else
0082 static inline unsigned long *
0083 get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
0084 {
0085 return NULL;
0086 }
0087 #endif
0088
0089 static inline unsigned long *
0090 get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
0091 {
0092 if (regs)
0093 return (unsigned long *)regs->sp;
0094
0095 if (task == current)
0096 return __builtin_frame_address(0);
0097
0098 return (unsigned long *)task->thread.sp;
0099 }
0100
0101
0102 struct stack_frame {
0103 struct stack_frame *next_frame;
0104 unsigned long return_address;
0105 };
0106
0107 struct stack_frame_ia32 {
0108 u32 next_frame;
0109 u32 return_address;
0110 };
0111
0112 void show_opcodes(struct pt_regs *regs, const char *loglvl);
0113 void show_ip(struct pt_regs *regs, const char *loglvl);
0114 #endif