We cannot overwrite a register which is not saved (ESI) because this will lead to a corruption in JIT code. The proper solution is to copy the call arguments.
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/emit-code.c | 37 +++++++++++++++++++++++++++++++------ include/jit/compiler.h | 3 ++- include/jit/emit-code.h | 3 ++- jit/trampoline.c | 7 ++++--- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c index 236ba0e..c4ba179 100644 --- a/arch/x86/emit-code.c +++ b/arch/x86/emit-code.c @@ -1389,21 +1389,46 @@ void emit_trampoline(struct compilation_unit *cu, } void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env *jni_env, - void *target) + void *target, struct vm_method *method) { + unsigned long args_size; + jit_text_lock(); buf->buf = jit_text_ptr(); - /* save return address into caller-saved register */ - __emit_pop_reg(buf, REG_ESI); + __emit_push_reg(buf, REG_ESI); + __emit_push_reg(buf, REG_EDI); + __emit_push_reg(buf, REG_ECX); + + /* + * Make a copy of call arguments + */ + __emit_mov_reg_reg(buf, REG_ESP, REG_ESI); + __emit_add_imm_reg(buf, (3 + 1) * sizeof(unsigned long), REG_ESI); + + args_size = sizeof(unsigned long) + (method->args_count + 1); + + __emit_add_imm_reg(buf, -args_size, REG_ESP); + __emit_mov_reg_reg(buf, REG_ESP, REG_EDI); + + __emit_mov_imm_reg(buf, method->args_count + 1, REG_ECX); + + /* CLD */ + emit(buf, 0xfc); + + /* REP MOVSD */ + emit(buf, 0xf3); + emit(buf, 0xa5); __emit_push_imm(buf, (unsigned long) jni_env); __emit_call(buf, target); - __emit_add_imm_reg(buf, 4, REG_ESP); + __emit_add_imm_reg(buf, args_size + sizeof(unsigned long), REG_ESP); + + __emit_pop_reg(buf, REG_ECX); + __emit_pop_reg(buf, REG_EDI); + __emit_pop_reg(buf, REG_ESI); - /* return to caller*/ - __emit_push_reg(buf, REG_ESI); emit_ret(buf); jit_text_reserve(buffer_offset(buf)); diff --git a/include/jit/compiler.h b/include/jit/compiler.h index 8584954..e2609ef 100644 --- a/include/jit/compiler.h +++ b/include/jit/compiler.h @@ -14,6 +14,7 @@ struct compilation_unit; struct expression; struct statement; struct buffer; +struct vm_method; struct fixup_site { /* Compilation unit to which relcall_insn belongs */ @@ -62,7 +63,7 @@ void *jit_magic_trampoline(struct compilation_unit *); struct jit_trampoline *alloc_jit_trampoline(void); struct jni_trampoline *alloc_jni_trampoline(void); struct jit_trampoline *build_jit_trampoline(struct compilation_unit *); -struct jni_trampoline *build_jni_trampoline(void *); +struct jni_trampoline *build_jni_trampoline(struct vm_method *, void *); void free_jit_trampoline(struct jit_trampoline *); void free_jni_trampoline(struct jni_trampoline *); diff --git a/include/jit/emit-code.h b/include/jit/emit-code.h index 07c41bf..291955f 100644 --- a/include/jit/emit-code.h +++ b/include/jit/emit-code.h @@ -8,6 +8,7 @@ struct buffer; struct insn; struct vm_object; struct vm_jni_env; +struct vm_method; enum emitter_type { NO_OPERANDS = 1, @@ -39,6 +40,6 @@ extern void emit_body(struct basic_block *, struct buffer *); extern void backpatch_branch_target(struct buffer *buf, struct insn *insn, unsigned long target_offset); extern void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env *jni_env, - void *target); + void *target, struct vm_method *method); #endif /* JATO_EMIT_CODE_H */ diff --git a/jit/trampoline.c b/jit/trampoline.c index 0de2db5..42f3afa 100644 --- a/jit/trampoline.c +++ b/jit/trampoline.c @@ -65,7 +65,8 @@ static void *jit_native_trampoline(struct compilation_unit *cu) add_cu_mapping((unsigned long)ret, cu); if (!method->jni_trampoline) - method->jni_trampoline = build_jni_trampoline(ret); + method->jni_trampoline = + build_jni_trampoline(method, ret); return buffer_ptr(method->jni_trampoline->objcode); } @@ -151,13 +152,13 @@ struct jit_trampoline *build_jit_trampoline(struct compilation_unit *cu) return trampoline; } -struct jni_trampoline *build_jni_trampoline(void *target) +struct jni_trampoline *build_jni_trampoline(struct vm_method *vmm, void *target) { struct jni_trampoline *trampoline; trampoline = alloc_jni_trampoline(); if (trampoline) emit_jni_trampoline(trampoline->objcode, vm_jni_get_jni_env(), - target); + target, vmm); return trampoline; } -- 1.6.0.6 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel