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 7441 2007-03-02 23:13:10Z michi $
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 "vmcore/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 */
169 if (opt_showdisassemble)
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 */
214 if (opt_showdisassemble)
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 */
264 if (opt_showdisassemble)
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 */
321 if (opt_showdisassemble)
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 */
379 if (opt_showdisassemble)
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 */
430 if (opt_showdisassemble)
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 */
482 if (opt_showdisassemble)
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 */
532 if (opt_showdisassemble)
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 */
579 if (opt_showdisassemble)
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 */
628 if (opt_showdisassemble)
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 */
679 if (opt_showdisassemble)
682 /* patch class flags */
684 *((s4 *) (ra + 1)) = (s4) c->flags;
690 /* patcher_checkcast_instanceof_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 8e 00 00 00 00 jle 0x00000000
699 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
701 *******************************************************************************/
703 bool patcher_checkcast_instanceof_interface(u1 *sp)
707 constant_classref *cr;
710 /* get stuff from the stack */
712 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
713 mcode = *((u8 *) (sp + 2 * 4));
714 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
716 /* get the fieldinfo */
718 if (!(c = resolve_classref_eager(cr)))
721 /* patch back original code */
723 *((u4 *) (ra + 0)) = (u4) mcode;
724 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
726 /* if we show disassembly, we have to skip the nop's */
728 if (opt_showdisassemble)
731 /* patch super class index */
733 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
735 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
736 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
737 c->index * sizeof(methodptr*));
743 /* patcher_checkcast_class *****************************************************
747 <patched call position>
748 ba 00 00 00 00 mov $0x00000000,%edx
749 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
750 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
752 ba 00 00 00 00 mov $0x00000000,%edx
754 *******************************************************************************/
756 bool patcher_checkcast_class(u1 *sp)
760 constant_classref *cr;
763 /* get stuff from the stack */
765 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
766 mcode = *((u8 *) (sp + 2 * 4));
767 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
769 /* get the fieldinfo */
771 if (!(c = resolve_classref_eager(cr)))
774 /* patch back original code */
776 *((u4 *) (ra + 0)) = (u4) mcode;
777 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
779 /* if we show disassembly, we have to skip the nop's */
781 if (opt_showdisassemble)
784 /* patch super class' vftbl */
786 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
787 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
793 /* patcher_instanceof_class ****************************************************
797 <patched call position>
798 b9 00 00 00 00 mov $0x0,%ecx
799 8b 40 14 mov 0x14(%eax),%eax
800 8b 51 18 mov 0x18(%ecx),%edx
801 8b 49 14 mov 0x14(%ecx),%ecx
803 *******************************************************************************/
805 bool patcher_instanceof_class(u1 *sp)
809 constant_classref *cr;
812 /* get stuff from the stack */
814 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
815 mcode = *((u8 *) (sp + 2 * 4));
816 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
818 /* get the fieldinfo */
820 if (!(c = resolve_classref_eager(cr)))
823 /* patch back original code */
825 *((u4 *) (ra + 0)) = (u4) mcode;
826 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
828 /* if we show disassembly, we have to skip the nop's */
830 if (opt_showdisassemble)
833 /* patch super class' vftbl */
835 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
841 /* patcher_clinit **************************************************************
843 Is used int PUT/GETSTATIC and native stub.
847 <patched call position>
849 *******************************************************************************/
851 bool patcher_clinit(u1 *sp)
857 /* get stuff from the stack */
859 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
860 mcode = *((u8 *) (sp + 2 * 4));
861 c = (classinfo *) *((ptrint *) (sp + 1 * 4));
863 /* check if the class is initialized */
865 if (!(c->state & CLASS_INITIALIZED))
866 if (!initialize_class(c))
869 /* patch back original code */
871 *((u4 *) (ra + 0)) = (u4) mcode;
872 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
878 /* patcher_athrow_areturn ******************************************************
882 <patched call position>
884 *******************************************************************************/
886 #ifdef ENABLE_VERIFIER
887 bool patcher_athrow_areturn(u1 *sp)
891 unresolved_class *uc;
893 /* get stuff from the stack */
895 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
896 mcode = *((u8 *) (sp + 2 * 4));
897 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
899 /* resolve the class and check subtype constraints */
901 if (!resolve_class_eager_no_access_check(uc))
904 /* patch back original code */
906 *((u4 *) (ra + 0)) = (u4) mcode;
907 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
911 #endif /* ENABLE_VERIFIER */
914 /* patcher_resolve_native ******************************************************
916 Is used in native stub.
920 <patched call position>
921 c7 44 24 04 28 90 01 40 movl $0x40019028,0x4(%esp)
923 *******************************************************************************/
925 #if !defined(WITH_STATIC_CLASSPATH)
926 bool patcher_resolve_native(u1 *sp)
933 /* get stuff from the stack */
935 ra = (u1 *) *((ptrint *) (sp + 6 * 4));
936 mcode = *((u8 *) (sp + 2 * 4));
937 m = (methodinfo *) *((ptrint *) (sp + 1 * 4));
939 /* resolve native function */
941 if (!(f = native_resolve_function(m)))
944 /* patch back original code */
946 *((u4 *) (ra + 0)) = (u4) mcode;
947 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
949 /* if we show disassembly, we have to skip the nop's */
951 if (opt_showdisassemble)
954 /* patch native function pointer */
956 *((ptrint *) (ra + 4)) = (ptrint) f;
960 #endif /* !defined(WITH_STATIC_CLASSPATH) */
964 * These are local overrides for various environment variables in Emacs.
965 * Please do not remove this and leave it at the end of the file, where
966 * Emacs will automagically detect them.
967 * ---------------------------------------------------------------------
970 * indent-tabs-mode: t
974 * vim:noexpandtab:sw=4:ts=4: