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
35 #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/asmpart.h"
43 #include "vm/jit/md.h"
44 #include "vm/jit/methodheader.h"
45 #include "vm/jit/patcher-common.h"
46 #include "vm/jit/stacktrace.h"
48 #include "vmcore/class.h"
49 #include "vmcore/field.h"
50 #include "vmcore/options.h"
51 #include "vm/resolve.h"
52 #include "vmcore/references.h"
55 #define PATCH_BACK_ORIGINAL_MCODE \
56 *((u4 *) pr->mpc) = (u4) pr->mcode; \
57 md_icacheflush((u1 *) pr->mpc, 4);
60 /* patcher_initialize_class ****************************************************
62 Initalizes a given classinfo pointer. This function does not patch
65 *******************************************************************************/
67 bool patcher_initialize_class(patchref_t *pr)
71 /* get stuff from the stack */
73 c = (classinfo *) pr->ref;
75 /* check if the class is initialized */
77 if (!(c->state & CLASS_INITIALIZED))
78 if (!initialize_class(c))
81 PATCH_BACK_ORIGINAL_MCODE;
87 /* patcher_resolve_class *******************************************************
89 Resolves a given unresolved_class pointer. This function does not
92 *******************************************************************************/
94 #ifdef ENABLE_VERIFIER
95 bool patcher_resolve_class(patchref_t *pr)
99 /* get stuff from the stack */
101 uc = (unresolved_class *) pr->ref;
103 /* resolve the class and check subtype constraints */
105 if (!resolve_class_eager_no_access_check(uc))
108 PATCH_BACK_ORIGINAL_MCODE;
112 #endif /* ENABLE_VERIFIER */
115 /* patcher_resolve_classref_to_classinfo ***************************************
119 <patched call postition>
120 806dffc4 lwz r3,-60(r13)
121 81adffc0 lwz r13,-64(r13)
128 <patched call position>
129 808dffc0 lwz r4,-64(r13)
130 38a10038 addi r5,r1,56
131 81adffbc lwz r13,-68(r13)
138 <patched call position>
139 808dffd8 lwz r4,-40(r13)
140 81adffd4 lwz r13,-44(r13)
144 *******************************************************************************/
146 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
148 constant_classref *cr;
152 /* get stuff from the stack */
154 cr = (constant_classref *) pr->ref;
155 datap = (u1 *) pr->datap;
157 /* get the classinfo */
159 if (!(c = resolve_classref_eager(cr)))
162 PATCH_BACK_ORIGINAL_MCODE;
164 /* patch the classinfo pointer */
166 *((ptrint *) datap) = (ptrint) c;
168 /* synchronize data cache */
170 md_dcacheflush(datap, SIZEOF_VOID_P);
176 /* patcher_resolve_classref_to_vftbl *******************************************
180 <patched call position>
181 81870000 lwz r12,0(r7)
182 800c0014 lwz r0,20(r12)
183 818dff78 lwz r12,-136(r13)
188 <patched call position>
189 817d0000 lwz r11,0(r29)
190 818dff8c lwz r12,-116(r13)
192 *******************************************************************************/
194 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
196 constant_classref *cr;
200 /* get stuff from the stack */
202 cr = (constant_classref *) pr->ref;
203 datap = (u1 *) pr->datap;
205 /* get the fieldinfo */
207 if (!(c = resolve_classref_eager(cr)))
210 PATCH_BACK_ORIGINAL_MCODE;
212 /* patch super class' vftbl */
214 *((ptrint *) datap) = (ptrint) c->vftbl;
216 /* synchronize data cache */
218 md_dcacheflush(datap, SIZEOF_VOID_P);
224 /* patcher_resolve_classref_to_flags *******************************************
226 CHECKCAST/INSTANCEOF:
228 <patched call position>
229 818dff7c lwz r12,-132(r13)
231 *******************************************************************************/
233 bool patcher_resolve_classref_to_flags(patchref_t *pr)
235 constant_classref *cr;
239 /* get stuff from the stack */
241 cr = (constant_classref *) pr->ref;
242 datap = (u1 *) pr->datap;
244 /* get the fieldinfo */
246 if (!(c = resolve_classref_eager(cr)))
249 PATCH_BACK_ORIGINAL_MCODE;
251 /* patch class flags */
253 *((s4 *) datap) = (s4) c->flags;
255 /* synchronize data cache */
257 md_dcacheflush(datap, SIZEOF_VOID_P);
263 /* patcher_resolve_native_function *********************************************
267 *******************************************************************************/
269 #if !defined(WITH_STATIC_CLASSPATH)
270 bool patcher_resolve_native_function(patchref_t *pr)
276 /* get stuff from the stack */
278 m = (methodinfo *) pr->ref;
279 datap = (u1 *) pr->datap;
281 /* resolve native function */
283 if (!(f = native_resolve_function(m)))
286 PATCH_BACK_ORIGINAL_MCODE;
288 /* patch native function pointer */
290 *((ptrint *) datap) = (ptrint) f;
292 /* synchronize data cache */
294 md_dcacheflush(datap, SIZEOF_VOID_P);
298 #endif /* !defined(WITH_STATIC_CLASSPATH) */
301 /* patcher_get_putstatic *******************************************************
305 <patched call position>
306 816dffc8 lwz r11,-56(r13)
307 80ab0000 lwz r5,0(r11)
309 *******************************************************************************/
311 bool patcher_get_putstatic(patchref_t *pr)
314 unresolved_field *uf;
318 /* get stuff from the stack */
321 uf = (unresolved_field *) pr->ref;
322 datap = (u1 *) pr->datap;
324 /* get the fieldinfo */
326 if (!(fi = resolve_field_eager(uf)))
329 /* check if the field's class is initialized */
331 if (!(fi->class->state & CLASS_INITIALIZED))
332 if (!initialize_class(fi->class))
335 PATCH_BACK_ORIGINAL_MCODE;
337 /* patch the field value's address */
339 *((intptr_t *) datap) = (intptr_t) fi->value;
341 /* synchronize data cache */
343 md_dcacheflush(datap, SIZEOF_VOID_P);
349 /* patcher_get_putfield ********************************************************
353 <patched call position>
354 811f0014 lwz r8,20(r31)
356 *******************************************************************************/
358 bool patcher_get_putfield(patchref_t *pr)
361 unresolved_field *uf;
366 uf = (unresolved_field *) pr->ref;
368 /* get the fieldinfo */
370 if (!(fi = resolve_field_eager(uf)))
373 PATCH_BACK_ORIGINAL_MCODE;
375 /* if we show NOPs, we have to skip them */
380 /* patch the field's offset */
382 if (IS_LNG_TYPE(fi->type)) {
383 /* If the field has type long, we have to patch two
384 instructions. But we have to check which instruction
385 is first. We do that with the offset of the first
388 disp = *((u4 *) (ra + 0 * 4));
391 *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
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)) &= 0xffff0000;
398 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
402 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
404 /* synchronize instruction cache */
406 md_icacheflush(ra + 0 * 4, 2 * 4);
412 /* patcher_invokestatic_special ************************************************
416 <patched call position>
417 81adffd8 lwz r13,-40(r13)
421 ******************************************************************************/
423 bool patcher_invokestatic_special(patchref_t *pr)
425 unresolved_method *um;
429 /* get stuff from the stack */
431 um = (unresolved_method *) pr->ref;
432 datap = (u1 *) pr->datap;
434 /* get the fieldinfo */
436 if (!(m = resolve_method_eager(um)))
439 PATCH_BACK_ORIGINAL_MCODE;
441 /* patch stubroutine */
443 *((ptrint *) datap) = (ptrint) m->stubroutine;
445 /* synchronize data cache */
447 md_dcacheflush(datap, SIZEOF_VOID_P);
453 /* patcher_invokevirtual *******************************************************
457 <patched call position>
458 81830000 lwz r12,0(r3)
459 81ac0088 lwz r13,136(r12)
463 *******************************************************************************/
465 bool patcher_invokevirtual(patchref_t *pr)
468 unresolved_method *um;
472 /* get stuff from the stack */
475 um = (unresolved_method *) pr->ref;
477 /* get the fieldinfo */
479 if (!(m = resolve_method_eager(um)))
482 PATCH_BACK_ORIGINAL_MCODE;
484 /* if we show NOPs, we have to skip them */
489 /* patch vftbl index */
491 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
493 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
495 /* synchronize instruction cache */
497 md_icacheflush(ra + 1 * 4, 1 * 4);
503 /* patcher_invokeinterface *****************************************************
507 <patched call position>
508 81830000 lwz r12,0(r3)
509 818cffd0 lwz r12,-48(r12)
510 81ac000c lwz r13,12(r12)
514 *******************************************************************************/
516 bool patcher_invokeinterface(patchref_t *pr)
519 unresolved_method *um;
523 /* get stuff from the stack */
526 um = (unresolved_method *) pr->ref;
528 /* get the fieldinfo */
530 if (!(m = resolve_method_eager(um)))
533 PATCH_BACK_ORIGINAL_MCODE;
535 /* if we show NOPs, we have to skip them */
540 /* patch interfacetable index */
542 disp = OFFSET(vftbl_t, interfacetable[0]) -
543 sizeof(methodptr*) * m->class->index;
545 /* XXX TWISTI: check displacement */
547 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
549 /* patch method offset */
551 disp = sizeof(methodptr) * (m - m->class->methods);
553 /* XXX TWISTI: check displacement */
555 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
557 /* synchronize instruction cache */
559 md_icacheflush(ra + 1 * 4, 2 * 4);
565 /* patcher_checkcast_interface *************************************************
569 <patched call position>
570 81870000 lwz r12,0(r7)
571 800c0010 lwz r0,16(r12)
572 34000000 addic. r0,r0,0
573 41810008 bgt- 0x014135d8
574 83c00003 lwz r30,3(0)
575 800c0000 lwz r0,0(r12)
577 *******************************************************************************/
579 bool patcher_checkcast_interface(patchref_t *pr)
582 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 NOPs, we have to skip them */
603 /* patch super class index */
607 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
609 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
611 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
613 /* synchronize instruction cache */
615 md_icacheflush(ra + 2 * 4, 4 * 4);
621 /* patcher_instanceof_interface ************************************************
625 <patched call position>
626 81870000 lwz r12,0(r7)
627 800c0010 lwz r0,16(r12)
628 34000000 addic. r0,r0,0
629 41810008 bgt- 0x014135d8
630 83c00003 lwz r30,3(0)
631 800c0000 lwz r0,0(r12)
633 *******************************************************************************/
635 bool patcher_instanceof_interface(patchref_t *pr)
638 constant_classref *cr;
642 /* get stuff from the stack */
645 cr = (constant_classref *) pr->ref;
647 /* get the fieldinfo */
649 if (!(c = resolve_classref_eager(cr)))
652 PATCH_BACK_ORIGINAL_MCODE;
654 /* if we show NOPs, we have to skip them */
659 /* patch super class index */
663 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
665 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
667 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
669 /* synchronize instruction cache */
671 md_icacheflush(ra + 2 * 4, 3 * 4);
678 * These are local overrides for various environment variables in Emacs.
679 * Please do not remove this and leave it at the end of the file, where
680 * Emacs will automagically detect them.
681 * ---------------------------------------------------------------------
684 * indent-tabs-mode: t
688 * vim:noexpandtab:sw=4:ts=4: