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"
41 #include "vm/initialize.h"
42 #include "vm/options.h"
43 #include "vm/references.h"
44 #include "vm/resolve.h"
46 #include "vm/jit/patcher-common.h"
49 #define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
52 /* patcher_patch_code **********************************************************
54 Just patches back the original machine code.
56 *******************************************************************************/
58 void patcher_patch_code(patchref_t *pr)
60 PATCH_BACK_ORIGINAL_MCODE;
64 /* patcher_get_putstatic *******************************************************
68 <patched call position>
69 b8 00 00 00 00 mov $0x00000000,%eax
71 *******************************************************************************/
73 bool patcher_get_putstatic(patchref_t *pr)
79 /* get stuff from the stack */
82 uf = (unresolved_field *) pr->ref;
84 /* get the fieldinfo */
86 if (!(fi = resolve_field_eager(uf)))
89 /* check if the field's class is initialized */
91 if (!(fi->clazz->state & CLASS_INITIALIZED))
92 if (!initialize_class(fi->clazz))
95 PATCH_BACK_ORIGINAL_MCODE;
97 /* if we show disassembly, we have to skip the nop's */
100 ra = ra + PATCHER_CALL_SIZE;
102 /* patch the field value's address */
104 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
110 /* patcher_getfield ************************************************************
114 <patched call position>
115 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
117 *******************************************************************************/
119 bool patcher_getfield(patchref_t *pr)
122 unresolved_field *uf;
125 /* get stuff from the stack */
128 uf = (unresolved_field *) pr->ref;
130 /* get the fieldinfo */
132 if (!(fi = resolve_field_eager(uf)))
135 PATCH_BACK_ORIGINAL_MCODE;
137 /* if we show disassembly, we have to skip the nop's */
140 ra = ra + PATCHER_CALL_SIZE;
142 /* patch the field's offset */
144 *((u4 *) (ra + 2)) = (u4) (fi->offset);
146 /* if the field has type long, we need to patch the second move too */
148 if (fi->type == TYPE_LNG)
149 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
155 /* patcher_putfield ************************************************************
159 <patched call position>
160 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
162 *******************************************************************************/
164 bool patcher_putfield(patchref_t *pr)
167 unresolved_field *uf;
170 /* get stuff from the stack */
173 uf = (unresolved_field *) pr->ref;
175 /* get the fieldinfo */
177 if (!(fi = resolve_field_eager(uf)))
180 PATCH_BACK_ORIGINAL_MCODE;
182 /* if we show disassembly, we have to skip the nop's */
185 ra = ra + PATCHER_CALL_SIZE;
187 /* patch the field's offset */
189 if (fi->type != TYPE_LNG) {
190 *((u4 *) (ra + 2)) = (u4) (fi->offset);
193 /* The long code is special:
195 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
196 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
199 *((u4 *) (ra + 2)) = (u4) (fi->offset);
200 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
207 /* patcher_putfieldconst *******************************************************
211 <patched call position>
212 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
214 *******************************************************************************/
216 bool patcher_putfieldconst(patchref_t *pr)
219 unresolved_field *uf;
222 /* get stuff from the stack */
225 uf = (unresolved_field *) pr->ref;
227 /* get the fieldinfo */
229 if (!(fi = resolve_field_eager(uf)))
232 PATCH_BACK_ORIGINAL_MCODE;
234 /* if we show disassembly, we have to skip the nop's */
237 ra = ra + PATCHER_CALL_SIZE;
239 /* patch the field's offset */
241 if (!IS_2_WORD_TYPE(fi->type)) {
242 *((u4 *) (ra + 2)) = (u4) (fi->offset);
245 /* long/double code is different:
247 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
248 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
251 *((u4 *) (ra + 2)) = (u4) (fi->offset);
252 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
259 /* patcher_aconst **************************************************************
263 <patched call position>
264 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
265 b8 00 00 00 00 mov $0x0000000,%eax
267 *******************************************************************************/
269 bool patcher_aconst(patchref_t *pr)
272 constant_classref *cr;
275 /* get stuff from the stack */
278 cr = (constant_classref *) pr->ref;
280 /* get the classinfo */
282 if (!(c = resolve_classref_eager(cr)))
285 PATCH_BACK_ORIGINAL_MCODE;
287 /* if we show disassembly, we have to skip the nop's */
290 ra = ra + PATCHER_CALL_SIZE;
292 /* patch the classinfo pointer */
294 *((ptrint *) (ra + 1)) = (ptrint) c;
300 /* patcher_builtin_multianewarray **********************************************
304 <patched call position>
305 c7 04 24 02 00 00 00 movl $0x2,(%esp)
306 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
308 83 c0 0c add $0xc,%eax
309 89 44 24 08 mov %eax,0x8(%esp)
310 b8 00 00 00 00 mov $0x00000000,%eax
313 *******************************************************************************/
315 bool patcher_builtin_multianewarray(patchref_t *pr)
318 constant_classref *cr;
321 /* get stuff from the stack */
324 cr = (constant_classref *) pr->ref;
326 /* get the classinfo */
328 if (!(c = resolve_classref_eager(cr)))
331 PATCH_BACK_ORIGINAL_MCODE;
333 /* if we show disassembly, we have to skip the nop's */
336 ra = ra + PATCHER_CALL_SIZE;
338 /* patch the classinfo pointer */
340 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
346 /* patcher_builtin_arraycheckcast **********************************************
350 <patched call position>
351 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
352 ba 00 00 00 00 mov $0x00000000,%edx
355 *******************************************************************************/
357 bool patcher_builtin_arraycheckcast(patchref_t *pr)
360 constant_classref *cr;
363 /* get stuff from the stack */
366 cr = (constant_classref *) pr->ref;
368 /* get the classinfo */
370 if (!(c = resolve_classref_eager(cr)))
373 PATCH_BACK_ORIGINAL_MCODE;
375 /* if we show disassembly, we have to skip the nop's */
378 ra = ra + PATCHER_CALL_SIZE;
380 /* patch the classinfo pointer */
382 *((ptrint *) (ra + 4)) = (ptrint) c;
384 /* patch new function address */
386 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
392 /* patcher_invokestatic_special ************************************************
396 <patched call position>
397 b9 00 00 00 00 mov $0x00000000,%ecx
400 *******************************************************************************/
402 bool patcher_invokestatic_special(patchref_t *pr)
405 unresolved_method *um;
408 /* get stuff from the stack */
411 um = (unresolved_method *) pr->ref;
413 /* get the methodinfo */
415 if (!(m = resolve_method_eager(um)))
418 PATCH_BACK_ORIGINAL_MCODE;
420 /* if we show disassembly, we have to skip the nop's */
423 ra = ra + PATCHER_CALL_SIZE;
425 /* patch stubroutine */
427 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
433 /* patcher_invokevirtual *******************************************************
437 <patched call position>
438 8b 08 mov (%eax),%ecx
439 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
442 *******************************************************************************/
444 bool patcher_invokevirtual(patchref_t *pr)
447 unresolved_method *um;
450 /* get stuff from the stack */
453 um = (unresolved_method *) pr->ref;
455 /* get the fieldinfo */
457 if (!(m = resolve_method_eager(um)))
460 PATCH_BACK_ORIGINAL_MCODE;
462 /* if we show disassembly, we have to skip the nop's */
465 ra = ra + PATCHER_CALL_SIZE;
467 /* patch vftbl index */
469 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
470 sizeof(methodptr) * m->vftblindex);
476 /* patcher_invokeinterface *****************************************************
480 <patched call position>
481 8b 00 mov (%eax),%eax
482 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
483 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
486 *******************************************************************************/
488 bool patcher_invokeinterface(patchref_t *pr)
491 unresolved_method *um;
494 /* get stuff from the stack */
497 um = (unresolved_method *) pr->ref;
499 /* get the fieldinfo */
501 if (!(m = resolve_method_eager(um)))
504 PATCH_BACK_ORIGINAL_MCODE;
506 /* if we show disassembly, we have to skip the nop's */
509 ra = ra + PATCHER_CALL_SIZE;
511 /* patch interfacetable index */
513 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
514 sizeof(methodptr) * m->clazz->index);
516 /* patch method offset */
518 *((s4 *) (ra + 2 + 6 + 2)) =
519 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
525 /* patcher_checkcast_instanceof_flags ******************************************
529 <patched call position>
530 b9 00 00 00 00 mov $0x00000000,%ecx
532 *******************************************************************************/
534 bool patcher_checkcast_instanceof_flags(patchref_t *pr)
537 constant_classref *cr;
540 /* get stuff from the stack */
543 cr = (constant_classref *) pr->ref;
545 /* get the fieldinfo */
547 if (!(c = resolve_classref_eager(cr)))
550 PATCH_BACK_ORIGINAL_MCODE;
552 /* if we show disassembly, we have to skip the nop's */
555 ra = ra + PATCHER_CALL_SIZE;
557 /* patch class flags */
559 *((s4 *) (ra + 1)) = (s4) c->flags;
565 /* patcher_checkcast_interface *************************************************
569 <patched call position>
570 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
571 81 ea 00 00 00 00 sub $0x00000000,%edx
573 0f 8f 06 00 00 00 jg 0x00000000
574 8b 35 03 00 00 00 mov 0x3,%esi
575 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
577 *******************************************************************************/
579 bool patcher_checkcast_interface(patchref_t *pr)
582 constant_classref *cr;
585 /* get stuff from the stack */
588 cr = (constant_classref *) pr->ref;
590 /* get the fieldinfo */
592 if (!(c = resolve_classref_eager(cr)))
595 PATCH_BACK_ORIGINAL_MCODE;
597 /* if we show disassembly, we have to skip the nop's */
600 ra = ra + PATCHER_CALL_SIZE;
602 /* patch super class index */
604 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
606 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
607 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
608 c->index * sizeof(methodptr*));
614 /* patcher_instanceof_interface ************************************************
618 <patched call position>
619 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
620 81 ea 00 00 00 00 sub $0x00000000,%edx
622 0f 8e 13 00 00 00 jle 0x00000000
623 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
625 *******************************************************************************/
627 bool patcher_instanceof_interface(patchref_t *pr)
630 constant_classref *cr;
633 /* get stuff from the stack */
636 cr = (constant_classref *) pr->ref;
638 /* get the fieldinfo */
640 if (!(c = resolve_classref_eager(cr)))
643 PATCH_BACK_ORIGINAL_MCODE;
645 /* if we show disassembly, we have to skip the nop's */
648 ra = ra + PATCHER_CALL_SIZE;
650 /* patch super class index */
652 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
654 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
655 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
656 c->index * sizeof(methodptr*));
662 /* patcher_checkcast_class *****************************************************
666 <patched call position>
667 ba 00 00 00 00 mov $0x00000000,%edx
668 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
669 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
671 ba 00 00 00 00 mov $0x00000000,%edx
673 *******************************************************************************/
675 bool patcher_checkcast_class(patchref_t *pr)
678 constant_classref *cr;
681 /* get stuff from the stack */
684 cr = (constant_classref *) pr->ref;
686 /* get the fieldinfo */
688 if (!(c = resolve_classref_eager(cr)))
691 PATCH_BACK_ORIGINAL_MCODE;
693 /* if we show disassembly, we have to skip the nop's */
696 ra = ra + PATCHER_CALL_SIZE;
698 /* patch super class' vftbl */
700 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
701 *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
707 /* patcher_instanceof_class ****************************************************
711 <patched call position>
712 b9 00 00 00 00 mov $0x0,%ecx
713 8b 40 14 mov 0x14(%eax),%eax
714 8b 51 18 mov 0x18(%ecx),%edx
715 8b 49 14 mov 0x14(%ecx),%ecx
717 *******************************************************************************/
719 bool patcher_instanceof_class(patchref_t *pr)
722 constant_classref *cr;
725 /* get stuff from the stack */
728 cr = (constant_classref *) pr->ref;
730 /* get the fieldinfo */
732 if (!(c = resolve_classref_eager(cr)))
735 PATCH_BACK_ORIGINAL_MCODE;
737 /* if we show disassembly, we have to skip the nop's */
740 ra = ra + PATCHER_CALL_SIZE;
742 /* patch super class' vftbl */
744 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
751 * These are local overrides for various environment variables in Emacs.
752 * Please do not remove this and leave it at the end of the file, where
753 * Emacs will automagically detect them.
754 * ---------------------------------------------------------------------
757 * indent-tabs-mode: t
761 * vim:noexpandtab:sw=4:ts=4: