aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>2012-02-08 18:49:49 +0200
committerPekka Enberg <penberg@kernel.org>2012-02-08 22:24:46 +0200
commit8c6cee29f742f068d8acb3a981bf5d67bb7f5dea (patch)
treeb90cd9084bb47665ebc7dae6dd08615bb7e71e13
parentfef481ea7313e286813f9435324350dd0625ace8 (diff)
downloadjato-8c6cee29f742f068d8acb3a981bf5d67bb7f5dea.tar.gz
x86, x86-64: restore the stack frame correctly when unwinding
In addition to space reserved for locals, unwinding has to account for callee-saved registers and other values saved on the stack. Both x86 and x86-64 were affected, the former since it adopted a few stack layout changes (standard prologs/epilogs and canaries), while the latter seems to have been affected for a long time. Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--arch/x86/include/arch/stack-frame.h1
-rw-r--r--arch/x86/stack-frame.c25
-rw-r--r--arch/x86/unwind_32.S2
-rw-r--r--arch/x86/unwind_64.S2
-rw-r--r--test/unit/arch-x86/Makefile1
-rw-r--r--test/unit/jit/emit-stub.c3
6 files changed, 32 insertions, 2 deletions
diff --git a/arch/x86/include/arch/stack-frame.h b/arch/x86/include/arch/stack-frame.h
index d19e58e4..aa932fe4 100644
--- a/arch/x86/include/arch/stack-frame.h
+++ b/arch/x86/include/arch/stack-frame.h
@@ -43,5 +43,6 @@ unsigned long slot_offset(struct stack_slot *slot);
unsigned long slot_offset_64(struct stack_slot *slot);
unsigned long frame_locals_size(struct stack_frame *frame);
unsigned long cu_frame_locals_offset(struct compilation_unit *cu);
+unsigned long cu_frame_total_offset(struct compilation_unit *cu);
#endif
diff --git a/arch/x86/stack-frame.c b/arch/x86/stack-frame.c
index 236c2960..1aa884bf 100644
--- a/arch/x86/stack-frame.c
+++ b/arch/x86/stack-frame.c
@@ -32,6 +32,7 @@
#include "jit/compiler.h"
#include "jit/args.h"
#include "jit/text.h"
+#include "jit/debug.h"
#include "vm/stack-trace.h"
#include "vm/method.h"
@@ -58,6 +59,19 @@
#define ARGS_START_OFFSET offsetof(struct jit_stack_frame, args)
+#ifdef CONFIG_X86_32
+static unsigned long cu_frame_misc_size(struct compilation_unit *cu)
+{
+ return (opt_debug_stack ? sizeof(unsigned long) : 0); /* canary */
+}
+#else
+static unsigned long cu_frame_misc_size(struct compilation_unit *cu)
+{
+ return sizeof(unsigned long) + /* *this */
+ (opt_debug_stack ? sizeof(unsigned long) : 0); /* canary */
+}
+#endif
+
static unsigned long __index_to_offset(unsigned long index)
{
return index * sizeof(unsigned long);
@@ -120,6 +134,17 @@ unsigned long cu_frame_locals_offset(struct compilation_unit *cu)
}
/*
+ * Returns offset to subtract from the
+ * stack pointer to reserve space for the entire stack frame.
+ */
+unsigned long cu_frame_total_offset(struct compilation_unit *cu)
+{
+ return cu_frame_locals_offset(cu) +
+ sizeof(unsigned long) * NR_CALLEE_SAVE_REGS +
+ cu_frame_misc_size(cu);
+}
+
+/*
* Checks whether given native function was called from jit trampoline
* code. It checks whether return address points after a relative call
* to jit_magic_trampoline, which is typical for trampolines.
diff --git a/arch/x86/unwind_32.S b/arch/x86/unwind_32.S
index f9056ac2..faf829dd 100644
--- a/arch/x86/unwind_32.S
+++ b/arch/x86/unwind_32.S
@@ -28,7 +28,7 @@ unwind:
*/
push %edx
push %ecx
- call cu_frame_locals_offset
+ call cu_frame_total_offset
pop %ecx
pop %edx
diff --git a/arch/x86/unwind_64.S b/arch/x86/unwind_64.S
index 464c8443..d61754e0 100644
--- a/arch/x86/unwind_64.S
+++ b/arch/x86/unwind_64.S
@@ -26,7 +26,7 @@ unwind:
movq %rax, %rdi
movq 0x08(%rsp), %rsi
- call cu_frame_locals_offset
+ call cu_frame_total_offset
pop %rdi
diff --git a/test/unit/arch-x86/Makefile b/test/unit/arch-x86/Makefile
index 1be7feb5..3e9bd66a 100644
--- a/test/unit/arch-x86/Makefile
+++ b/test/unit/arch-x86/Makefile
@@ -12,6 +12,7 @@ TOPLEVEL_OBJS += lib/buffer.o
TOPLEVEL_OBJS += lib/hash-map.o
TOPLEVEL_OBJS += lib/string.o
TOPLEVEL_OBJS += lib/symbol.o
+TOPLEVEL_OBJS += test/unit/jit/emit-stub.o
TOPLEVEL_OBJS += test/unit/libharness/libharness.o
TOPLEVEL_OBJS += test/unit/vm/stack-trace-stub.o
TOPLEVEL_OBJS += test/unit/vm/trace-stub.o
diff --git a/test/unit/jit/emit-stub.c b/test/unit/jit/emit-stub.c
new file mode 100644
index 00000000..a97cf547
--- /dev/null
+++ b/test/unit/jit/emit-stub.c
@@ -0,0 +1,3 @@
+#include "jit/debug.h"
+
+bool opt_debug_stack;