diff options
author | Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> | 2012-01-28 13:42:36 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-01-28 22:19:46 +0200 |
commit | 863281a8a685a121bf85f2490500c9d4539066a5 (patch) | |
tree | 73583c35de78c2937744cae52204844440bde41b | |
parent | 2ffd5b493019fe4e7aa8e2c7b948203291af6a84 (diff) | |
download | jato-863281a8a685a121bf85f2490500c9d4539066a5.tar.gz |
x86-64: add stack redzoning
This places a canary value on the stack to check for corruption. Despite
being called "redzoning", it has nothing to do with the x86-64 redzone
as described in the ABI.
Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | arch/x86/emit_64.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/emit_64.c b/arch/x86/emit_64.c index f7ec81ea..3791c9fe 100644 --- a/arch/x86/emit_64.c +++ b/arch/x86/emit_64.c @@ -45,6 +45,7 @@ #include "jit/stack-slot.h" #include "jit/statement.h" #include "jit/compiler.h" +#include "jit/debug.h" #include "jit/exception.h" #include "jit/emit-code.h" #include "jit/text.h" @@ -1199,6 +1200,8 @@ static void emit_restore_callee_save_regs(struct buffer *buf) } } +#define STACK_FRAME_REDZONE_END 0xdeadbeefcafebabe + void emit_prolog(struct buffer *buf, struct stack_frame *frame, unsigned long frame_size) { @@ -1218,6 +1221,11 @@ void emit_prolog(struct buffer *buf, struct stack_frame *frame, /* Save *this. */ __emit_push_reg(buf, MACH_REG_RDI); + + if (opt_debug_stack) { + __emit_mov_imm_reg(buf, STACK_FRAME_REDZONE_END, MACH_REG_RAX); + __emit_push_reg(buf, MACH_REG_RAX); + } } static void emit_restore_regs(struct buffer *buf) @@ -1228,8 +1236,36 @@ static void emit_restore_regs(struct buffer *buf) emit_restore_callee_save_regs(buf); } +static void do_stack_redzone_check(unsigned long magic) +{ + unsigned long addr = (unsigned long) __builtin_return_address(0); + + if (magic == STACK_FRAME_REDZONE_END) + return; + + printf("Stack frame redzone overwritten at %lx: %lx\n", addr, magic); + abort(); +} + +static void emit_stack_redzone_check(struct buffer *buf) +{ + /* Pass the magic value to do_stack_redzone_check(). */ + __emit_pop_reg(buf, MACH_REG_RDI); + + __emit_push_reg(buf, MACH_REG_RAX); + __emit64_push_xmm(buf, MACH_REG_XMM0); + + __emit_call(buf, do_stack_redzone_check); + + __emit64_pop_xmm(buf, MACH_REG_XMM0); + __emit_pop_reg(buf, MACH_REG_RAX); +} + void emit_epilog(struct buffer *buf) { + if (opt_debug_stack) + emit_stack_redzone_check(buf); + emit_restore_regs(buf); emit_leave(buf); emit_ret(buf); @@ -1241,6 +1277,9 @@ void emit_epilog(struct buffer *buf) */ void emit_unwind(struct buffer *buf) { + if (opt_debug_stack) + emit_stack_redzone_check(buf); + emit_restore_regs(buf); emit_leave(buf); __emit_jmp(buf, (unsigned long)&unwind); |