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

Reply via email to