diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-01-13 19:47:21 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-02-01 17:03:48 +0200 |
commit | af7dedb289556e0c206d436c45c64f326013e120 (patch) | |
tree | 41853295b2f7d1ec7707343440bfb6e19c2ca07f | |
parent | f784e9727db3d2c891bf0bb20a1ad4135a9fe5c8 (diff) | |
download | jato-af7dedb289556e0c206d436c45c64f326013e120.tar.gz |
x86-32: Fix non-standard stack frame layout
This patch fixes the non-standard stack frame layout on 32-bit. Prolog is
changed as follows:
Before:
[main] 0xa736b790: 57 push %edi
[main] 0xa736b791: 56 push %esi
[main] 0xa736b792: 53 push %ebx
[main] 0xa736b793: 55 push %ebp
[main] 0xa736b794: 89 e5 mov %esp,%ebp
[main] 0xa736b796: 83 ec 10 sub $0x10,%esp
After:
[main] 0xa73db4a8: 55 push %ebp
[main] 0xa73db4a9: 89 e5 mov %esp,%ebp
[main] 0xa73db4ab: 83 ec 10 sub $0x10,%esp
[main] 0xa73db4ae: 57 push %edi
[main] 0xa73db4af: 56 push %esi
[main] 0xa73db4b0: 53 push %ebx
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | arch/x86/emit_32.c | 12 | ||||
-rw-r--r-- | arch/x86/emit_64.c | 4 | ||||
-rw-r--r-- | arch/x86/include/arch/stack-frame.h | 3 | ||||
-rw-r--r-- | arch/x86/stack-frame.c | 8 | ||||
-rw-r--r-- | test/unit/arch-x86/encode-test.c | 6 |
5 files changed, 8 insertions, 25 deletions
diff --git a/arch/x86/emit_32.c b/arch/x86/emit_32.c index 40004c06..f133bdac 100644 --- a/arch/x86/emit_32.c +++ b/arch/x86/emit_32.c @@ -621,14 +621,14 @@ static void emit_restore_callee_save_regs(struct buffer *buf) void emit_prolog(struct buffer *buf, struct stack_frame *frame, unsigned long frame_size) { - emit_save_callee_save_regs(buf); - __emit_push_reg(buf, MACH_REG_EBP); __emit_mov_reg_reg(buf, MACH_REG_ESP, MACH_REG_EBP); if (frame_size) __emit_sub_imm_reg(buf, frame_size, MACH_REG_ESP); + emit_save_callee_save_regs(buf); + if (opt_debug_stack) __emit_push_imm(buf, STACK_FRAME_REDZONE_END); } @@ -667,22 +667,18 @@ void emit_epilog(struct buffer *buf) if (opt_debug_stack) emit_stack_redzone_check(buf); - emit_leave(buf); emit_restore_regs(buf); + emit_leave(buf); emit_ret(buf); } -/* - * FIXME: We use different stack layout on 32-bit and 64-bit so prolog, epilog, - * and unwind sequences are slightly different. - */ void emit_unwind(struct buffer *buf) { if (opt_debug_stack) emit_stack_redzone_check(buf); - emit_leave(buf); emit_restore_regs(buf); + emit_leave(buf); __emit_jmp(buf, (unsigned long)&unwind); } diff --git a/arch/x86/emit_64.c b/arch/x86/emit_64.c index f78bb665..081ab8df 100644 --- a/arch/x86/emit_64.c +++ b/arch/x86/emit_64.c @@ -1265,10 +1265,6 @@ void emit_epilog(struct buffer *buf) emit_ret(buf); } -/* - * FIXME: We use different stack layout on 32-bit and 64-bit so prolog, epilog, - * and unwind sequences are slightly different. - */ void emit_unwind(struct buffer *buf) { if (opt_debug_stack) diff --git a/arch/x86/include/arch/stack-frame.h b/arch/x86/include/arch/stack-frame.h index fc0ab27c..d19e58e4 100644 --- a/arch/x86/include/arch/stack-frame.h +++ b/arch/x86/include/arch/stack-frame.h @@ -22,9 +22,6 @@ struct native_stack_frame { struct jit_stack_frame { void *prev; /* previous stack frame link */ - unsigned long old_ebx; - unsigned long old_esi; - unsigned long old_edi; unsigned long return_address; unsigned long args[0]; } __attribute__((packed)); diff --git a/arch/x86/stack-frame.c b/arch/x86/stack-frame.c index c7db807e..236c2960 100644 --- a/arch/x86/stack-frame.c +++ b/arch/x86/stack-frame.c @@ -40,10 +40,7 @@ #include "arch/stack-frame.h" /* - * The three callee-saved registers are unconditionally stored on the stack - * after EIP and EBP (see emit_prolog() for details). Therefore, there are five - * 32-bit stack slots before the first argument to a function as illustrated by - * the following diagram: + * The stack frame layout is illustrated by the following diagram: * * : : ^ * : : | Higher memory addresses @@ -52,9 +49,6 @@ * : ... : * | Arg 1 | <-- Start offset of arguments * | Old EIP | - * | EDI | - * | ESI | - * | EBX | * | Old EBP | <-- New EBP * | Local 1 | * : ... : diff --git a/test/unit/arch-x86/encode-test.c b/test/unit/arch-x86/encode-test.c index 56f8d09d..e417d890 100644 --- a/test/unit/arch-x86/encode-test.c +++ b/test/unit/arch-x86/encode-test.c @@ -948,7 +948,7 @@ void test_encoding_reg_memdisp(void) void test_encoding_memlocal(void) { #ifdef CONFIG_32_BIT - uint8_t encoding[] = { 0xff, 0xb5, 0x14, 0x00, 0x00, 0x00 }; + uint8_t encoding[] = { 0xff, 0xb5, 0x08, 0x00, 0x00, 0x00 }; #else uint8_t encoding[] = { 0xff, 0xb5, 0x10, 0x00, 0x00, 0x00 }; #endif @@ -981,7 +981,7 @@ void test_encoding_memlocal(void) void test_encoding_fstp_memlocal(void) { #ifdef CONFIG_32_BIT - uint8_t encoding[] = { 0xd9, 0x9d, 0x14, 0x00, 0x00, 0x00 }; + uint8_t encoding[] = { 0xd9, 0x9d, 0x08, 0x00, 0x00, 0x00 }; #else uint8_t encoding[] = { 0xd9, 0x9d, 0x10, 0x00, 0x00, 0x00 }; #endif @@ -1014,7 +1014,7 @@ void test_encoding_fstp_memlocal(void) void test_encoding_fstp_64_memlocal(void) { #ifdef CONFIG_32_BIT - uint8_t encoding[] = { 0xdd, 0x9d, 0x14, 0x00, 0x00, 0x00 }; + uint8_t encoding[] = { 0xdd, 0x9d, 0x08, 0x00, 0x00, 0x00 }; #else uint8_t encoding[] = { 0xdd, 0x9d, 0x10, 0x00, 0x00, 0x00 }; #endif |