Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
c9cf4dbb FW |
2 | /* |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | |
4 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | |
5 | */ | |
6 | ||
1965aae3 PA |
7 | #ifndef _ASM_X86_STACKTRACE_H |
8 | #define _ASM_X86_STACKTRACE_H | |
c0b766f1 | 9 | |
c9cf4dbb | 10 | #include <linux/uaccess.h> |
9c0729dc | 11 | #include <linux/ptrace.h> |
32074269 TG |
12 | |
13 | #include <asm/cpu_entry_area.h> | |
7b32aead | 14 | #include <asm/switch_to.h> |
c9cf4dbb | 15 | |
cb76c939 JP |
16 | enum stack_type { |
17 | STACK_TYPE_UNKNOWN, | |
18 | STACK_TYPE_TASK, | |
19 | STACK_TYPE_IRQ, | |
20 | STACK_TYPE_SOFTIRQ, | |
4fe2d8b1 | 21 | STACK_TYPE_ENTRY, |
cb76c939 JP |
22 | STACK_TYPE_EXCEPTION, |
23 | STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1, | |
24 | }; | |
25 | ||
26 | struct stack_info { | |
27 | enum stack_type type; | |
28 | unsigned long *begin, *end, *next_sp; | |
29 | }; | |
30 | ||
31 | bool in_task_stack(unsigned long *stack, struct task_struct *task, | |
32 | struct stack_info *info); | |
33 | ||
4fe2d8b1 | 34 | bool in_entry_stack(unsigned long *stack, struct stack_info *info); |
33a2f1a6 | 35 | |
cb76c939 JP |
36 | int get_stack_info(unsigned long *stack, struct task_struct *task, |
37 | struct stack_info *info, unsigned long *visit_mask); | |
6b27edd7 JR |
38 | bool get_stack_info_noinstr(unsigned long *stack, struct task_struct *task, |
39 | struct stack_info *info); | |
cb76c939 | 40 | |
44b979fa PZ |
41 | static __always_inline |
42 | bool get_stack_guard_info(unsigned long *stack, struct stack_info *info) | |
43 | { | |
44 | /* make sure it's not in the stack proper */ | |
45 | if (get_stack_info_noinstr(stack, current, info)) | |
46 | return false; | |
47 | /* but if it is in the page below it, we hit a guard */ | |
48 | return get_stack_info_noinstr((void *)stack + PAGE_SIZE, current, info); | |
49 | } | |
50 | ||
3d02a9c4 | 51 | const char *stack_type_name(enum stack_type type); |
cb76c939 JP |
52 | |
53 | static inline bool on_stack(struct stack_info *info, void *addr, size_t len) | |
54 | { | |
55 | void *begin = info->begin; | |
56 | void *end = info->end; | |
57 | ||
58 | return (info->type != STACK_TYPE_UNKNOWN && | |
59 | addr >= begin && addr < end && | |
60 | addr + len > begin && addr + len <= end); | |
61 | } | |
62 | ||
c9cf4dbb FW |
63 | #ifdef CONFIG_X86_32 |
64 | #define STACKSLOTS_PER_LINE 8 | |
c9cf4dbb FW |
65 | #else |
66 | #define STACKSLOTS_PER_LINE 4 | |
c9cf4dbb FW |
67 | #endif |
68 | ||
9c0729dc | 69 | #ifdef CONFIG_FRAME_POINTER |
4b8afafb JP |
70 | static inline unsigned long * |
71 | get_frame_pointer(struct task_struct *task, struct pt_regs *regs) | |
9c0729dc | 72 | { |
9c0729dc | 73 | if (regs) |
4b8afafb | 74 | return (unsigned long *)regs->bp; |
9c0729dc | 75 | |
81539169 | 76 | if (task == current) |
4b8afafb | 77 | return __builtin_frame_address(0); |
9c0729dc | 78 | |
2c96b2fe | 79 | return &((struct inactive_task_frame *)task->thread.sp)->bp; |
9c0729dc SSP |
80 | } |
81 | #else | |
4b8afafb JP |
82 | static inline unsigned long * |
83 | get_frame_pointer(struct task_struct *task, struct pt_regs *regs) | |
9c0729dc | 84 | { |
4b8afafb JP |
85 | return NULL; |
86 | } | |
87 | #endif /* CONFIG_FRAME_POINTER */ | |
88 | ||
89 | static inline unsigned long * | |
90 | get_stack_pointer(struct task_struct *task, struct pt_regs *regs) | |
91 | { | |
92 | if (regs) | |
3c88c692 | 93 | return (unsigned long *)regs->sp; |
4b8afafb | 94 | |
81539169 | 95 | if (task == current) |
4b8afafb JP |
96 | return __builtin_frame_address(0); |
97 | ||
98 | return (unsigned long *)task->thread.sp; | |
9c0729dc | 99 | } |
9c0729dc | 100 | |
c9cf4dbb FW |
101 | /* The form of the top of the frame on the stack */ |
102 | struct stack_frame { | |
103 | struct stack_frame *next_frame; | |
104 | unsigned long return_address; | |
105 | }; | |
106 | ||
107 | struct stack_frame_ia32 { | |
108 | u32 next_frame; | |
109 | u32 return_address; | |
110 | }; | |
111 | ||
342db04a | 112 | void show_opcodes(struct pt_regs *regs, const char *loglvl); |
7cccf072 | 113 | void show_ip(struct pt_regs *regs, const char *loglvl); |
1965aae3 | 114 | #endif /* _ASM_X86_STACKTRACE_H */ |