Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  *  Copyright (C) 1991, 1992  Linus Torvalds
0004  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
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     /* make sure it's not in the stack proper */
0045     if (get_stack_info_noinstr(stack, current, info))
0046         return false;
0047     /* but if it is in the page below it, we hit a guard */
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 /* CONFIG_FRAME_POINTER */
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 /* The form of the top of the frame on the stack */
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 /* _ASM_X86_STACKTRACE_H */