aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>2012-01-28 13:42:36 +0200
committerPekka Enberg <penberg@kernel.org>2012-01-28 22:19:46 +0200
commit863281a8a685a121bf85f2490500c9d4539066a5 (patch)
tree73583c35de78c2937744cae52204844440bde41b
parent2ffd5b493019fe4e7aa8e2c7b948203291af6a84 (diff)
downloadjato-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.c39
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);