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 bool patcher_resolve_native_function(patchref_t *pr)
275 /* get stuff from the stack */
277 m = (methodinfo *) pr->ref;
278 datap = (u1 *) pr->datap;
280 /* resolve native function */
282 if (!(f = native_resolve_function(m)))
285 PATCH_BACK_ORIGINAL_MCODE;
287 /* patch native function pointer */
289 *((ptrint *) datap) = (ptrint) f;
291 /* synchronize data cache */
293 md_dcacheflush(datap, SIZEOF_VOID_P);
299 /* patcher_get_putstatic *******************************************************
303 <patched call position>
304 816dffc8 lwz r11,-56(r13)
305 80ab0000 lwz r5,0(r11)
307 *******************************************************************************/
309 bool patcher_get_putstatic(patchref_t *pr)
312 unresolved_field *uf;
316 /* get stuff from the stack */
319 uf = (unresolved_field *) pr->ref;
320 datap = (u1 *) pr->datap;
322 /* get the fieldinfo */
324 if (!(fi = resolve_field_eager(uf)))
327 /* check if the field's class is initialized */
329 if (!(fi->class->state & CLASS_INITIALIZED))
330 if (!initialize_class(fi->class))
333 PATCH_BACK_ORIGINAL_MCODE;
335 /* patch the field value's address */
337 *((intptr_t *) datap) = (intptr_t) fi->value;
339 /* synchronize data cache */
341 md_dcacheflush(datap, SIZEOF_VOID_P);
347 /* patcher_get_putfield ********************************************************
351 <patched call position>
352 811f0014 lwz r8,20(r31)
354 *******************************************************************************/
356 bool patcher_get_putfield(patchref_t *pr)
359 unresolved_field *uf;
364 uf = (unresolved_field *) pr->ref;
366 /* get the fieldinfo */
368 if (!(fi = resolve_field_eager(uf)))
371 PATCH_BACK_ORIGINAL_MCODE;
373 /* if we show NOPs, we have to skip them */
378 /* patch the field's offset */
380 if (IS_LNG_TYPE(fi->type)) {
381 /* If the field has type long, we have to patch two
382 instructions. But we have to check which instruction
383 is first. We do that with the offset of the first
386 disp = *((u4 *) (ra + 0 * 4));
389 *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
390 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
391 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
394 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
395 *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
396 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
400 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
402 /* synchronize instruction cache */
404 md_icacheflush(ra + 0 * 4, 2 * 4);
410 /* patcher_invokestatic_special ************************************************
414 <patched call position>
415 81adffd8 lwz r13,-40(r13)
419 ******************************************************************************/
421 bool patcher_invokestatic_special(patchref_t *pr)
423 unresolved_method *um;
427 /* get stuff from the stack */
429 um = (unresolved_method *) pr->ref;
430 datap = (u1 *) pr->datap;
432 /* get the fieldinfo */
434 if (!(m = resolve_method_eager(um)))
437 PATCH_BACK_ORIGINAL_MCODE;
439 /* patch stubroutine */
441 *((ptrint *) datap) = (ptrint) m->stubroutine;
443 /* synchronize data cache */
445 md_dcacheflush(datap, SIZEOF_VOID_P);
451 /* patcher_invokevirtual *******************************************************
455 <patched call position>
456 81830000 lwz r12,0(r3)
457 81ac0088 lwz r13,136(r12)
461 *******************************************************************************/
463 bool patcher_invokevirtual(patchref_t *pr)
466 unresolved_method *um;
470 /* get stuff from the stack */
473 um = (unresolved_method *) pr->ref;
475 /* get the fieldinfo */
477 if (!(m = resolve_method_eager(um)))
480 PATCH_BACK_ORIGINAL_MCODE;
482 /* if we show NOPs, we have to skip them */
487 /* patch vftbl index */
489 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
491 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
493 /* synchronize instruction cache */
495 md_icacheflush(ra + 1 * 4, 1 * 4);
501 /* patcher_invokeinterface *****************************************************
505 <patched call position>
506 81830000 lwz r12,0(r3)
507 818cffd0 lwz r12,-48(r12)
508 81ac000c lwz r13,12(r12)
512 *******************************************************************************/
514 bool patcher_invokeinterface(patchref_t *pr)
517 unresolved_method *um;
521 /* get stuff from the stack */
524 um = (unresolved_method *) pr->ref;
526 /* get the fieldinfo */
528 if (!(m = resolve_method_eager(um)))
531 PATCH_BACK_ORIGINAL_MCODE;
533 /* if we show NOPs, we have to skip them */
538 /* patch interfacetable index */
540 disp = OFFSET(vftbl_t, interfacetable[0]) -
541 sizeof(methodptr*) * m->class->index;
543 /* XXX TWISTI: check displacement */
545 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
547 /* patch method offset */
549 disp = sizeof(methodptr) * (m - m->class->methods);
551 /* XXX TWISTI: check displacement */
553 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
555 /* synchronize instruction cache */
557 md_icacheflush(ra + 1 * 4, 2 * 4);
563 /* patcher_checkcast_interface *************************************************
567 <patched call position>
568 81870000 lwz r12,0(r7)
569 800c0010 lwz r0,16(r12)
570 34000000 addic. r0,r0,0
571 41810008 bgt- 0x014135d8
572 83c00003 lwz r30,3(0)
573 800c0000 lwz r0,0(r12)
575 *******************************************************************************/
577 bool patcher_checkcast_interface(patchref_t *pr)
580 constant_classref *cr;
584 /* get stuff from the stack */
587 cr = (constant_classref *) pr->ref;
589 /* get the fieldinfo */
591 if (!(c = resolve_classref_eager(cr)))
594 PATCH_BACK_ORIGINAL_MCODE;
596 /* if we show NOPs, we have to skip them */
601 /* patch super class index */
605 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
607 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
609 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
611 /* synchronize instruction cache */
613 md_icacheflush(ra + 2 * 4, 4 * 4);
619 /* patcher_instanceof_interface ************************************************
623 <patched call position>
624 81870000 lwz r12,0(r7)
625 800c0010 lwz r0,16(r12)
626 34000000 addic. r0,r0,0
627 41810008 bgt- 0x014135d8
628 83c00003 lwz r30,3(0)
629 800c0000 lwz r0,0(r12)
631 *******************************************************************************/
633 bool patcher_instanceof_interface(patchref_t *pr)
636 constant_classref *cr;
640 /* get stuff from the stack */
643 cr = (constant_classref *) pr->ref;
645 /* get the fieldinfo */
647 if (!(c = resolve_classref_eager(cr)))
650 PATCH_BACK_ORIGINAL_MCODE;
652 /* if we show NOPs, we have to skip them */
657 /* patch super class index */
661 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
663 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
665 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
667 /* synchronize instruction cache */
669 md_icacheflush(ra + 2 * 4, 3 * 4);
676 * These are local overrides for various environment variables in Emacs.
677 * Please do not remove this and leave it at the end of the file, where
678 * Emacs will automagically detect them.
679 * ---------------------------------------------------------------------
682 * indent-tabs-mode: t
686 * vim:noexpandtab:sw=4:ts=4: