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 7596 2007-03-28 21:05:53Z twisti $
33 #include "vm/jit/i386/codegen.h"
35 #include "mm/memory.h"
37 #include "native/native.h"
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
43 #include "vm/jit/patcher.h"
44 #include "vm/jit/stacktrace.h"
46 #include "vmcore/class.h"
47 #include "vmcore/field.h"
48 #include "vmcore/options.h"
49 #include "vm/resolve.h"
50 #include "vmcore/references.h"
53 /* patcher_wrapper *************************************************************
55 Wrapper for all patchers. It also creates the stackframe info
58 If the return value of the patcher function is false, it gets the
59 exception object, clears the exception pointer and returns the
62 *******************************************************************************/
64 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
73 /* define the patcher function */
75 bool (*patcher_function)(u1 *);
77 /* get stuff from the stack */
79 xpc = (u1 *) *((ptrint *) (sp + 6 * 4));
80 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
81 f = (functionptr) *((ptrint *) (sp + 0 * 4));
83 /* calculate and set the new return address */
85 xpc = xpc - PATCHER_CALL_SIZE;
87 *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
89 /* cast the passed function to a patcher function */
91 patcher_function = (bool (*)(u1 *)) (ptrint) f;
93 /* enter a monitor on the patching position */
97 /* create the stackframeinfo */
99 /* RA is passed as NULL, but the XPC is correct and can be used in
100 stacktrace_create_extern_stackframeinfo for
101 md_codegen_get_pv_from_pc. */
103 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
105 /* call the proper patcher function */
107 result = (patcher_function)(sp);
109 /* remove the stackframeinfo */
111 stacktrace_remove_stackframeinfo(&sfi);
113 /* check for return value and exit accordingly */
115 if (result == false) {
116 e = exceptions_get_and_clear_exception();
123 PATCHER_MARK_PATCHED_MONITOREXIT;
129 /* patcher_get_putstatic *******************************************************
133 <patched call position>
134 b8 00 00 00 00 mov $0x00000000,%eax
136 *******************************************************************************/
138 bool patcher_get_putstatic(u1 *sp)
142 unresolved_field *uf;
145 /* get stuff from the stack */
147 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
148 mcode = *((u8 *) (sp + 2 * 4));
149 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
151 /* get the fieldinfo */
153 if (!(fi = resolve_field_eager(uf)))
156 /* check if the field's class is initialized */
158 if (!(fi->class->state & CLASS_INITIALIZED))
159 if (!initialize_class(fi->class))
162 /* patch back original code */
164 *((u4 *) (ra + 0)) = (u4) mcode;
165 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
167 /* if we show disassembly, we have to skip the nop's */
172 /* patch the field value's address */
174 *((ptrint *) (ra + 1)) = (ptrint) &(fi->value);
180 /* patcher_getfield ************************************************************
184 <patched call position>
185 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
187 *******************************************************************************/
189 bool patcher_getfield(u1 *sp)
193 unresolved_field *uf;
196 /* get stuff from the stack */
198 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
199 mcode = *((u8 *) (sp + 2 * 4));
200 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
202 /* get the fieldinfo */
204 if (!(fi = resolve_field_eager(uf)))
207 /* patch back original code */
209 *((u4 *) (ra + 0)) = (u4) mcode;
210 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
212 /* if we show disassembly, we have to skip the nop's */
217 /* patch the field's offset */
219 *((u4 *) (ra + 2)) = (u4) (fi->offset);
221 /* if the field has type long, we need to patch the second move too */
223 if (fi->type == TYPE_LNG)
224 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
230 /* patcher_putfield ************************************************************
234 <patched call position>
235 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
237 *******************************************************************************/
239 bool patcher_putfield(u1 *sp)
243 unresolved_field *uf;
246 /* get stuff from the stack */
248 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
249 mcode = *((u8 *) (sp + 2 * 4));
250 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
252 /* get the fieldinfo */
254 if (!(fi = resolve_field_eager(uf)))
257 /* patch back original code */
259 *((u4 *) (ra + 0)) = (u4) mcode;
260 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
262 /* if we show disassembly, we have to skip the nop's */
267 /* patch the field's offset */
269 if (fi->type != TYPE_LNG) {
270 *((u4 *) (ra + 2)) = (u4) (fi->offset);
273 /* The long code is special:
275 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
276 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
279 *((u4 *) (ra + 2)) = (u4) (fi->offset);
280 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
287 /* patcher_putfieldconst *******************************************************
291 <patched call position>
292 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
294 *******************************************************************************/
296 bool patcher_putfieldconst(u1 *sp)
300 unresolved_field *uf;
303 /* get stuff from the stack */
305 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
306 mcode = *((u8 *) (sp + 2 * 4));
307 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
309 /* get the fieldinfo */
311 if (!(fi = resolve_field_eager(uf)))
314 /* patch back original code */
316 *((u4 *) (ra + 0)) = (u4) mcode;
317 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
319 /* if we show disassembly, we have to skip the nop's */
324 /* patch the field's offset */
326 if (!IS_2_WORD_TYPE(fi->type)) {
327 *((u4 *) (ra + 2)) = (u4) (fi->offset);
330 /* long/double code is different:
332 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
333 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
336 *((u4 *) (ra + 2)) = (u4) (fi->offset);
337 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
344 /* patcher_aconst **************************************************************
348 <patched call postition>
349 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
350 b8 00 00 00 00 mov $0x0000000,%eax
352 *******************************************************************************/
354 bool patcher_aconst(u1 *sp)
358 constant_classref *cr;
361 /* get stuff from the stack */
363 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
364 mcode = *((u8 *) (sp + 2 * 4));
365 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
367 /* get the classinfo */
369 if (!(c = resolve_classref_eager(cr)))
372 /* patch back original code */
374 *((u4 *) (ra + 0)) = (u4) mcode;
375 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
377 /* if we show disassembly, we have to skip the nop's */
382 /* patch the classinfo pointer */
384 *((ptrint *) (ra + 1)) = (ptrint) c;
390 /* patcher_builtin_multianewarray **********************************************
394 <patched call position>
395 c7 04 24 02 00 00 00 movl $0x2,(%esp)
396 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
398 83 c0 0c add $0xc,%eax
399 89 44 24 08 mov %eax,0x8(%esp)
400 b8 00 00 00 00 mov $0x00000000,%eax
403 *******************************************************************************/
405 bool patcher_builtin_multianewarray(u1 *sp)
409 constant_classref *cr;
412 /* get stuff from the stack */
414 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
415 mcode = *((u8 *) (sp + 2 * 4));
416 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
418 /* get the classinfo */
420 if (!(c = resolve_classref_eager(cr)))
423 /* patch back original code */
425 *((u4 *) (ra + 0)) = (u4) mcode;
426 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
428 /* if we show disassembly, we have to skip the nop's */
433 /* patch the classinfo pointer */
435 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
437 /* patch new function address */
439 *((ptrint *) (ra + 7 + 8 + 2 + 3 + 4 + 1)) =
440 (ptrint) BUILTIN_multianewarray;
446 /* patcher_builtin_arraycheckcast **********************************************
450 <patched call position>
451 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
452 ba 00 00 00 00 mov $0x00000000,%edx
455 *******************************************************************************/
457 bool patcher_builtin_arraycheckcast(u1 *sp)
461 constant_classref *cr;
464 /* get stuff from the stack */
466 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
467 mcode = *((u8 *) (sp + 2 * 4));
468 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
470 /* get the classinfo */
472 if (!(c = resolve_classref_eager(cr)))
475 /* patch back original code */
477 *((u4 *) (ra + 0)) = (u4) mcode;
478 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
480 /* if we show disassembly, we have to skip the nop's */
485 /* patch the classinfo pointer */
487 *((ptrint *) (ra + 4)) = (ptrint) c;
489 /* patch new function address */
491 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
497 /* patcher_invokestatic_special ************************************************
501 <patched call position>
502 b9 00 00 00 00 mov $0x00000000,%ecx
505 *******************************************************************************/
507 bool patcher_invokestatic_special(u1 *sp)
511 unresolved_method *um;
514 /* get stuff from the stack */
516 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
517 mcode = *((u8 *) (sp + 2 * 4));
518 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
520 /* get the fieldinfo */
522 if (!(m = resolve_method_eager(um)))
525 /* patch back original code */
527 *((u4 *) (ra + 0)) = (u4) mcode;
528 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
530 /* if we show disassembly, we have to skip the nop's */
535 /* patch stubroutine */
537 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
543 /* patcher_invokevirtual *******************************************************
547 <patched call position>
548 8b 08 mov (%eax),%ecx
549 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
552 *******************************************************************************/
554 bool patcher_invokevirtual(u1 *sp)
558 unresolved_method *um;
561 /* get stuff from the stack */
563 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
564 mcode = *((u8 *) (sp + 2 * 4));
565 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
567 /* get the fieldinfo */
569 if (!(m = resolve_method_eager(um)))
572 /* patch back original code */
574 *((u4 *) (ra + 0)) = (u4) mcode;
575 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
577 /* if we show disassembly, we have to skip the nop's */
582 /* patch vftbl index */
584 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
585 sizeof(methodptr) * m->vftblindex);
591 /* patcher_invokeinterface *****************************************************
595 <patched call position>
596 8b 00 mov (%eax),%eax
597 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
598 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
601 *******************************************************************************/
603 bool patcher_invokeinterface(u1 *sp)
607 unresolved_method *um;
610 /* get stuff from the stack */
612 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
613 mcode = *((u8 *) (sp + 2 * 4));
614 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
616 /* get the fieldinfo */
618 if (!(m = resolve_method_eager(um)))
621 /* patch back original code */
623 *((u4 *) (ra + 0)) = (u4) mcode;
624 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
626 /* if we show disassembly, we have to skip the nop's */
631 /* patch interfacetable index */
633 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
634 sizeof(methodptr) * m->class->index);
636 /* patch method offset */
638 *((s4 *) (ra + 2 + 6 + 2)) =
639 (s4) (sizeof(methodptr) * (m - m->class->methods));
645 /* patcher_checkcast_instanceof_flags ******************************************
649 <patched call position>
650 b9 00 00 00 00 mov $0x00000000,%ecx
652 *******************************************************************************/
654 bool patcher_checkcast_instanceof_flags(u1 *sp)
658 constant_classref *cr;
661 /* get stuff from the stack */
663 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
664 mcode = *((u8 *) (sp + 2 * 4));
665 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
667 /* get the fieldinfo */
669 if (!(c = resolve_classref_eager(cr)))
672 /* patch back original code */
674 *((u4 *) (ra + 0)) = (u4) mcode;
675 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
677 /* if we show disassembly, we have to skip the nop's */
682 /* patch class flags */
684 *((s4 *) (ra + 1)) = (s4) c->flags;
690 /* patcher_checkcast_interface *************************************************
694 <patched call position>
695 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
696 81 ea 00 00 00 00 sub $0x00000000,%edx
698 0f 8f 06 00 00 00 jg 0x00000000
699 8b 35 03 00 00 00 mov 0x3,%esi
700 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
702 *******************************************************************************/
704 bool patcher_checkcast_interface(u1 *sp)
708 constant_classref *cr;
711 /* get stuff from the stack */
713 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
714 mcode = *((u8 *) (sp + 2 * 4));
715 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
717 /* get the fieldinfo */
719 if (!(c = resolve_classref_eager(cr)))
722 /* patch back original code */
724 *((u4 *) (ra + 0)) = (u4) mcode;
725 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
727 /* if we show disassembly, we have to skip the nop's */
732 /* patch super class index */
734 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
736 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
737 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
738 c->index * sizeof(methodptr*));
744 /* patcher_instanceof_interface ************************************************
748 <patched call position>
749 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
750 81 ea 00 00 00 00 sub $0x00000000,%edx
752 0f 8e 13 00 00 00 jle 0x00000000
753 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
755 *******************************************************************************/
757 bool patcher_instanceof_interface(u1 *sp)
761 constant_classref *cr;
764 /* get stuff from the stack */
766 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
767 mcode = *((u8 *) (sp + 2 * 4));
768 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
770 /* get the fieldinfo */
772 if (!(c = resolve_classref_eager(cr)))
775 /* patch back original code */
777 *((u4 *) (ra + 0)) = (u4) mcode;
778 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
780 /* if we show disassembly, we have to skip the nop's */
785 /* patch super class index */
787 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
789 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
790 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
791 c->index * sizeof(methodptr*));
797 /* patcher_checkcast_class *****************************************************
801 <patched call position>
802 ba 00 00 00 00 mov $0x00000000,%edx
803 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
804 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
806 ba 00 00 00 00 mov $0x00000000,%edx
808 *******************************************************************************/
810 bool patcher_checkcast_class(u1 *sp)
814 constant_classref *cr;
817 /* get stuff from the stack */
819 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
820 mcode = *((u8 *) (sp + 2 * 4));
821 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
823 /* get the fieldinfo */
825 if (!(c = resolve_classref_eager(cr)))
828 /* patch back original code */
830 *((u4 *) (ra + 0)) = (u4) mcode;
831 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
833 /* if we show disassembly, we have to skip the nop's */
838 /* patch super class' vftbl */
840 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
841 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
847 /* patcher_instanceof_class ****************************************************
851 <patched call position>
852 b9 00 00 00 00 mov $0x0,%ecx
853 8b 40 14 mov 0x14(%eax),%eax
854 8b 51 18 mov 0x18(%ecx),%edx
855 8b 49 14 mov 0x14(%ecx),%ecx
857 *******************************************************************************/
859 bool patcher_instanceof_class(u1 *sp)
863 constant_classref *cr;
866 /* get stuff from the stack */
868 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
869 mcode = *((u8 *) (sp + 2 * 4));
870 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
872 /* get the fieldinfo */
874 if (!(c = resolve_classref_eager(cr)))
877 /* patch back original code */
879 *((u4 *) (ra + 0)) = (u4) mcode;
880 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
882 /* if we show disassembly, we have to skip the nop's */
887 /* patch super class' vftbl */
889 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
895 /* patcher_clinit **************************************************************
897 Is used int PUT/GETSTATIC and native stub.
901 <patched call position>
903 *******************************************************************************/
905 bool patcher_clinit(u1 *sp)
911 /* get stuff from the stack */
913 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
914 mcode = *((u8 *) (sp + 2 * 4));
915 c = (classinfo *) *((ptrint *) (sp + 1 * 4));
917 /* check if the class is initialized */
919 if (!(c->state & CLASS_INITIALIZED))
920 if (!initialize_class(c))
923 /* patch back original code */
925 *((u4 *) (ra + 0)) = (u4) mcode;
926 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
932 /* patcher_athrow_areturn ******************************************************
936 <patched call position>
938 *******************************************************************************/
940 #ifdef ENABLE_VERIFIER
941 bool patcher_athrow_areturn(u1 *sp)
945 unresolved_class *uc;
947 /* get stuff from the stack */
949 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
950 mcode = *((u8 *) (sp + 2 * 4));
951 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
953 /* resolve the class and check subtype constraints */
955 if (!resolve_class_eager_no_access_check(uc))
958 /* patch back original code */
960 *((u4 *) (ra + 0)) = (u4) mcode;
961 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
965 #endif /* ENABLE_VERIFIER */
968 /* patcher_resolve_native ******************************************************
970 Is used in native stub.
974 <patched call position>
975 c7 44 24 04 28 90 01 40 movl $0x40019028,0x4(%esp)
977 *******************************************************************************/
979 #if !defined(WITH_STATIC_CLASSPATH)
980 bool patcher_resolve_native(u1 *sp)
987 /* get stuff from the stack */
989 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
990 mcode = *((u8 *) (sp + 2 * 4));
991 m = (methodinfo *) *((ptrint *) (sp + 1 * 4));
993 /* resolve native function */
995 if (!(f = native_resolve_function(m)))
998 /* patch back original code */
1000 *((u4 *) (ra + 0)) = (u4) mcode;
1001 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1003 /* if we show disassembly, we have to skip the nop's */
1008 /* patch native function pointer */
1010 *((ptrint *) (ra + 4)) = (ptrint) f;
1014 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1018 * These are local overrides for various environment variables in Emacs.
1019 * Please do not remove this and leave it at the end of the file, where
1020 * Emacs will automagically detect them.
1021 * ---------------------------------------------------------------------
1024 * indent-tabs-mode: t
1028 * vim:noexpandtab:sw=4:ts=4: