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
25 $Id: patcher.c 8295 2007-08-11 17:57:24Z michi $
36 #include "vm/jit/i386/codegen.h"
38 #include "mm/memory.h"
40 #include "native/native.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
46 #include "vm/jit/patcher.h"
47 #include "vm/jit/stacktrace.h"
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vm/resolve.h"
53 #include "vmcore/references.h"
56 /* patcher_wrapper *************************************************************
58 Wrapper for all patchers. It also creates the stackframe info
61 If the return value of the patcher function is false, it gets the
62 exception object, clears the exception pointer and returns the
65 *******************************************************************************/
67 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
76 /* define the patcher function */
78 bool (*patcher_function)(u1 *);
80 /* get stuff from the stack */
82 xpc = (u1 *) *((ptrint *) (sp + 6 * 4));
83 o = (java_object_t *) *((ptrint *) (sp + 4 * 4));
84 f = (functionptr) *((ptrint *) (sp + 0 * 4));
86 /* calculate and set the new return address */
88 xpc = xpc - PATCHER_CALL_SIZE;
90 *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
92 /* cast the passed function to a patcher function */
94 patcher_function = (bool (*)(u1 *)) (ptrint) f;
96 /* enter a monitor on the patching position */
100 /* create the stackframeinfo */
102 /* RA is passed as NULL, but the XPC is correct and can be used in
103 stacktrace_create_extern_stackframeinfo for
104 md_codegen_get_pv_from_pc. */
106 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
108 /* call the proper patcher function */
110 result = (patcher_function)(sp);
112 /* remove the stackframeinfo */
114 stacktrace_remove_stackframeinfo(&sfi);
116 /* check for return value and exit accordingly */
118 if (result == false) {
119 e = exceptions_get_and_clear_exception();
126 PATCHER_MARK_PATCHED_MONITOREXIT;
132 /* patcher_get_putstatic *******************************************************
136 <patched call position>
137 b8 00 00 00 00 mov $0x00000000,%eax
139 *******************************************************************************/
141 bool patcher_get_putstatic(u1 *sp)
145 unresolved_field *uf;
148 /* get stuff from the stack */
150 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
151 mcode = *((u8 *) (sp + 2 * 4));
152 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
154 /* get the fieldinfo */
156 if (!(fi = resolve_field_eager(uf)))
159 /* check if the field's class is initialized */
161 if (!(fi->class->state & CLASS_INITIALIZED))
162 if (!initialize_class(fi->class))
165 /* patch back original code */
167 *((u4 *) (ra + 0)) = (u4) mcode;
168 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
170 /* if we show disassembly, we have to skip the nop's */
175 /* patch the field value's address */
177 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
183 /* patcher_getfield ************************************************************
187 <patched call position>
188 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
190 *******************************************************************************/
192 bool patcher_getfield(u1 *sp)
196 unresolved_field *uf;
199 /* get stuff from the stack */
201 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
202 mcode = *((u8 *) (sp + 2 * 4));
203 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
205 /* get the fieldinfo */
207 if (!(fi = resolve_field_eager(uf)))
210 /* patch back original code */
212 *((u4 *) (ra + 0)) = (u4) mcode;
213 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
215 /* if we show disassembly, we have to skip the nop's */
220 /* patch the field's offset */
222 *((u4 *) (ra + 2)) = (u4) (fi->offset);
224 /* if the field has type long, we need to patch the second move too */
226 if (fi->type == TYPE_LNG)
227 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
233 /* patcher_putfield ************************************************************
237 <patched call position>
238 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
240 *******************************************************************************/
242 bool patcher_putfield(u1 *sp)
246 unresolved_field *uf;
249 /* get stuff from the stack */
251 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
252 mcode = *((u8 *) (sp + 2 * 4));
253 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
255 /* get the fieldinfo */
257 if (!(fi = resolve_field_eager(uf)))
260 /* patch back original code */
262 *((u4 *) (ra + 0)) = (u4) mcode;
263 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
265 /* if we show disassembly, we have to skip the nop's */
270 /* patch the field's offset */
272 if (fi->type != TYPE_LNG) {
273 *((u4 *) (ra + 2)) = (u4) (fi->offset);
276 /* The long code is special:
278 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
279 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
282 *((u4 *) (ra + 2)) = (u4) (fi->offset);
283 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
290 /* patcher_putfieldconst *******************************************************
294 <patched call position>
295 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
297 *******************************************************************************/
299 bool patcher_putfieldconst(u1 *sp)
303 unresolved_field *uf;
306 /* get stuff from the stack */
308 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
309 mcode = *((u8 *) (sp + 2 * 4));
310 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
312 /* get the fieldinfo */
314 if (!(fi = resolve_field_eager(uf)))
317 /* patch back original code */
319 *((u4 *) (ra + 0)) = (u4) mcode;
320 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
322 /* if we show disassembly, we have to skip the nop's */
327 /* patch the field's offset */
329 if (!IS_2_WORD_TYPE(fi->type)) {
330 *((u4 *) (ra + 2)) = (u4) (fi->offset);
333 /* long/double code is different:
335 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
336 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
339 *((u4 *) (ra + 2)) = (u4) (fi->offset);
340 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
347 /* patcher_aconst **************************************************************
351 <patched call postition>
352 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
353 b8 00 00 00 00 mov $0x0000000,%eax
355 *******************************************************************************/
357 bool patcher_aconst(u1 *sp)
361 constant_classref *cr;
364 /* get stuff from the stack */
366 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
367 mcode = *((u8 *) (sp + 2 * 4));
368 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
370 /* get the classinfo */
372 if (!(c = resolve_classref_eager(cr)))
375 /* patch back original code */
377 *((u4 *) (ra + 0)) = (u4) mcode;
378 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
380 /* if we show disassembly, we have to skip the nop's */
385 /* patch the classinfo pointer */
387 *((ptrint *) (ra + 1)) = (ptrint) c;
393 /* patcher_builtin_multianewarray **********************************************
397 <patched call position>
398 c7 04 24 02 00 00 00 movl $0x2,(%esp)
399 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
401 83 c0 0c add $0xc,%eax
402 89 44 24 08 mov %eax,0x8(%esp)
403 b8 00 00 00 00 mov $0x00000000,%eax
406 *******************************************************************************/
408 bool patcher_builtin_multianewarray(u1 *sp)
412 constant_classref *cr;
415 /* get stuff from the stack */
417 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
418 mcode = *((u8 *) (sp + 2 * 4));
419 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
421 /* get the classinfo */
423 if (!(c = resolve_classref_eager(cr)))
426 /* patch back original code */
428 *((u4 *) (ra + 0)) = (u4) mcode;
429 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
431 /* if we show disassembly, we have to skip the nop's */
436 /* patch the classinfo pointer */
438 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
444 /* patcher_builtin_arraycheckcast **********************************************
448 <patched call position>
449 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
450 ba 00 00 00 00 mov $0x00000000,%edx
453 *******************************************************************************/
455 bool patcher_builtin_arraycheckcast(u1 *sp)
459 constant_classref *cr;
462 /* get stuff from the stack */
464 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
465 mcode = *((u8 *) (sp + 2 * 4));
466 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
468 /* get the classinfo */
470 if (!(c = resolve_classref_eager(cr)))
473 /* patch back original code */
475 *((u4 *) (ra + 0)) = (u4) mcode;
476 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
478 /* if we show disassembly, we have to skip the nop's */
483 /* patch the classinfo pointer */
485 *((ptrint *) (ra + 4)) = (ptrint) c;
487 /* patch new function address */
489 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
495 /* patcher_invokestatic_special ************************************************
499 <patched call position>
500 b9 00 00 00 00 mov $0x00000000,%ecx
503 *******************************************************************************/
505 bool patcher_invokestatic_special(u1 *sp)
509 unresolved_method *um;
512 /* get stuff from the stack */
514 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
515 mcode = *((u8 *) (sp + 2 * 4));
516 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
518 /* get the fieldinfo */
520 if (!(m = resolve_method_eager(um)))
523 /* patch back original code */
525 *((u4 *) (ra + 0)) = (u4) mcode;
526 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
528 /* if we show disassembly, we have to skip the nop's */
533 /* patch stubroutine */
535 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
541 /* patcher_invokevirtual *******************************************************
545 <patched call position>
546 8b 08 mov (%eax),%ecx
547 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
550 *******************************************************************************/
552 bool patcher_invokevirtual(u1 *sp)
556 unresolved_method *um;
559 /* get stuff from the stack */
561 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
562 mcode = *((u8 *) (sp + 2 * 4));
563 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
565 /* get the fieldinfo */
567 if (!(m = resolve_method_eager(um)))
570 /* patch back original code */
572 *((u4 *) (ra + 0)) = (u4) mcode;
573 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
575 /* if we show disassembly, we have to skip the nop's */
580 /* patch vftbl index */
582 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
583 sizeof(methodptr) * m->vftblindex);
589 /* patcher_invokeinterface *****************************************************
593 <patched call position>
594 8b 00 mov (%eax),%eax
595 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
596 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
599 *******************************************************************************/
601 bool patcher_invokeinterface(u1 *sp)
605 unresolved_method *um;
608 /* get stuff from the stack */
610 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
611 mcode = *((u8 *) (sp + 2 * 4));
612 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
614 /* get the fieldinfo */
616 if (!(m = resolve_method_eager(um)))
619 /* patch back original code */
621 *((u4 *) (ra + 0)) = (u4) mcode;
622 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
624 /* if we show disassembly, we have to skip the nop's */
629 /* patch interfacetable index */
631 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
632 sizeof(methodptr) * m->class->index);
634 /* patch method offset */
636 *((s4 *) (ra + 2 + 6 + 2)) =
637 (s4) (sizeof(methodptr) * (m - m->class->methods));
643 /* patcher_checkcast_instanceof_flags ******************************************
647 <patched call position>
648 b9 00 00 00 00 mov $0x00000000,%ecx
650 *******************************************************************************/
652 bool patcher_checkcast_instanceof_flags(u1 *sp)
656 constant_classref *cr;
659 /* get stuff from the stack */
661 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
662 mcode = *((u8 *) (sp + 2 * 4));
663 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
665 /* get the fieldinfo */
667 if (!(c = resolve_classref_eager(cr)))
670 /* patch back original code */
672 *((u4 *) (ra + 0)) = (u4) mcode;
673 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
675 /* if we show disassembly, we have to skip the nop's */
680 /* patch class flags */
682 *((s4 *) (ra + 1)) = (s4) c->flags;
688 /* patcher_checkcast_interface *************************************************
692 <patched call position>
693 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
694 81 ea 00 00 00 00 sub $0x00000000,%edx
696 0f 8f 06 00 00 00 jg 0x00000000
697 8b 35 03 00 00 00 mov 0x3,%esi
698 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
700 *******************************************************************************/
702 bool patcher_checkcast_interface(u1 *sp)
706 constant_classref *cr;
709 /* get stuff from the stack */
711 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
712 mcode = *((u8 *) (sp + 2 * 4));
713 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
715 /* get the fieldinfo */
717 if (!(c = resolve_classref_eager(cr)))
720 /* patch back original code */
722 *((u4 *) (ra + 0)) = (u4) mcode;
723 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
725 /* if we show disassembly, we have to skip the nop's */
730 /* patch super class index */
732 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
734 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
735 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
736 c->index * sizeof(methodptr*));
742 /* patcher_instanceof_interface ************************************************
746 <patched call position>
747 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
748 81 ea 00 00 00 00 sub $0x00000000,%edx
750 0f 8e 13 00 00 00 jle 0x00000000
751 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
753 *******************************************************************************/
755 bool patcher_instanceof_interface(u1 *sp)
759 constant_classref *cr;
762 /* get stuff from the stack */
764 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
765 mcode = *((u8 *) (sp + 2 * 4));
766 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
768 /* get the fieldinfo */
770 if (!(c = resolve_classref_eager(cr)))
773 /* patch back original code */
775 *((u4 *) (ra + 0)) = (u4) mcode;
776 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
778 /* if we show disassembly, we have to skip the nop's */
783 /* patch super class index */
785 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
787 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
788 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
789 c->index * sizeof(methodptr*));
795 /* patcher_checkcast_class *****************************************************
799 <patched call position>
800 ba 00 00 00 00 mov $0x00000000,%edx
801 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
802 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
804 ba 00 00 00 00 mov $0x00000000,%edx
806 *******************************************************************************/
808 bool patcher_checkcast_class(u1 *sp)
812 constant_classref *cr;
815 /* get stuff from the stack */
817 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
818 mcode = *((u8 *) (sp + 2 * 4));
819 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
821 /* get the fieldinfo */
823 if (!(c = resolve_classref_eager(cr)))
826 /* patch back original code */
828 *((u4 *) (ra + 0)) = (u4) mcode;
829 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
831 /* if we show disassembly, we have to skip the nop's */
836 /* patch super class' vftbl */
838 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
839 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
845 /* patcher_instanceof_class ****************************************************
849 <patched call position>
850 b9 00 00 00 00 mov $0x0,%ecx
851 8b 40 14 mov 0x14(%eax),%eax
852 8b 51 18 mov 0x18(%ecx),%edx
853 8b 49 14 mov 0x14(%ecx),%ecx
855 *******************************************************************************/
857 bool patcher_instanceof_class(u1 *sp)
861 constant_classref *cr;
864 /* get stuff from the stack */
866 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
867 mcode = *((u8 *) (sp + 2 * 4));
868 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
870 /* get the fieldinfo */
872 if (!(c = resolve_classref_eager(cr)))
875 /* patch back original code */
877 *((u4 *) (ra + 0)) = (u4) mcode;
878 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
880 /* if we show disassembly, we have to skip the nop's */
885 /* patch super class' vftbl */
887 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
893 /* patcher_clinit **************************************************************
895 Is used int PUT/GETSTATIC and native stub.
899 <patched call position>
901 *******************************************************************************/
903 bool patcher_clinit(u1 *sp)
909 /* get stuff from the stack */
911 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
912 mcode = *((u8 *) (sp + 2 * 4));
913 c = (classinfo *) *((ptrint *) (sp + 1 * 4));
915 /* check if the class is initialized */
917 if (!(c->state & CLASS_INITIALIZED))
918 if (!initialize_class(c))
921 /* patch back original code */
923 *((u4 *) (ra + 0)) = (u4) mcode;
924 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
930 /* patcher_athrow_areturn ******************************************************
934 <patched call position>
936 *******************************************************************************/
938 #ifdef ENABLE_VERIFIER
939 bool patcher_athrow_areturn(u1 *sp)
943 unresolved_class *uc;
945 /* get stuff from the stack */
947 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
948 mcode = *((u8 *) (sp + 2 * 4));
949 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
951 /* resolve the class and check subtype constraints */
953 if (!resolve_class_eager_no_access_check(uc))
956 /* patch back original code */
958 *((u4 *) (ra + 0)) = (u4) mcode;
959 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
963 #endif /* ENABLE_VERIFIER */
966 /* patcher_resolve_native ******************************************************
968 Is used in native stub.
972 <patched call position>
973 c7 44 24 04 28 90 01 40 movl $0x40019028,0x4(%esp)
975 *******************************************************************************/
977 #if !defined(WITH_STATIC_CLASSPATH)
978 bool patcher_resolve_native(u1 *sp)
985 /* get stuff from the stack */
987 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
988 mcode = *((u8 *) (sp + 2 * 4));
989 m = (methodinfo *) *((ptrint *) (sp + 1 * 4));
991 /* resolve native function */
993 if (!(f = native_resolve_function(m)))
996 /* patch back original code */
998 *((u4 *) (ra + 0)) = (u4) mcode;
999 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1001 /* if we show disassembly, we have to skip the nop's */
1006 /* patch native function pointer */
1008 *((ptrint *) (ra + 4)) = (ptrint) f;
1012 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1016 * These are local overrides for various environment variables in Emacs.
1017 * Please do not remove this and leave it at the end of the file, where
1018 * Emacs will automagically detect them.
1019 * ---------------------------------------------------------------------
1022 * indent-tabs-mode: t
1026 * vim:noexpandtab:sw=4:ts=4: