diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/traps.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index cfffe3dd9e83..47b0bef335bd 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -100,36 +100,45 @@ asmlinkage void machine_check(void); | |||
100 | int kstack_depth_to_print = 24; | 100 | int kstack_depth_to_print = 24; |
101 | static unsigned int code_bytes = 64; | 101 | static unsigned int code_bytes = 64; |
102 | 102 | ||
103 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | 103 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) |
104 | { | 104 | { |
105 | return p > (void *)tinfo && | 105 | return p > (void *)tinfo && |
106 | p < (void *)tinfo + THREAD_SIZE - 3; | 106 | p <= (void *)tinfo + THREAD_SIZE - size; |
107 | } | 107 | } |
108 | 108 | ||
109 | /* The form of the top of the frame on the stack */ | ||
110 | struct stack_frame { | ||
111 | struct stack_frame *next_frame; | ||
112 | unsigned long return_address; | ||
113 | }; | ||
114 | |||
109 | static inline unsigned long print_context_stack(struct thread_info *tinfo, | 115 | static inline unsigned long print_context_stack(struct thread_info *tinfo, |
110 | unsigned long *stack, unsigned long ebp, | 116 | unsigned long *stack, unsigned long ebp, |
111 | struct stacktrace_ops *ops, void *data) | 117 | struct stacktrace_ops *ops, void *data) |
112 | { | 118 | { |
113 | unsigned long addr; | ||
114 | |||
115 | #ifdef CONFIG_FRAME_POINTER | 119 | #ifdef CONFIG_FRAME_POINTER |
116 | while (valid_stack_ptr(tinfo, (void *)ebp)) { | 120 | struct stack_frame *frame = (struct stack_frame *)ebp; |
117 | unsigned long new_ebp; | 121 | while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) { |
118 | addr = *(unsigned long *)(ebp + 4); | 122 | struct stack_frame *next; |
123 | unsigned long addr; | ||
124 | |||
125 | addr = frame->return_address; | ||
119 | ops->address(data, addr); | 126 | ops->address(data, addr); |
120 | /* | 127 | /* |
121 | * break out of recursive entries (such as | 128 | * break out of recursive entries (such as |
122 | * end_of_stack_stop_unwind_function). Also, | 129 | * end_of_stack_stop_unwind_function). Also, |
123 | * we can never allow a frame pointer to | 130 | * we can never allow a frame pointer to |
124 | * move downwards! | 131 | * move downwards! |
125 | */ | 132 | */ |
126 | new_ebp = *(unsigned long *)ebp; | 133 | next = frame->next_frame; |
127 | if (new_ebp <= ebp) | 134 | if (next <= frame) |
128 | break; | 135 | break; |
129 | ebp = new_ebp; | 136 | frame = next; |
130 | } | 137 | } |
131 | #else | 138 | #else |
132 | while (valid_stack_ptr(tinfo, stack)) { | 139 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { |
140 | unsigned long addr; | ||
141 | |||
133 | addr = *stack++; | 142 | addr = *stack++; |
134 | if (__kernel_text_address(addr)) | 143 | if (__kernel_text_address(addr)) |
135 | ops->address(data, addr); | 144 | ops->address(data, addr); |