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/exceptions.h"
40 #include "vm/initialize.h"
42 #include "vm/jit/patcher-common.h"
43 #include "vm/jit/stacktrace.h"
45 #include "vmcore/class.h"
46 #include "vmcore/field.h"
47 #include "vmcore/options.h"
48 #include "vm/resolve.h"
49 #include "vmcore/references.h"
52 #define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
55 /* patcher_patch_code **********************************************************
57 Just patches back the original machine code.
59 *******************************************************************************/
61 void patcher_patch_code(patchref_t *pr)
63 PATCH_BACK_ORIGINAL_MCODE;
67 /* patcher_get_putstatic *******************************************************
71 <patched call position>
72 b8 00 00 00 00 mov $0x00000000,%eax
74 *******************************************************************************/
76 bool patcher_get_putstatic(patchref_t *pr)
82 /* get stuff from the stack */
85 uf = (unresolved_field *) pr->ref;
87 /* get the fieldinfo */
89 if (!(fi = resolve_field_eager(uf)))
92 /* check if the field's class is initialized */
94 if (!(fi->clazz->state & CLASS_INITIALIZED))
95 if (!initialize_class(fi->clazz))
98 PATCH_BACK_ORIGINAL_MCODE;
100 /* if we show disassembly, we have to skip the nop's */
103 ra = ra + PATCHER_CALL_SIZE;
105 /* patch the field value's address */
107 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
113 /* patcher_getfield ************************************************************
117 <patched call position>
118 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
120 *******************************************************************************/
122 bool patcher_getfield(patchref_t *pr)
125 unresolved_field *uf;
128 /* get stuff from the stack */
131 uf = (unresolved_field *) pr->ref;
133 /* get the fieldinfo */
135 if (!(fi = resolve_field_eager(uf)))
138 PATCH_BACK_ORIGINAL_MCODE;
140 /* if we show disassembly, we have to skip the nop's */
143 ra = ra + PATCHER_CALL_SIZE;
145 /* patch the field's offset */
147 *((u4 *) (ra + 2)) = (u4) (fi->offset);
149 /* if the field has type long, we need to patch the second move too */
151 if (fi->type == TYPE_LNG)
152 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
158 /* patcher_putfield ************************************************************
162 <patched call position>
163 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
165 *******************************************************************************/
167 bool patcher_putfield(patchref_t *pr)
170 unresolved_field *uf;
173 /* get stuff from the stack */
176 uf = (unresolved_field *) pr->ref;
178 /* get the fieldinfo */
180 if (!(fi = resolve_field_eager(uf)))
183 PATCH_BACK_ORIGINAL_MCODE;
185 /* if we show disassembly, we have to skip the nop's */
188 ra = ra + PATCHER_CALL_SIZE;
190 /* patch the field's offset */
192 if (fi->type != TYPE_LNG) {
193 *((u4 *) (ra + 2)) = (u4) (fi->offset);
196 /* The long code is special:
198 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
199 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
202 *((u4 *) (ra + 2)) = (u4) (fi->offset);
203 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
210 /* patcher_putfieldconst *******************************************************
214 <patched call position>
215 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
217 *******************************************************************************/
219 bool patcher_putfieldconst(patchref_t *pr)
222 unresolved_field *uf;
225 /* get stuff from the stack */
228 uf = (unresolved_field *) pr->ref;
230 /* get the fieldinfo */
232 if (!(fi = resolve_field_eager(uf)))
235 PATCH_BACK_ORIGINAL_MCODE;
237 /* if we show disassembly, we have to skip the nop's */
240 ra = ra + PATCHER_CALL_SIZE;
242 /* patch the field's offset */
244 if (!IS_2_WORD_TYPE(fi->type)) {
245 *((u4 *) (ra + 2)) = (u4) (fi->offset);
248 /* long/double code is different:
250 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
251 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
254 *((u4 *) (ra + 2)) = (u4) (fi->offset);
255 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
262 /* patcher_aconst **************************************************************
266 <patched call postition>
267 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
268 b8 00 00 00 00 mov $0x0000000,%eax
270 *******************************************************************************/
272 bool patcher_aconst(patchref_t *pr)
275 constant_classref *cr;
278 /* get stuff from the stack */
281 cr = (constant_classref *) pr->ref;
283 /* get the classinfo */
285 if (!(c = resolve_classref_eager(cr)))
288 PATCH_BACK_ORIGINAL_MCODE;
290 /* if we show disassembly, we have to skip the nop's */
293 ra = ra + PATCHER_CALL_SIZE;
295 /* patch the classinfo pointer */
297 *((ptrint *) (ra + 1)) = (ptrint) c;
303 /* patcher_builtin_multianewarray **********************************************
307 <patched call position>
308 c7 04 24 02 00 00 00 movl $0x2,(%esp)
309 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
311 83 c0 0c add $0xc,%eax
312 89 44 24 08 mov %eax,0x8(%esp)
313 b8 00 00 00 00 mov $0x00000000,%eax
316 *******************************************************************************/
318 bool patcher_builtin_multianewarray(patchref_t *pr)
321 constant_classref *cr;
324 /* get stuff from the stack */
327 cr = (constant_classref *) pr->ref;
329 /* get the classinfo */
331 if (!(c = resolve_classref_eager(cr)))
334 PATCH_BACK_ORIGINAL_MCODE;
336 /* if we show disassembly, we have to skip the nop's */
339 ra = ra + PATCHER_CALL_SIZE;
341 /* patch the classinfo pointer */
343 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
349 /* patcher_builtin_arraycheckcast **********************************************
353 <patched call position>
354 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
355 ba 00 00 00 00 mov $0x00000000,%edx
358 *******************************************************************************/
360 bool patcher_builtin_arraycheckcast(patchref_t *pr)
363 constant_classref *cr;
366 /* get stuff from the stack */
369 cr = (constant_classref *) pr->ref;
371 /* get the classinfo */
373 if (!(c = resolve_classref_eager(cr)))
376 PATCH_BACK_ORIGINAL_MCODE;
378 /* if we show disassembly, we have to skip the nop's */
381 ra = ra + PATCHER_CALL_SIZE;
383 /* patch the classinfo pointer */
385 *((ptrint *) (ra + 4)) = (ptrint) c;
387 /* patch new function address */
389 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
395 /* patcher_invokestatic_special ************************************************
399 <patched call position>
400 b9 00 00 00 00 mov $0x00000000,%ecx
403 *******************************************************************************/
405 bool patcher_invokestatic_special(patchref_t *pr)
408 unresolved_method *um;
411 /* get stuff from the stack */
414 um = (unresolved_method *) pr->ref;
416 /* get the fieldinfo */
418 if (!(m = resolve_method_eager(um)))
421 PATCH_BACK_ORIGINAL_MCODE;
423 /* if we show disassembly, we have to skip the nop's */
426 ra = ra + PATCHER_CALL_SIZE;
428 /* patch stubroutine */
430 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
436 /* patcher_invokevirtual *******************************************************
440 <patched call position>
441 8b 08 mov (%eax),%ecx
442 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
445 *******************************************************************************/
447 bool patcher_invokevirtual(patchref_t *pr)
450 unresolved_method *um;
453 /* get stuff from the stack */
456 um = (unresolved_method *) pr->ref;
458 /* get the fieldinfo */
460 if (!(m = resolve_method_eager(um)))
463 PATCH_BACK_ORIGINAL_MCODE;
465 /* if we show disassembly, we have to skip the nop's */
468 ra = ra + PATCHER_CALL_SIZE;
470 /* patch vftbl index */
472 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
473 sizeof(methodptr) * m->vftblindex);
479 /* patcher_invokeinterface *****************************************************
483 <patched call position>
484 8b 00 mov (%eax),%eax
485 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
486 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
489 *******************************************************************************/
491 bool patcher_invokeinterface(patchref_t *pr)
494 unresolved_method *um;
497 /* get stuff from the stack */
500 um = (unresolved_method *) pr->ref;
502 /* get the fieldinfo */
504 if (!(m = resolve_method_eager(um)))
507 PATCH_BACK_ORIGINAL_MCODE;
509 /* if we show disassembly, we have to skip the nop's */
512 ra = ra + PATCHER_CALL_SIZE;
514 /* patch interfacetable index */
516 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
517 sizeof(methodptr) * m->clazz->index);
519 /* patch method offset */
521 *((s4 *) (ra + 2 + 6 + 2)) =
522 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
528 /* patcher_checkcast_instanceof_flags ******************************************
532 <patched call position>
533 b9 00 00 00 00 mov $0x00000000,%ecx
535 *******************************************************************************/
537 bool patcher_checkcast_instanceof_flags(patchref_t *pr)
540 constant_classref *cr;
543 /* get stuff from the stack */
546 cr = (constant_classref *) pr->ref;
548 /* get the fieldinfo */
550 if (!(c = resolve_classref_eager(cr)))
553 PATCH_BACK_ORIGINAL_MCODE;
555 /* if we show disassembly, we have to skip the nop's */
558 ra = ra + PATCHER_CALL_SIZE;
560 /* patch class flags */
562 *((s4 *) (ra + 1)) = (s4) c->flags;
568 /* patcher_checkcast_interface *************************************************
572 <patched call position>
573 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
574 81 ea 00 00 00 00 sub $0x00000000,%edx
576 0f 8f 06 00 00 00 jg 0x00000000
577 8b 35 03 00 00 00 mov 0x3,%esi
578 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
580 *******************************************************************************/
582 bool patcher_checkcast_interface(patchref_t *pr)
585 constant_classref *cr;
588 /* get stuff from the stack */
591 cr = (constant_classref *) pr->ref;
593 /* get the fieldinfo */
595 if (!(c = resolve_classref_eager(cr)))
598 PATCH_BACK_ORIGINAL_MCODE;
600 /* if we show disassembly, we have to skip the nop's */
603 ra = ra + PATCHER_CALL_SIZE;
605 /* patch super class index */
607 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
609 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
610 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
611 c->index * sizeof(methodptr*));
617 /* patcher_instanceof_interface ************************************************
621 <patched call position>
622 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
623 81 ea 00 00 00 00 sub $0x00000000,%edx
625 0f 8e 13 00 00 00 jle 0x00000000
626 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
628 *******************************************************************************/
630 bool patcher_instanceof_interface(patchref_t *pr)
633 constant_classref *cr;
636 /* get stuff from the stack */
639 cr = (constant_classref *) pr->ref;
641 /* get the fieldinfo */
643 if (!(c = resolve_classref_eager(cr)))
646 PATCH_BACK_ORIGINAL_MCODE;
648 /* if we show disassembly, we have to skip the nop's */
651 ra = ra + PATCHER_CALL_SIZE;
653 /* patch super class index */
655 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
657 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
658 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
659 c->index * sizeof(methodptr*));
665 /* patcher_checkcast_class *****************************************************
669 <patched call position>
670 ba 00 00 00 00 mov $0x00000000,%edx
671 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
672 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
674 ba 00 00 00 00 mov $0x00000000,%edx
676 *******************************************************************************/
678 bool patcher_checkcast_class(patchref_t *pr)
681 constant_classref *cr;
684 /* get stuff from the stack */
687 cr = (constant_classref *) pr->ref;
689 /* get the fieldinfo */
691 if (!(c = resolve_classref_eager(cr)))
694 PATCH_BACK_ORIGINAL_MCODE;
696 /* if we show disassembly, we have to skip the nop's */
699 ra = ra + PATCHER_CALL_SIZE;
701 /* patch super class' vftbl */
703 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
709 /* patcher_instanceof_class ****************************************************
713 <patched call position>
714 b9 00 00 00 00 mov $0x0,%ecx
715 8b 40 14 mov 0x14(%eax),%eax
716 8b 51 18 mov 0x18(%ecx),%edx
717 8b 49 14 mov 0x14(%ecx),%ecx
719 *******************************************************************************/
721 bool patcher_instanceof_class(patchref_t *pr)
724 constant_classref *cr;
727 /* get stuff from the stack */
730 cr = (constant_classref *) pr->ref;
732 /* get the fieldinfo */
734 if (!(c = resolve_classref_eager(cr)))
737 PATCH_BACK_ORIGINAL_MCODE;
739 /* if we show disassembly, we have to skip the nop's */
742 ra = ra + PATCHER_CALL_SIZE;
744 /* patch super class' vftbl */
746 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
753 * These are local overrides for various environment variables in Emacs.
754 * Please do not remove this and leave it at the end of the file, where
755 * Emacs will automagically detect them.
756 * ---------------------------------------------------------------------
759 * indent-tabs-mode: t
763 * vim:noexpandtab:sw=4:ts=4: