diff options
-rw-r--r-- | arch/x86/entry/entry_32.S | 4 | ||||
-rw-r--r-- | arch/x86/kernel/unwind_frame.c | 12 |
2 files changed, 14 insertions, 2 deletions
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 8a13d468635a..50e0d2bc4528 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S | |||
@@ -176,7 +176,7 @@ | |||
176 | /* | 176 | /* |
177 | * This is a sneaky trick to help the unwinder find pt_regs on the stack. The | 177 | * This is a sneaky trick to help the unwinder find pt_regs on the stack. The |
178 | * frame pointer is replaced with an encoded pointer to pt_regs. The encoding | 178 | * frame pointer is replaced with an encoded pointer to pt_regs. The encoding |
179 | * is just setting the LSB, which makes it an invalid stack address and is also | 179 | * is just clearing the MSB, which makes it an invalid stack address and is also |
180 | * a signal to the unwinder that it's a pt_regs pointer in disguise. | 180 | * a signal to the unwinder that it's a pt_regs pointer in disguise. |
181 | * | 181 | * |
182 | * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the | 182 | * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the |
@@ -185,7 +185,7 @@ | |||
185 | .macro ENCODE_FRAME_POINTER | 185 | .macro ENCODE_FRAME_POINTER |
186 | #ifdef CONFIG_FRAME_POINTER | 186 | #ifdef CONFIG_FRAME_POINTER |
187 | mov %esp, %ebp | 187 | mov %esp, %ebp |
188 | orl $0x1, %ebp | 188 | andl $0x7fffffff, %ebp |
189 | #endif | 189 | #endif |
190 | .endm | 190 | .endm |
191 | 191 | ||
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index d05637726c10..4949bbc95f75 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c | |||
@@ -174,6 +174,7 @@ static bool is_last_task_frame(struct unwind_state *state) | |||
174 | * This determines if the frame pointer actually contains an encoded pointer to | 174 | * This determines if the frame pointer actually contains an encoded pointer to |
175 | * pt_regs on the stack. See ENCODE_FRAME_POINTER. | 175 | * pt_regs on the stack. See ENCODE_FRAME_POINTER. |
176 | */ | 176 | */ |
177 | #ifdef CONFIG_X86_64 | ||
177 | static struct pt_regs *decode_frame_pointer(unsigned long *bp) | 178 | static struct pt_regs *decode_frame_pointer(unsigned long *bp) |
178 | { | 179 | { |
179 | unsigned long regs = (unsigned long)bp; | 180 | unsigned long regs = (unsigned long)bp; |
@@ -183,6 +184,17 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp) | |||
183 | 184 | ||
184 | return (struct pt_regs *)(regs & ~0x1); | 185 | return (struct pt_regs *)(regs & ~0x1); |
185 | } | 186 | } |
187 | #else | ||
188 | static struct pt_regs *decode_frame_pointer(unsigned long *bp) | ||
189 | { | ||
190 | unsigned long regs = (unsigned long)bp; | ||
191 | |||
192 | if (regs & 0x80000000) | ||
193 | return NULL; | ||
194 | |||
195 | return (struct pt_regs *)(regs | 0x80000000); | ||
196 | } | ||
197 | #endif | ||
186 | 198 | ||
187 | #ifdef CONFIG_X86_32 | 199 | #ifdef CONFIG_X86_32 |
188 | #define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long)) | 200 | #define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long)) |