diff options
author | Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> | 2012-02-08 18:49:49 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-02-08 22:24:46 +0200 |
commit | 8c6cee29f742f068d8acb3a981bf5d67bb7f5dea (patch) | |
tree | b90cd9084bb47665ebc7dae6dd08615bb7e71e13 | |
parent | fef481ea7313e286813f9435324350dd0625ace8 (diff) | |
download | jato-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.h | 1 | ||||
-rw-r--r-- | arch/x86/stack-frame.c | 25 | ||||
-rw-r--r-- | arch/x86/unwind_32.S | 2 | ||||
-rw-r--r-- | arch/x86/unwind_64.S | 2 | ||||
-rw-r--r-- | test/unit/arch-x86/Makefile | 1 | ||||
-rw-r--r-- | test/unit/jit/emit-stub.c | 3 |
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; |