]>
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> |
7b32aead | 12 | #include <asm/switch_to.h> |
c9cf4dbb | 13 | |
cb76c939 JP |
14 | enum stack_type { |
15 | STACK_TYPE_UNKNOWN, | |
16 | STACK_TYPE_TASK, | |
17 | STACK_TYPE_IRQ, | |
18 | STACK_TYPE_SOFTIRQ, | |
19 | STACK_TYPE_EXCEPTION, | |
20 | STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1, | |
21 | }; | |
22 | ||
23 | struct stack_info { | |
24 | enum stack_type type; | |
25 | unsigned long *begin, *end, *next_sp; | |
26 | }; | |
27 | ||
28 | bool in_task_stack(unsigned long *stack, struct task_struct *task, | |
29 | struct stack_info *info); | |
30 | ||
31 | int get_stack_info(unsigned long *stack, struct task_struct *task, | |
32 | struct stack_info *info, unsigned long *visit_mask); | |
33 | ||
3d02a9c4 | 34 | const char *stack_type_name(enum stack_type type); |
cb76c939 JP |
35 | |
36 | static inline bool on_stack(struct stack_info *info, void *addr, size_t len) | |
37 | { | |
38 | void *begin = info->begin; | |
39 | void *end = info->end; | |
40 | ||
41 | return (info->type != STACK_TYPE_UNKNOWN && | |
42 | addr >= begin && addr < end && | |
43 | addr + len > begin && addr + len <= end); | |
44 | } | |
45 | ||
c9cf4dbb FW |
46 | #ifdef CONFIG_X86_32 |
47 | #define STACKSLOTS_PER_LINE 8 | |
c9cf4dbb FW |
48 | #else |
49 | #define STACKSLOTS_PER_LINE 4 | |
c9cf4dbb FW |
50 | #endif |
51 | ||
9c0729dc | 52 | #ifdef CONFIG_FRAME_POINTER |
4b8afafb JP |
53 | static inline unsigned long * |
54 | get_frame_pointer(struct task_struct *task, struct pt_regs *regs) | |
9c0729dc | 55 | { |
9c0729dc | 56 | if (regs) |
4b8afafb | 57 | return (unsigned long *)regs->bp; |
9c0729dc | 58 | |
81539169 | 59 | if (task == current) |
4b8afafb | 60 | return __builtin_frame_address(0); |
9c0729dc | 61 | |
2c96b2fe | 62 | return &((struct inactive_task_frame *)task->thread.sp)->bp; |
9c0729dc SSP |
63 | } |
64 | #else | |
4b8afafb JP |
65 | static inline unsigned long * |
66 | get_frame_pointer(struct task_struct *task, struct pt_regs *regs) | |
9c0729dc | 67 | { |
4b8afafb JP |
68 | return NULL; |
69 | } | |
70 | #endif /* CONFIG_FRAME_POINTER */ | |
71 | ||
72 | static inline unsigned long * | |
73 | get_stack_pointer(struct task_struct *task, struct pt_regs *regs) | |
74 | { | |
75 | if (regs) | |
76 | return (unsigned long *)kernel_stack_pointer(regs); | |
77 | ||
81539169 | 78 | if (task == current) |
4b8afafb JP |
79 | return __builtin_frame_address(0); |
80 | ||
81 | return (unsigned long *)task->thread.sp; | |
9c0729dc | 82 | } |
9c0729dc | 83 | |
e18bcccd JP |
84 | void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, |
85 | unsigned long *stack, char *log_lvl); | |
c9cf4dbb | 86 | |
c9cf4dbb FW |
87 | extern unsigned int code_bytes; |
88 | ||
89 | /* The form of the top of the frame on the stack */ | |
90 | struct stack_frame { | |
91 | struct stack_frame *next_frame; | |
92 | unsigned long return_address; | |
93 | }; | |
94 | ||
95 | struct stack_frame_ia32 { | |
96 | u32 next_frame; | |
97 | u32 return_address; | |
98 | }; | |
99 | ||
b0f82b81 | 100 | static inline unsigned long caller_frame_pointer(void) |
c9cf4dbb FW |
101 | { |
102 | struct stack_frame *frame; | |
103 | ||
4b8afafb | 104 | frame = __builtin_frame_address(0); |
c9cf4dbb FW |
105 | |
106 | #ifdef CONFIG_FRAME_POINTER | |
b0f82b81 | 107 | frame = frame->next_frame; |
c9cf4dbb FW |
108 | #endif |
109 | ||
110 | return (unsigned long)frame; | |
111 | } | |
112 | ||
1965aae3 | 113 | #endif /* _ASM_X86_STACKTRACE_H */ |