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
