1 /* src/vm/jit/powerpc/patcher.c - PowerPC 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 8216 2007-07-19 13:51:21Z michi $
36 #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/asmpart.h"
44 #include "vm/jit/md.h"
45 #include "vm/jit/methodheader.h"
46 #include "vm/jit/patcher-common.h"
47 #include "vm/jit/stacktrace.h"
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vm/resolve.h"
53 #include "vmcore/references.h"
56 #define PATCH_BACK_ORIGINAL_MCODE \
57 *((u4 *) pr->mpc) = (u4) pr->mcode; \
58 md_icacheflush((u1 *) pr->mpc, 4);
61 /* patcher_initialize_class ****************************************************
63 Initalizes a given classinfo pointer. This function does not patch
66 *******************************************************************************/
68 bool patcher_initialize_class(patchref_t *pr)
72 /* get stuff from the stack */
74 c = (classinfo *) pr->ref;
76 /* check if the class is initialized */
78 if (!(c->state & CLASS_INITIALIZED))
79 if (!initialize_class(c))
82 PATCH_BACK_ORIGINAL_MCODE;
88 /* patcher_resolve_class *******************************************************
90 Resolves a given unresolved_class pointer. This function does not
93 *******************************************************************************/
95 #ifdef ENABLE_VERIFIER
96 bool patcher_resolve_class(patchref_t *pr)
100 /* get stuff from the stack */
102 uc = (unresolved_class *) pr->ref;
104 /* resolve the class and check subtype constraints */
106 if (!resolve_class_eager_no_access_check(uc))
109 PATCH_BACK_ORIGINAL_MCODE;
113 #endif /* ENABLE_VERIFIER */
116 /* patcher_resolve_classref_to_classinfo ***************************************
120 <patched call postition>
121 806dffc4 lwz r3,-60(r13)
122 81adffc0 lwz r13,-64(r13)
129 <patched call position>
130 808dffc0 lwz r4,-64(r13)
131 38a10038 addi r5,r1,56
132 81adffbc lwz r13,-68(r13)
139 <patched call position>
140 808dffd8 lwz r4,-40(r13)
141 81adffd4 lwz r13,-44(r13)
145 *******************************************************************************/
147 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
149 constant_classref *cr;
153 /* get stuff from the stack */
155 cr = (constant_classref *) pr->ref;
156 datap = (u1 *) pr->datap;
158 /* get the classinfo */
160 if (!(c = resolve_classref_eager(cr)))
163 PATCH_BACK_ORIGINAL_MCODE;
165 /* patch the classinfo pointer */
167 *((ptrint *) datap) = (ptrint) c;
169 /* synchronize data cache */
171 md_dcacheflush(datap, SIZEOF_VOID_P);
177 /* patcher_resolve_classref_to_vftbl *******************************************
181 <patched call position>
182 81870000 lwz r12,0(r7)
183 800c0014 lwz r0,20(r12)
184 818dff78 lwz r12,-136(r13)
189 <patched call position>
190 817d0000 lwz r11,0(r29)
191 818dff8c lwz r12,-116(r13)
193 *******************************************************************************/
195 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
197 constant_classref *cr;
201 /* get stuff from the stack */
203 cr = (constant_classref *) pr->ref;
204 datap = (u1 *) pr->datap;
206 /* get the fieldinfo */
208 if (!(c = resolve_classref_eager(cr)))
211 PATCH_BACK_ORIGINAL_MCODE;
213 /* patch super class' vftbl */
215 *((ptrint *) datap) = (ptrint) c->vftbl;
217 /* synchronize data cache */
219 md_dcacheflush(datap, SIZEOF_VOID_P);
225 /* patcher_resolve_classref_to_flags *******************************************
227 CHECKCAST/INSTANCEOF:
229 <patched call position>
230 818dff7c lwz r12,-132(r13)
232 *******************************************************************************/
234 bool patcher_resolve_classref_to_flags(patchref_t *pr)
236 constant_classref *cr;
240 /* get stuff from the stack */
242 cr = (constant_classref *) pr->ref;
243 datap = (u1 *) pr->datap;
245 /* get the fieldinfo */
247 if (!(c = resolve_classref_eager(cr)))
250 PATCH_BACK_ORIGINAL_MCODE;
252 /* patch class flags */
254 *((s4 *) datap) = (s4) c->flags;
256 /* synchronize data cache */
258 md_dcacheflush(datap, SIZEOF_VOID_P);
264 /* patcher_resolve_native_function *********************************************
268 *******************************************************************************/
270 #if !defined(WITH_STATIC_CLASSPATH)
271 bool patcher_resolve_native_function(patchref_t *pr)
277 /* get stuff from the stack */
279 m = (methodinfo *) pr->ref;
280 datap = (u1 *) pr->datap;
282 /* resolve native function */
284 if (!(f = native_resolve_function(m)))
287 PATCH_BACK_ORIGINAL_MCODE;
289 /* patch native function pointer */
291 *((ptrint *) datap) = (ptrint) f;
293 /* synchronize data cache */
295 md_dcacheflush(datap, SIZEOF_VOID_P);
299 #endif /* !defined(WITH_STATIC_CLASSPATH) */
302 /* patcher_get_putstatic *******************************************************
306 <patched call position>
307 816dffc8 lwz r11,-56(r13)
308 80ab0000 lwz r5,0(r11)
310 *******************************************************************************/
312 bool patcher_get_putstatic(patchref_t *pr)
315 unresolved_field *uf;
319 /* get stuff from the stack */
322 uf = (unresolved_field *) pr->ref;
323 datap = (u1 *) pr->datap;
325 /* get the fieldinfo */
327 if (!(fi = resolve_field_eager(uf)))
330 /* check if the field's class is initialized */
332 if (!(fi->class->state & CLASS_INITIALIZED))
333 if (!initialize_class(fi->class))
336 PATCH_BACK_ORIGINAL_MCODE;
338 /* patch the field value's address */
340 *((ptrint *) datap) = (ptrint) &(fi->value);
342 /* synchronize data cache */
344 md_dcacheflush(datap, SIZEOF_VOID_P);
350 /* patcher_get_putfield ********************************************************
354 <patched call position>
355 811f0014 lwz r8,20(r31)
357 *******************************************************************************/
359 bool patcher_get_putfield(patchref_t *pr)
362 unresolved_field *uf;
367 uf = (unresolved_field *) pr->ref;
369 /* get the fieldinfo */
371 if (!(fi = resolve_field_eager(uf)))
374 PATCH_BACK_ORIGINAL_MCODE;
376 /* if we show NOPs, we have to skip them */
381 /* patch the field's offset */
383 if (IS_LNG_TYPE(fi->type)) {
384 /* If the field has type long, we have to patch two
385 instructions. But we have to check which instruction
386 is first. We do that with the offset of the first
389 disp = *((u4 *) (ra + 0 * 4));
392 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
393 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
396 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
397 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
401 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
403 /* synchronize instruction cache */
405 md_icacheflush(ra + 0 * 4, 2 * 4);
411 /* patcher_invokestatic_special ************************************************
415 <patched call position>
416 81adffd8 lwz r13,-40(r13)
420 ******************************************************************************/
422 bool patcher_invokestatic_special(patchref_t *pr)
424 unresolved_method *um;
428 /* get stuff from the stack */
430 um = (unresolved_method *) pr->ref;
431 datap = (u1 *) pr->datap;
433 /* get the fieldinfo */
435 if (!(m = resolve_method_eager(um)))
438 PATCH_BACK_ORIGINAL_MCODE;
440 /* patch stubroutine */
442 *((ptrint *) datap) = (ptrint) m->stubroutine;
444 /* synchronize data cache */
446 md_dcacheflush(datap, SIZEOF_VOID_P);
452 /* patcher_invokevirtual *******************************************************
456 <patched call position>
457 81830000 lwz r12,0(r3)
458 81ac0088 lwz r13,136(r12)
462 *******************************************************************************/
464 bool patcher_invokevirtual(patchref_t *pr)
467 unresolved_method *um;
471 /* get stuff from the stack */
474 um = (unresolved_method *) pr->ref;
476 /* get the fieldinfo */
478 if (!(m = resolve_method_eager(um)))
481 PATCH_BACK_ORIGINAL_MCODE;
483 /* if we show NOPs, we have to skip them */
488 /* patch vftbl index */
490 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
492 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
494 /* synchronize instruction cache */
496 md_icacheflush(ra + 1 * 4, 1 * 4);
502 /* patcher_invokeinterface *****************************************************
506 <patched call position>
507 81830000 lwz r12,0(r3)
508 818cffd0 lwz r12,-48(r12)
509 81ac000c lwz r13,12(r12)
513 *******************************************************************************/
515 bool patcher_invokeinterface(patchref_t *pr)
518 unresolved_method *um;
522 /* get stuff from the stack */
525 um = (unresolved_method *) pr->ref;
527 /* get the fieldinfo */
529 if (!(m = resolve_method_eager(um)))
532 PATCH_BACK_ORIGINAL_MCODE;
534 /* if we show NOPs, we have to skip them */
539 /* patch interfacetable index */
541 disp = OFFSET(vftbl_t, interfacetable[0]) -
542 sizeof(methodptr*) * m->class->index;
544 /* XXX TWISTI: check displacement */
546 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
548 /* patch method offset */
550 disp = sizeof(methodptr) * (m - m->class->methods);
552 /* XXX TWISTI: check displacement */
554 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
556 /* synchronize instruction cache */
558 md_icacheflush(ra + 1 * 4, 2 * 4);
564 /* patcher_checkcast_interface *************************************************
568 <patched call position>
569 81870000 lwz r12,0(r7)
570 800c0010 lwz r0,16(r12)
571 34000000 addic. r0,r0,0
572 41810008 bgt- 0x014135d8
573 83c00003 lwz r30,3(0)
574 800c0000 lwz r0,0(r12)
576 *******************************************************************************/
578 bool patcher_checkcast_interface(patchref_t *pr)
581 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 NOPs, we have to skip them */
602 /* patch super class index */
606 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
608 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
610 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
612 /* synchronize instruction cache */
614 md_icacheflush(ra + 2 * 4, 4 * 4);
620 /* patcher_instanceof_interface ************************************************
624 <patched call position>
625 81870000 lwz r12,0(r7)
626 800c0010 lwz r0,16(r12)
627 34000000 addic. r0,r0,0
628 41810008 bgt- 0x014135d8
629 83c00003 lwz r30,3(0)
630 800c0000 lwz r0,0(r12)
632 *******************************************************************************/
634 bool patcher_instanceof_interface(patchref_t *pr)
637 constant_classref *cr;
641 /* get stuff from the stack */
644 cr = (constant_classref *) pr->ref;
646 /* get the fieldinfo */
648 if (!(c = resolve_classref_eager(cr)))
651 PATCH_BACK_ORIGINAL_MCODE;
653 /* if we show NOPs, we have to skip them */
658 /* patch super class index */
662 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
664 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
666 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
668 /* synchronize instruction cache */
670 md_icacheflush(ra + 2 * 4, 3 * 4);
677 * These are local overrides for various environment variables in Emacs.
678 * Please do not remove this and leave it at the end of the file, where
679 * Emacs will automagically detect them.
680 * ---------------------------------------------------------------------
683 * indent-tabs-mode: t
687 * vim:noexpandtab:sw=4:ts=4: