1 /* src/vm/jit/i386/patcher.c - i386 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "vm/jit/i386/codegen.h"
36 #include "mm/memory.h"
38 #include "native/native.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
44 #include "vm/jit/patcher.h"
45 #include "vm/jit/stacktrace.h"
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vm/resolve.h"
51 #include "vmcore/references.h"
54 /* patcher_wrapper *************************************************************
56 Wrapper for all patchers. It also creates the stackframe info
59 If the return value of the patcher function is false, it gets the
60 exception object, clears the exception pointer and returns the
63 *******************************************************************************/
65 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
74 /* define the patcher function */
76 bool (*patcher_function)(u1 *);
78 /* get stuff from the stack */
80 xpc = (u1 *) *((ptrint *) (sp + 6 * 4));
81 o = (java_object_t *) *((ptrint *) (sp + 4 * 4));
82 f = (functionptr) *((ptrint *) (sp + 0 * 4));
84 /* calculate and set the new return address */
86 xpc = xpc - PATCHER_CALL_SIZE;
88 *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
90 /* cast the passed function to a patcher function */
92 patcher_function = (bool (*)(u1 *)) (ptrint) f;
94 /* enter a monitor on the patching position */
98 /* create the stackframeinfo */
100 /* RA is passed as NULL, but the XPC is correct and can be used in
101 stacktrace_create_extern_stackframeinfo for
102 md_codegen_get_pv_from_pc. */
104 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
106 /* call the proper patcher function */
108 result = (patcher_function)(sp);
110 /* remove the stackframeinfo */
112 stacktrace_remove_stackframeinfo(&sfi);
114 /* check for return value and exit accordingly */
116 if (result == false) {
117 e = exceptions_get_and_clear_exception();
124 PATCHER_MARK_PATCHED_MONITOREXIT;
130 /* patcher_get_putstatic *******************************************************
134 <patched call position>
135 b8 00 00 00 00 mov $0x00000000,%eax
137 *******************************************************************************/
139 bool patcher_get_putstatic(u1 *sp)
143 unresolved_field *uf;
146 /* get stuff from the stack */
148 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
149 mcode = *((u8 *) (sp + 2 * 4));
150 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
152 /* get the fieldinfo */
154 if (!(fi = resolve_field_eager(uf)))
157 /* check if the field's class is initialized */
159 if (!(fi->class->state & CLASS_INITIALIZED))
160 if (!initialize_class(fi->class))
163 /* patch back original code */
165 *((u4 *) (ra + 0)) = (u4) mcode;
166 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
168 /* if we show disassembly, we have to skip the nop's */
173 /* patch the field value's address */
175 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
181 /* patcher_getfield ************************************************************
185 <patched call position>
186 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
188 *******************************************************************************/
190 bool patcher_getfield(u1 *sp)
194 unresolved_field *uf;
197 /* get stuff from the stack */
199 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
200 mcode = *((u8 *) (sp + 2 * 4));
201 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
203 /* get the fieldinfo */
205 if (!(fi = resolve_field_eager(uf)))
208 /* patch back original code */
210 *((u4 *) (ra + 0)) = (u4) mcode;
211 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
213 /* if we show disassembly, we have to skip the nop's */
218 /* patch the field's offset */
220 *((u4 *) (ra + 2)) = (u4) (fi->offset);
222 /* if the field has type long, we need to patch the second move too */
224 if (fi->type == TYPE_LNG)
225 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
231 /* patcher_putfield ************************************************************
235 <patched call position>
236 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
238 *******************************************************************************/
240 bool patcher_putfield(u1 *sp)
244 unresolved_field *uf;
247 /* get stuff from the stack */
249 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
250 mcode = *((u8 *) (sp + 2 * 4));
251 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
253 /* get the fieldinfo */
255 if (!(fi = resolve_field_eager(uf)))
258 /* patch back original code */
260 *((u4 *) (ra + 0)) = (u4) mcode;
261 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
263 /* if we show disassembly, we have to skip the nop's */
268 /* patch the field's offset */
270 if (fi->type != TYPE_LNG) {
271 *((u4 *) (ra + 2)) = (u4) (fi->offset);
274 /* The long code is special:
276 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
277 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
280 *((u4 *) (ra + 2)) = (u4) (fi->offset);
281 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
288 /* patcher_putfieldconst *******************************************************
292 <patched call position>
293 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
295 *******************************************************************************/
297 bool patcher_putfieldconst(u1 *sp)
301 unresolved_field *uf;
304 /* get stuff from the stack */
306 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
307 mcode = *((u8 *) (sp + 2 * 4));
308 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
310 /* get the fieldinfo */
312 if (!(fi = resolve_field_eager(uf)))
315 /* patch back original code */
317 *((u4 *) (ra + 0)) = (u4) mcode;
318 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
320 /* if we show disassembly, we have to skip the nop's */
325 /* patch the field's offset */
327 if (!IS_2_WORD_TYPE(fi->type)) {
328 *((u4 *) (ra + 2)) = (u4) (fi->offset);
331 /* long/double code is different:
333 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
334 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
337 *((u4 *) (ra + 2)) = (u4) (fi->offset);
338 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
345 /* patcher_aconst **************************************************************
349 <patched call postition>
350 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
351 b8 00 00 00 00 mov $0x0000000,%eax
353 *******************************************************************************/
355 bool patcher_aconst(u1 *sp)
359 constant_classref *cr;
362 /* get stuff from the stack */
364 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
365 mcode = *((u8 *) (sp + 2 * 4));
366 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
368 /* get the classinfo */
370 if (!(c = resolve_classref_eager(cr)))
373 /* patch back original code */
375 *((u4 *) (ra + 0)) = (u4) mcode;
376 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
378 /* if we show disassembly, we have to skip the nop's */
383 /* patch the classinfo pointer */
385 *((ptrint *) (ra + 1)) = (ptrint) c;
391 /* patcher_builtin_multianewarray **********************************************
395 <patched call position>
396 c7 04 24 02 00 00 00 movl $0x2,(%esp)
397 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
399 83 c0 0c add $0xc,%eax
400 89 44 24 08 mov %eax,0x8(%esp)
401 b8 00 00 00 00 mov $0x00000000,%eax
404 *******************************************************************************/
406 bool patcher_builtin_multianewarray(u1 *sp)
410 constant_classref *cr;
413 /* get stuff from the stack */
415 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
416 mcode = *((u8 *) (sp + 2 * 4));
417 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
419 /* get the classinfo */
421 if (!(c = resolve_classref_eager(cr)))
424 /* patch back original code */
426 *((u4 *) (ra + 0)) = (u4) mcode;
427 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
429 /* if we show disassembly, we have to skip the nop's */
434 /* patch the classinfo pointer */
436 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
442 /* patcher_builtin_arraycheckcast **********************************************
446 <patched call position>
447 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
448 ba 00 00 00 00 mov $0x00000000,%edx
451 *******************************************************************************/
453 bool patcher_builtin_arraycheckcast(u1 *sp)
457 constant_classref *cr;
460 /* get stuff from the stack */
462 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
463 mcode = *((u8 *) (sp + 2 * 4));
464 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
466 /* get the classinfo */
468 if (!(c = resolve_classref_eager(cr)))
471 /* patch back original code */
473 *((u4 *) (ra + 0)) = (u4) mcode;
474 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
476 /* if we show disassembly, we have to skip the nop's */
481 /* patch the classinfo pointer */
483 *((ptrint *) (ra + 4)) = (ptrint) c;
485 /* patch new function address */
487 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
493 /* patcher_invokestatic_special ************************************************
497 <patched call position>
498 b9 00 00 00 00 mov $0x00000000,%ecx
501 *******************************************************************************/
503 bool patcher_invokestatic_special(u1 *sp)
507 unresolved_method *um;
510 /* get stuff from the stack */
512 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
513 mcode = *((u8 *) (sp + 2 * 4));
514 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
516 /* get the fieldinfo */
518 if (!(m = resolve_method_eager(um)))
521 /* patch back original code */
523 *((u4 *) (ra + 0)) = (u4) mcode;
524 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
526 /* if we show disassembly, we have to skip the nop's */
531 /* patch stubroutine */
533 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
539 /* patcher_invokevirtual *******************************************************
543 <patched call position>
544 8b 08 mov (%eax),%ecx
545 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
548 *******************************************************************************/
550 bool patcher_invokevirtual(u1 *sp)
554 unresolved_method *um;
557 /* get stuff from the stack */
559 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
560 mcode = *((u8 *) (sp + 2 * 4));
561 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
563 /* get the fieldinfo */
565 if (!(m = resolve_method_eager(um)))
568 /* patch back original code */
570 *((u4 *) (ra + 0)) = (u4) mcode;
571 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
573 /* if we show disassembly, we have to skip the nop's */
578 /* patch vftbl index */
580 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
581 sizeof(methodptr) * m->vftblindex);
587 /* patcher_invokeinterface *****************************************************
591 <patched call position>
592 8b 00 mov (%eax),%eax
593 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
594 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
597 *******************************************************************************/
599 bool patcher_invokeinterface(u1 *sp)
603 unresolved_method *um;
606 /* get stuff from the stack */
608 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
609 mcode = *((u8 *) (sp + 2 * 4));
610 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
612 /* get the fieldinfo */
614 if (!(m = resolve_method_eager(um)))
617 /* patch back original code */
619 *((u4 *) (ra + 0)) = (u4) mcode;
620 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
622 /* if we show disassembly, we have to skip the nop's */
627 /* patch interfacetable index */
629 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
630 sizeof(methodptr) * m->class->index);
632 /* patch method offset */
634 *((s4 *) (ra + 2 + 6 + 2)) =
635 (s4) (sizeof(methodptr) * (m - m->class->methods));
641 /* patcher_checkcast_instanceof_flags ******************************************
645 <patched call position>
646 b9 00 00 00 00 mov $0x00000000,%ecx
648 *******************************************************************************/
650 bool patcher_checkcast_instanceof_flags(u1 *sp)
654 constant_classref *cr;
657 /* get stuff from the stack */
659 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
660 mcode = *((u8 *) (sp + 2 * 4));
661 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
663 /* get the fieldinfo */
665 if (!(c = resolve_classref_eager(cr)))
668 /* patch back original code */
670 *((u4 *) (ra + 0)) = (u4) mcode;
671 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
673 /* if we show disassembly, we have to skip the nop's */
678 /* patch class flags */
680 *((s4 *) (ra + 1)) = (s4) c->flags;
686 /* patcher_checkcast_interface *************************************************
690 <patched call position>
691 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
692 81 ea 00 00 00 00 sub $0x00000000,%edx
694 0f 8f 06 00 00 00 jg 0x00000000
695 8b 35 03 00 00 00 mov 0x3,%esi
696 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
698 *******************************************************************************/
700 bool patcher_checkcast_interface(u1 *sp)
704 constant_classref *cr;
707 /* get stuff from the stack */
709 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
710 mcode = *((u8 *) (sp + 2 * 4));
711 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
713 /* get the fieldinfo */
715 if (!(c = resolve_classref_eager(cr)))
718 /* patch back original code */
720 *((u4 *) (ra + 0)) = (u4) mcode;
721 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
723 /* if we show disassembly, we have to skip the nop's */
728 /* patch super class index */
730 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
732 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
733 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
734 c->index * sizeof(methodptr*));
740 /* patcher_instanceof_interface ************************************************
744 <patched call position>
745 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
746 81 ea 00 00 00 00 sub $0x00000000,%edx
748 0f 8e 13 00 00 00 jle 0x00000000
749 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
751 *******************************************************************************/
753 bool patcher_instanceof_interface(u1 *sp)
757 constant_classref *cr;
760 /* get stuff from the stack */
762 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
763 mcode = *((u8 *) (sp + 2 * 4));
764 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
766 /* get the fieldinfo */
768 if (!(c = resolve_classref_eager(cr)))
771 /* patch back original code */
773 *((u4 *) (ra + 0)) = (u4) mcode;
774 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
776 /* if we show disassembly, we have to skip the nop's */
781 /* patch super class index */
783 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
785 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
786 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
787 c->index * sizeof(methodptr*));
793 /* patcher_checkcast_class *****************************************************
797 <patched call position>
798 ba 00 00 00 00 mov $0x00000000,%edx
799 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
800 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
802 ba 00 00 00 00 mov $0x00000000,%edx
804 *******************************************************************************/
806 bool patcher_checkcast_class(u1 *sp)
810 constant_classref *cr;
813 /* get stuff from the stack */
815 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
816 mcode = *((u8 *) (sp + 2 * 4));
817 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
819 /* get the fieldinfo */
821 if (!(c = resolve_classref_eager(cr)))
824 /* patch back original code */
826 *((u4 *) (ra + 0)) = (u4) mcode;
827 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
829 /* if we show disassembly, we have to skip the nop's */
834 /* patch super class' vftbl */
836 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
837 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
843 /* patcher_instanceof_class ****************************************************
847 <patched call position>
848 b9 00 00 00 00 mov $0x0,%ecx
849 8b 40 14 mov 0x14(%eax),%eax
850 8b 51 18 mov 0x18(%ecx),%edx
851 8b 49 14 mov 0x14(%ecx),%ecx
853 *******************************************************************************/
855 bool patcher_instanceof_class(u1 *sp)
859 constant_classref *cr;
862 /* get stuff from the stack */
864 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
865 mcode = *((u8 *) (sp + 2 * 4));
866 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
868 /* get the fieldinfo */
870 if (!(c = resolve_classref_eager(cr)))
873 /* patch back original code */
875 *((u4 *) (ra + 0)) = (u4) mcode;
876 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
878 /* if we show disassembly, we have to skip the nop's */
883 /* patch super class' vftbl */
885 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
891 /* patcher_clinit **************************************************************
893 Is used int PUT/GETSTATIC and native stub.
897 <patched call position>
899 *******************************************************************************/
901 bool patcher_clinit(u1 *sp)
907 /* get stuff from the stack */
909 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
910 mcode = *((u8 *) (sp + 2 * 4));
911 c = (classinfo *) *((ptrint *) (sp + 1 * 4));
913 /* check if the class is initialized */
915 if (!(c->state & CLASS_INITIALIZED))
916 if (!initialize_class(c))
919 /* patch back original code */
921 *((u4 *) (ra + 0)) = (u4) mcode;
922 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
928 /* patcher_athrow_areturn ******************************************************
932 <patched call position>
934 *******************************************************************************/
936 #ifdef ENABLE_VERIFIER
937 bool patcher_athrow_areturn(u1 *sp)
941 unresolved_class *uc;
943 /* get stuff from the stack */
945 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
946 mcode = *((u8 *) (sp + 2 * 4));
947 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
949 /* resolve the class and check subtype constraints */
951 if (!resolve_class_eager_no_access_check(uc))
954 /* patch back original code */
956 *((u4 *) (ra + 0)) = (u4) mcode;
957 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
961 #endif /* ENABLE_VERIFIER */
964 /* patcher_resolve_native ******************************************************
966 Is used in native stub.
970 <patched call position>
971 c7 44 24 04 28 90 01 40 movl $0x40019028,0x4(%esp)
973 *******************************************************************************/
975 #if !defined(WITH_STATIC_CLASSPATH)
976 bool patcher_resolve_native(u1 *sp)
983 /* get stuff from the stack */
985 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
986 mcode = *((u8 *) (sp + 2 * 4));
987 m = (methodinfo *) *((ptrint *) (sp + 1 * 4));
989 /* resolve native function */
991 if (!(f = native_resolve_function(m)))
994 /* patch back original code */
996 *((u4 *) (ra + 0)) = (u4) mcode;
997 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
999 /* if we show disassembly, we have to skip the nop's */
1004 /* patch native function pointer */
1006 *((ptrint *) (ra + 4)) = (ptrint) f;
1010 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1014 * These are local overrides for various environment variables in Emacs.
1015 * Please do not remove this and leave it at the end of the file, where
1016 * Emacs will automagically detect them.
1017 * ---------------------------------------------------------------------
1020 * indent-tabs-mode: t
1024 * vim:noexpandtab:sw=4:ts=4: