1 /* src/vm/jit/i386/patcher.c - i386 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/jit/i386/codegen.h"
34 #include "mm/memory.h"
36 #include "native/native.h"
38 #include "vm/builtin.h"
39 #include "vm/initialize.h"
41 #include "vm/jit/patcher-common.h"
43 #include "vmcore/class.h"
44 #include "vmcore/field.h"
45 #include "vmcore/options.h"
46 #include "vm/resolve.h"
47 #include "vmcore/references.h"
50 #define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
53 /* patcher_patch_code **********************************************************
55 Just patches back the original machine code.
57 *******************************************************************************/
59 void patcher_patch_code(patchref_t *pr)
61 PATCH_BACK_ORIGINAL_MCODE;
65 /* patcher_get_putstatic *******************************************************
69 <patched call position>
70 b8 00 00 00 00 mov $0x00000000,%eax
72 *******************************************************************************/
74 bool patcher_get_putstatic(patchref_t *pr)
80 /* get stuff from the stack */
83 uf = (unresolved_field *) pr->ref;
85 /* get the fieldinfo */
87 if (!(fi = resolve_field_eager(uf)))
90 /* check if the field's class is initialized */
92 if (!(fi->clazz->state & CLASS_INITIALIZED))
93 if (!initialize_class(fi->clazz))
96 PATCH_BACK_ORIGINAL_MCODE;
98 /* if we show disassembly, we have to skip the nop's */
101 ra = ra + PATCHER_CALL_SIZE;
103 /* patch the field value's address */
105 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
111 /* patcher_getfield ************************************************************
115 <patched call position>
116 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
118 *******************************************************************************/
120 bool patcher_getfield(patchref_t *pr)
123 unresolved_field *uf;
126 /* get stuff from the stack */
129 uf = (unresolved_field *) pr->ref;
131 /* get the fieldinfo */
133 if (!(fi = resolve_field_eager(uf)))
136 PATCH_BACK_ORIGINAL_MCODE;
138 /* if we show disassembly, we have to skip the nop's */
141 ra = ra + PATCHER_CALL_SIZE;
143 /* patch the field's offset */
145 *((u4 *) (ra + 2)) = (u4) (fi->offset);
147 /* if the field has type long, we need to patch the second move too */
149 if (fi->type == TYPE_LNG)
150 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
156 /* patcher_putfield ************************************************************
160 <patched call position>
161 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
163 *******************************************************************************/
165 bool patcher_putfield(patchref_t *pr)
168 unresolved_field *uf;
171 /* get stuff from the stack */
174 uf = (unresolved_field *) pr->ref;
176 /* get the fieldinfo */
178 if (!(fi = resolve_field_eager(uf)))
181 PATCH_BACK_ORIGINAL_MCODE;
183 /* if we show disassembly, we have to skip the nop's */
186 ra = ra + PATCHER_CALL_SIZE;
188 /* patch the field's offset */
190 if (fi->type != TYPE_LNG) {
191 *((u4 *) (ra + 2)) = (u4) (fi->offset);
194 /* The long code is special:
196 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
197 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
200 *((u4 *) (ra + 2)) = (u4) (fi->offset);
201 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
208 /* patcher_putfieldconst *******************************************************
212 <patched call position>
213 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
215 *******************************************************************************/
217 bool patcher_putfieldconst(patchref_t *pr)
220 unresolved_field *uf;
223 /* get stuff from the stack */
226 uf = (unresolved_field *) pr->ref;
228 /* get the fieldinfo */
230 if (!(fi = resolve_field_eager(uf)))
233 PATCH_BACK_ORIGINAL_MCODE;
235 /* if we show disassembly, we have to skip the nop's */
238 ra = ra + PATCHER_CALL_SIZE;
240 /* patch the field's offset */
242 if (!IS_2_WORD_TYPE(fi->type)) {
243 *((u4 *) (ra + 2)) = (u4) (fi->offset);
246 /* long/double code is different:
248 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
249 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
252 *((u4 *) (ra + 2)) = (u4) (fi->offset);
253 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
260 /* patcher_aconst **************************************************************
264 <patched call postition>
265 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
266 b8 00 00 00 00 mov $0x0000000,%eax
268 *******************************************************************************/
270 bool patcher_aconst(patchref_t *pr)
273 constant_classref *cr;
276 /* get stuff from the stack */
279 cr = (constant_classref *) pr->ref;
281 /* get the classinfo */
283 if (!(c = resolve_classref_eager(cr)))
286 PATCH_BACK_ORIGINAL_MCODE;
288 /* if we show disassembly, we have to skip the nop's */
291 ra = ra + PATCHER_CALL_SIZE;
293 /* patch the classinfo pointer */
295 *((ptrint *) (ra + 1)) = (ptrint) c;
301 /* patcher_builtin_multianewarray **********************************************
305 <patched call position>
306 c7 04 24 02 00 00 00 movl $0x2,(%esp)
307 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
309 83 c0 0c add $0xc,%eax
310 89 44 24 08 mov %eax,0x8(%esp)
311 b8 00 00 00 00 mov $0x00000000,%eax
314 *******************************************************************************/
316 bool patcher_builtin_multianewarray(patchref_t *pr)
319 constant_classref *cr;
322 /* get stuff from the stack */
325 cr = (constant_classref *) pr->ref;
327 /* get the classinfo */
329 if (!(c = resolve_classref_eager(cr)))
332 PATCH_BACK_ORIGINAL_MCODE;
334 /* if we show disassembly, we have to skip the nop's */
337 ra = ra + PATCHER_CALL_SIZE;
339 /* patch the classinfo pointer */
341 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
347 /* patcher_builtin_arraycheckcast **********************************************
351 <patched call position>
352 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
353 ba 00 00 00 00 mov $0x00000000,%edx
356 *******************************************************************************/
358 bool patcher_builtin_arraycheckcast(patchref_t *pr)
361 constant_classref *cr;
364 /* get stuff from the stack */
367 cr = (constant_classref *) pr->ref;
369 /* get the classinfo */
371 if (!(c = resolve_classref_eager(cr)))
374 PATCH_BACK_ORIGINAL_MCODE;
376 /* if we show disassembly, we have to skip the nop's */
379 ra = ra + PATCHER_CALL_SIZE;
381 /* patch the classinfo pointer */
383 *((ptrint *) (ra + 4)) = (ptrint) c;
385 /* patch new function address */
387 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
393 /* patcher_invokestatic_special ************************************************
397 <patched call position>
398 b9 00 00 00 00 mov $0x00000000,%ecx
401 *******************************************************************************/
403 bool patcher_invokestatic_special(patchref_t *pr)
406 unresolved_method *um;
409 /* get stuff from the stack */
412 um = (unresolved_method *) pr->ref;
414 /* get the fieldinfo */
416 if (!(m = resolve_method_eager(um)))
419 PATCH_BACK_ORIGINAL_MCODE;
421 /* if we show disassembly, we have to skip the nop's */
424 ra = ra + PATCHER_CALL_SIZE;
426 /* patch stubroutine */
428 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
434 /* patcher_invokevirtual *******************************************************
438 <patched call position>
439 8b 08 mov (%eax),%ecx
440 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
443 *******************************************************************************/
445 bool patcher_invokevirtual(patchref_t *pr)
448 unresolved_method *um;
451 /* get stuff from the stack */
454 um = (unresolved_method *) pr->ref;
456 /* get the fieldinfo */
458 if (!(m = resolve_method_eager(um)))
461 PATCH_BACK_ORIGINAL_MCODE;
463 /* if we show disassembly, we have to skip the nop's */
466 ra = ra + PATCHER_CALL_SIZE;
468 /* patch vftbl index */
470 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
471 sizeof(methodptr) * m->vftblindex);
477 /* patcher_invokeinterface *****************************************************
481 <patched call position>
482 8b 00 mov (%eax),%eax
483 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
484 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
487 *******************************************************************************/
489 bool patcher_invokeinterface(patchref_t *pr)
492 unresolved_method *um;
495 /* get stuff from the stack */
498 um = (unresolved_method *) pr->ref;
500 /* get the fieldinfo */
502 if (!(m = resolve_method_eager(um)))
505 PATCH_BACK_ORIGINAL_MCODE;
507 /* if we show disassembly, we have to skip the nop's */
510 ra = ra + PATCHER_CALL_SIZE;
512 /* patch interfacetable index */
514 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
515 sizeof(methodptr) * m->clazz->index);
517 /* patch method offset */
519 *((s4 *) (ra + 2 + 6 + 2)) =
520 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
526 /* patcher_checkcast_instanceof_flags ******************************************
530 <patched call position>
531 b9 00 00 00 00 mov $0x00000000,%ecx
533 *******************************************************************************/
535 bool patcher_checkcast_instanceof_flags(patchref_t *pr)
538 constant_classref *cr;
541 /* get stuff from the stack */
544 cr = (constant_classref *) pr->ref;
546 /* get the fieldinfo */
548 if (!(c = resolve_classref_eager(cr)))
551 PATCH_BACK_ORIGINAL_MCODE;
553 /* if we show disassembly, we have to skip the nop's */
556 ra = ra + PATCHER_CALL_SIZE;
558 /* patch class flags */
560 *((s4 *) (ra + 1)) = (s4) c->flags;
566 /* patcher_checkcast_interface *************************************************
570 <patched call position>
571 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
572 81 ea 00 00 00 00 sub $0x00000000,%edx
574 0f 8f 06 00 00 00 jg 0x00000000
575 8b 35 03 00 00 00 mov 0x3,%esi
576 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
578 *******************************************************************************/
580 bool patcher_checkcast_interface(patchref_t *pr)
583 constant_classref *cr;
586 /* get stuff from the stack */
589 cr = (constant_classref *) pr->ref;
591 /* get the fieldinfo */
593 if (!(c = resolve_classref_eager(cr)))
596 PATCH_BACK_ORIGINAL_MCODE;
598 /* if we show disassembly, we have to skip the nop's */
601 ra = ra + PATCHER_CALL_SIZE;
603 /* patch super class index */
605 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
607 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
608 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
609 c->index * sizeof(methodptr*));
615 /* patcher_instanceof_interface ************************************************
619 <patched call position>
620 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
621 81 ea 00 00 00 00 sub $0x00000000,%edx
623 0f 8e 13 00 00 00 jle 0x00000000
624 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
626 *******************************************************************************/
628 bool patcher_instanceof_interface(patchref_t *pr)
631 constant_classref *cr;
634 /* get stuff from the stack */
637 cr = (constant_classref *) pr->ref;
639 /* get the fieldinfo */
641 if (!(c = resolve_classref_eager(cr)))
644 PATCH_BACK_ORIGINAL_MCODE;
646 /* if we show disassembly, we have to skip the nop's */
649 ra = ra + PATCHER_CALL_SIZE;
651 /* patch super class index */
653 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
655 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
656 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
657 c->index * sizeof(methodptr*));
663 /* patcher_checkcast_class *****************************************************
667 <patched call position>
668 ba 00 00 00 00 mov $0x00000000,%edx
669 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
670 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
672 ba 00 00 00 00 mov $0x00000000,%edx
674 *******************************************************************************/
676 bool patcher_checkcast_class(patchref_t *pr)
679 constant_classref *cr;
682 /* get stuff from the stack */
685 cr = (constant_classref *) pr->ref;
687 /* get the fieldinfo */
689 if (!(c = resolve_classref_eager(cr)))
692 PATCH_BACK_ORIGINAL_MCODE;
694 /* if we show disassembly, we have to skip the nop's */
697 ra = ra + PATCHER_CALL_SIZE;
699 /* patch super class' vftbl */
701 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
702 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
708 /* patcher_instanceof_class ****************************************************
712 <patched call position>
713 b9 00 00 00 00 mov $0x0,%ecx
714 8b 40 14 mov 0x14(%eax),%eax
715 8b 51 18 mov 0x18(%ecx),%edx
716 8b 49 14 mov 0x14(%ecx),%ecx
718 *******************************************************************************/
720 bool patcher_instanceof_class(patchref_t *pr)
723 constant_classref *cr;
726 /* get stuff from the stack */
729 cr = (constant_classref *) pr->ref;
731 /* get the fieldinfo */
733 if (!(c = resolve_classref_eager(cr)))
736 PATCH_BACK_ORIGINAL_MCODE;
738 /* if we show disassembly, we have to skip the nop's */
741 ra = ra + PATCHER_CALL_SIZE;
743 /* patch super class' vftbl */
745 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
752 * These are local overrides for various environment variables in Emacs.
753 * Please do not remove this and leave it at the end of the file, where
754 * Emacs will automagically detect them.
755 * ---------------------------------------------------------------------
758 * indent-tabs-mode: t
762 * vim:noexpandtab:sw=4:ts=4: