Impact: this fixes segmentation fault occuring when executing empty
exception handlers compiled with ecj. The ecj compiler generates a
'pop' instruction when exception handler is empty. This causes that
exception object reference is not popped from native stack when
exception handler is executed and that leads to native stack
corruption.

Solution is to always spill the reference to a well known location.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/include/arch/instruction.h |    6 ++++++
 arch/x86/insn-selector_32.brg       |    3 ++-
 include/jit/compilation-unit.h      |    3 +++
 include/jit/exception.h             |    1 +
 jit/compilation-unit.c              |    4 ++++
 jit/compiler.c                      |    5 +++++
 jit/exception.c                     |   22 ++++++++++++++++++++++
 test/include/arch/instruction.h     |    6 ++++++
 8 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/arch/instruction.h 
b/arch/x86/include/arch/instruction.h
index 0a5cd20..6dd0a75 100644
--- a/arch/x86/include/arch/instruction.h
+++ b/arch/x86/include/arch/instruction.h
@@ -167,6 +167,12 @@ reload_insn(struct stack_slot *slot, struct var_info *var)
        return memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, var);
 }
 
+static inline struct insn *
+exception_spill_insn(struct stack_slot *slot)
+{
+       return memlocal_insn(INSN_POP_MEMLOCAL, slot);
+}
+
 struct insn *alloc_insn(enum insn_type);
 void free_insn(struct insn *);
 
diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 3bf0b6d..af95758 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -884,11 +884,12 @@ arg:      EXPR_ARGS_LIST(arg, arg)
 reg:   EXPR_EXCEPTION_REF
 {
        struct var_info *result;
+       struct stack_slot *slot = s->b_parent->exception_spill_slot;
 
        result = get_var(s->b_parent);
        state->reg1 = result;
 
-       select_insn(s, tree, reg_insn(INSN_POP_REG, result));
+       select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot, 
result));
 }
 
 stmt:  STMT_RETURN(reg)
diff --git a/include/jit/compilation-unit.h b/include/jit/compilation-unit.h
index 2c5e0b3..88d87b1 100644
--- a/include/jit/compilation-unit.h
+++ b/include/jit/compilation-unit.h
@@ -34,6 +34,9 @@ struct compilation_unit {
        /* The stack frame contains information of stack slots for stack-based
           arguments, local variables, and spill/reload storage.  */
        struct stack_frame *stack_frame;
+
+       /* It's needed to spill exception object reference at eh entry */
+       struct stack_slot *exception_spill_slot;
 };
 
 struct compilation_unit *alloc_compilation_unit(struct methodblock *);
diff --git a/include/jit/exception.h b/include/jit/exception.h
index dbbc18b..10e88fd 100644
--- a/include/jit/exception.h
+++ b/include/jit/exception.h
@@ -20,5 +20,6 @@ unsigned char *throw_exception_from(struct compilation_unit 
*cu,
                                    struct jit_stack_frame *frame,
                                    unsigned char *native_ptr,
                                    struct object *exception);
+int insert_exception_spill_insns(struct compilation_unit *cu);
 
 #endif
diff --git a/jit/compilation-unit.c b/jit/compilation-unit.c
index 652ea7c..8d60b20 100644
--- a/jit/compilation-unit.c
+++ b/jit/compilation-unit.c
@@ -56,6 +56,10 @@ struct compilation_unit *alloc_compilation_unit(struct 
methodblock *method)
                                                    method->max_locals);
                if (!cu->stack_frame)
                        goto out_of_memory;
+
+               cu->exception_spill_slot = get_spill_slot_32(cu->stack_frame);
+               if (!cu->exception_spill_slot)
+                       goto out_of_memory;
        }
        return cu;
 
diff --git a/jit/compiler.c b/jit/compiler.c
index 4d7a71e..6063b8d 100644
--- a/jit/compiler.c
+++ b/jit/compiler.c
@@ -11,6 +11,7 @@
 #include <jit/compiler.h>
 #include <jit/statement.h>
 #include <jit/bc-offset-mapping.h>
+#include <jit/exception.h>
 
 #include <errno.h>
 #include <stdlib.h>
@@ -50,6 +51,10 @@ int compile(struct compilation_unit *cu)
        if (opt_trace_tree_ir)
                trace_tree_ir(cu);
 
+       err = insert_exception_spill_insns(cu);
+       if (err)
+               goto out;
+
        err = select_instructions(cu);
        if (err)
                goto out;
diff --git a/jit/exception.c b/jit/exception.c
index 2a98dab..2aa9b81 100644
--- a/jit/exception.c
+++ b/jit/exception.c
@@ -27,9 +27,12 @@
 #include <jit/exception.h>
 #include <jit/compilation-unit.h>
 #include <jit/bc-offset-mapping.h>
+#include <jit/basic-block.h>
 #include <vm/buffer.h>
 #include <arch/exception.h>
 #include <arch/stack-frame.h>
+#include <arch/instruction.h>
+#include <errno.h>
 
 struct exception_table_entry *exception_find_entry(struct methodblock *method,
                                                   unsigned long target)
@@ -139,3 +142,22 @@ unsigned char *throw_exception_from(struct 
compilation_unit *cu,
 
        return bb_native_ptr(cu->unwind_bb);
 }
+
+int insert_exception_spill_insns(struct compilation_unit *cu)
+{
+       struct insn *insn;
+       struct basic_block *bb;
+
+       for_each_basic_block(bb, &cu->bb_list) {
+               if (bb->is_eh) {
+                       insn = exception_spill_insn(cu->exception_spill_slot);
+                       if (insn == NULL)
+                               return -ENOMEM;
+
+                       insn->bytecode_offset = bb->start;
+                       bb_add_insn(bb, insn);
+               }
+       }
+
+       return 0;
+}
diff --git a/test/include/arch/instruction.h b/test/include/arch/instruction.h
index 2821986..3aa81ba 100644
--- a/test/include/arch/instruction.h
+++ b/test/include/arch/instruction.h
@@ -87,6 +87,12 @@ reload_insn(struct stack_slot *slot, struct var_info *var)
        return ld_insn(INSN_LD_LOCAL, slot, var);
 }
 
+static inline struct insn *
+exception_spill_insn(struct stack_slot *slot)
+{
+       return NULL;
+}
+
 struct insn *alloc_insn(enum insn_type);
 void free_insn(struct insn *);
 
-- 
1.6.0.6


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables 
unlimited royalty-free distribution of the report engine 
for externally facing server and web deployment. 
http://p.sf.net/sfu/businessobjects
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to