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 8286 2007-08-10 10:46:17Z michi $
37 #include "mm/memory.h"
38 #include "native/native.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/md.h"
46 #include "vm/jit/methodheader.h"
47 #include "vm/jit/patcher-common.h"
48 #include "vm/jit/stacktrace.h"
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vm/resolve.h"
54 #include "vmcore/references.h"
57 #define PATCH_BACK_ORIGINAL_MCODE \
58 *((u4 *) pr->mpc) = (u4) pr->mcode; \
59 md_icacheflush((u1 *) pr->mpc, 4);
62 /* patcher_initialize_class ****************************************************
64 Initalizes a given classinfo pointer. This function does not patch
67 *******************************************************************************/
69 bool patcher_initialize_class(patchref_t *pr)
73 /* get stuff from the stack */
75 c = (classinfo *) pr->ref;
77 /* check if the class is initialized */
79 if (!(c->state & CLASS_INITIALIZED))
80 if (!initialize_class(c))
83 PATCH_BACK_ORIGINAL_MCODE;
89 /* patcher_resolve_class *******************************************************
91 Resolves a given unresolved_class pointer. This function does not
94 *******************************************************************************/
96 #ifdef ENABLE_VERIFIER
97 bool patcher_resolve_class(patchref_t *pr)
101 /* get stuff from the stack */
103 uc = (unresolved_class *) pr->ref;
105 /* resolve the class and check subtype constraints */
107 if (!resolve_class_eager_no_access_check(uc))
110 PATCH_BACK_ORIGINAL_MCODE;
114 #endif /* ENABLE_VERIFIER */
117 /* patcher_resolve_classref_to_classinfo ***************************************
121 <patched call postition>
122 806dffc4 lwz r3,-60(r13)
123 81adffc0 lwz r13,-64(r13)
130 <patched call position>
131 808dffc0 lwz r4,-64(r13)
132 38a10038 addi r5,r1,56
133 81adffbc lwz r13,-68(r13)
140 <patched call position>
141 808dffd8 lwz r4,-40(r13)
142 81adffd4 lwz r13,-44(r13)
146 *******************************************************************************/
148 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
150 constant_classref *cr;
154 /* get stuff from the stack */
156 cr = (constant_classref *) pr->ref;
157 datap = (u1 *) pr->datap;
159 /* get the classinfo */
161 if (!(c = resolve_classref_eager(cr)))
164 PATCH_BACK_ORIGINAL_MCODE;
166 /* patch the classinfo pointer */
168 *((ptrint *) datap) = (ptrint) c;
170 /* synchronize data cache */
172 md_dcacheflush(datap, SIZEOF_VOID_P);
178 /* patcher_resolve_classref_to_vftbl *******************************************
182 <patched call position>
183 81870000 lwz r12,0(r7)
184 800c0014 lwz r0,20(r12)
185 818dff78 lwz r12,-136(r13)
190 <patched call position>
191 817d0000 lwz r11,0(r29)
192 818dff8c lwz r12,-116(r13)
194 *******************************************************************************/
196 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
198 constant_classref *cr;
202 /* get stuff from the stack */
204 cr = (constant_classref *) pr->ref;
205 datap = (u1 *) pr->datap;
207 /* get the fieldinfo */
209 if (!(c = resolve_classref_eager(cr)))
212 PATCH_BACK_ORIGINAL_MCODE;
214 /* patch super class' vftbl */
216 *((ptrint *) datap) = (ptrint) c->vftbl;
218 /* synchronize data cache */
220 md_dcacheflush(datap, SIZEOF_VOID_P);
226 /* patcher_resolve_classref_to_flags *******************************************
228 CHECKCAST/INSTANCEOF:
230 <patched call position>
231 818dff7c lwz r12,-132(r13)
233 *******************************************************************************/
235 bool patcher_resolve_classref_to_flags(patchref_t *pr)
237 constant_classref *cr;
241 /* get stuff from the stack */
243 cr = (constant_classref *) pr->ref;
244 datap = (u1 *) pr->datap;
246 /* get the fieldinfo */
248 if (!(c = resolve_classref_eager(cr)))
251 PATCH_BACK_ORIGINAL_MCODE;
253 /* patch class flags */
255 *((s4 *) datap) = (s4) c->flags;
257 /* synchronize data cache */
259 md_dcacheflush(datap, SIZEOF_VOID_P);
265 /* patcher_resolve_native_function *********************************************
269 *******************************************************************************/
271 #if !defined(WITH_STATIC_CLASSPATH)
272 bool patcher_resolve_native_function(patchref_t *pr)
278 /* get stuff from the stack */
280 m = (methodinfo *) pr->ref;
281 datap = (u1 *) pr->datap;
283 /* resolve native function */
285 if (!(f = native_resolve_function(m)))
288 PATCH_BACK_ORIGINAL_MCODE;
290 /* patch native function pointer */
292 *((ptrint *) datap) = (ptrint) f;
294 /* synchronize data cache */
296 md_dcacheflush(datap, SIZEOF_VOID_P);
300 #endif /* !defined(WITH_STATIC_CLASSPATH) */
303 /* patcher_get_putstatic *******************************************************
307 <patched call position>
308 816dffc8 lwz r11,-56(r13)
309 80ab0000 lwz r5,0(r11)
311 *******************************************************************************/
313 bool patcher_get_putstatic(patchref_t *pr)
316 unresolved_field *uf;
320 /* get stuff from the stack */
323 uf = (unresolved_field *) pr->ref;
324 datap = (u1 *) pr->datap;
326 /* get the fieldinfo */
328 if (!(fi = resolve_field_eager(uf)))
331 /* check if the field's class is initialized */
333 if (!(fi->class->state & CLASS_INITIALIZED))
334 if (!initialize_class(fi->class))
337 PATCH_BACK_ORIGINAL_MCODE;
339 /* patch the field value's address */
341 *((intptr_t *) datap) = (intptr_t) fi->value;
343 /* synchronize data cache */
345 md_dcacheflush(datap, SIZEOF_VOID_P);
351 /* patcher_get_putfield ********************************************************
355 <patched call position>
356 811f0014 lwz r8,20(r31)
358 *******************************************************************************/
360 bool patcher_get_putfield(patchref_t *pr)
363 unresolved_field *uf;
368 uf = (unresolved_field *) pr->ref;
370 /* get the fieldinfo */
372 if (!(fi = resolve_field_eager(uf)))
375 PATCH_BACK_ORIGINAL_MCODE;
377 /* if we show NOPs, we have to skip them */
382 /* patch the field's offset */
384 if (IS_LNG_TYPE(fi->type)) {
385 /* If the field has type long, we have to patch two
386 instructions. But we have to check which instruction
387 is first. We do that with the offset of the first
390 disp = *((u4 *) (ra + 0 * 4));
393 *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
394 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
395 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
398 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
399 *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
400 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
404 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
406 /* synchronize instruction cache */
408 md_icacheflush(ra + 0 * 4, 2 * 4);
414 /* patcher_invokestatic_special ************************************************
418 <patched call position>
419 81adffd8 lwz r13,-40(r13)
423 ******************************************************************************/
425 bool patcher_invokestatic_special(patchref_t *pr)
427 unresolved_method *um;
431 /* get stuff from the stack */
433 um = (unresolved_method *) pr->ref;
434 datap = (u1 *) pr->datap;
436 /* get the fieldinfo */
438 if (!(m = resolve_method_eager(um)))
441 PATCH_BACK_ORIGINAL_MCODE;
443 /* patch stubroutine */
445 *((ptrint *) datap) = (ptrint) m->stubroutine;
447 /* synchronize data cache */
449 md_dcacheflush(datap, SIZEOF_VOID_P);
455 /* patcher_invokevirtual *******************************************************
459 <patched call position>
460 81830000 lwz r12,0(r3)
461 81ac0088 lwz r13,136(r12)
465 *******************************************************************************/
467 bool patcher_invokevirtual(patchref_t *pr)
470 unresolved_method *um;
474 /* get stuff from the stack */
477 um = (unresolved_method *) pr->ref;
479 /* get the fieldinfo */
481 if (!(m = resolve_method_eager(um)))
484 PATCH_BACK_ORIGINAL_MCODE;
486 /* if we show NOPs, we have to skip them */
491 /* patch vftbl index */
493 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
495 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
497 /* synchronize instruction cache */
499 md_icacheflush(ra + 1 * 4, 1 * 4);
505 /* patcher_invokeinterface *****************************************************
509 <patched call position>
510 81830000 lwz r12,0(r3)
511 818cffd0 lwz r12,-48(r12)
512 81ac000c lwz r13,12(r12)
516 *******************************************************************************/
518 bool patcher_invokeinterface(patchref_t *pr)
521 unresolved_method *um;
525 /* get stuff from the stack */
528 um = (unresolved_method *) pr->ref;
530 /* get the fieldinfo */
532 if (!(m = resolve_method_eager(um)))
535 PATCH_BACK_ORIGINAL_MCODE;
537 /* if we show NOPs, we have to skip them */
542 /* patch interfacetable index */
544 disp = OFFSET(vftbl_t, interfacetable[0]) -
545 sizeof(methodptr*) * m->class->index;
547 /* XXX TWISTI: check displacement */
549 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
551 /* patch method offset */
553 disp = sizeof(methodptr) * (m - m->class->methods);
555 /* XXX TWISTI: check displacement */
557 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
559 /* synchronize instruction cache */
561 md_icacheflush(ra + 1 * 4, 2 * 4);
567 /* patcher_checkcast_interface *************************************************
571 <patched call position>
572 81870000 lwz r12,0(r7)
573 800c0010 lwz r0,16(r12)
574 34000000 addic. r0,r0,0
575 41810008 bgt- 0x014135d8
576 83c00003 lwz r30,3(0)
577 800c0000 lwz r0,0(r12)
579 *******************************************************************************/
581 bool patcher_checkcast_interface(patchref_t *pr)
584 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 NOPs, we have to skip them */
605 /* patch super class index */
609 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
611 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
613 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
615 /* synchronize instruction cache */
617 md_icacheflush(ra + 2 * 4, 4 * 4);
623 /* patcher_instanceof_interface ************************************************
627 <patched call position>
628 81870000 lwz r12,0(r7)
629 800c0010 lwz r0,16(r12)
630 34000000 addic. r0,r0,0
631 41810008 bgt- 0x014135d8
632 83c00003 lwz r30,3(0)
633 800c0000 lwz r0,0(r12)
635 *******************************************************************************/
637 bool patcher_instanceof_interface(patchref_t *pr)
640 constant_classref *cr;
644 /* get stuff from the stack */
647 cr = (constant_classref *) pr->ref;
649 /* get the fieldinfo */
651 if (!(c = resolve_classref_eager(cr)))
654 PATCH_BACK_ORIGINAL_MCODE;
656 /* if we show NOPs, we have to skip them */
661 /* patch super class index */
665 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
667 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
669 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
671 /* synchronize instruction cache */
673 md_icacheflush(ra + 2 * 4, 3 * 4);
680 * These are local overrides for various environment variables in Emacs.
681 * Please do not remove this and leave it at the end of the file, where
682 * Emacs will automagically detect them.
683 * ---------------------------------------------------------------------
686 * indent-tabs-mode: t
690 * vim:noexpandtab:sw=4:ts=4: