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 7596 2007-03-28 21:05:53Z twisti $
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/patcher.h"
45 #include "vm/jit/md.h"
46 #include "vm/jit/methodheader.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 /* patcher_wrapper *************************************************************
58 Wrapper for all patchers. It also creates the stackframe info
61 If the return value of the patcher function is false, it gets the
62 exception object, clears the exception pointer and returns the
65 *******************************************************************************/
67 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
77 /* define the patcher function */
79 bool (*patcher_function)(u1 *);
83 /* get stuff from the stack */
85 xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
86 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
87 f = (functionptr) *((ptrint *) (sp + 0 * 4));
89 /* Correct RA is calculated in codegen.c and stored in the patcher
90 stub stack. There's no need to adjust xpc. */
92 /* store PV into the patcher function position */
94 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
96 /* cast the passed function to a patcher function */
98 patcher_function = (bool (*)(u1 *)) (ptrint) f;
100 /* enter a monitor on the patching position */
102 PATCHER_MONITORENTER;
104 /* create the stackframeinfo */
106 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
108 /* call the proper patcher function */
110 result = (patcher_function)(sp);
112 /* remove the stackframeinfo */
114 stacktrace_remove_stackframeinfo(&sfi);
116 /* check for return value and exit accordingly */
118 if (result == false) {
119 e = exceptions_get_and_clear_exception();
126 /* patch back original code */
128 mcode = *((u4 *) (sp + 3 * 4));
130 *((u4 *) xpc) = mcode;
132 /* synchronize instruction cache */
134 md_icacheflush(xpc, 4);
136 PATCHER_MARK_PATCHED_MONITOREXIT;
142 /* patcher_initialize_class ****************************************************
144 Initalizes a given classinfo pointer. This function does not patch
147 *******************************************************************************/
149 bool patcher_initialize_class(u1 *sp)
153 /* get stuff from the stack */
155 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
157 /* check if the class is initialized */
159 if (!(c->state & CLASS_INITIALIZED))
160 if (!initialize_class(c))
167 /* patcher_resolve_class *******************************************************
169 Resolves a given unresolved_class pointer. This function does not
172 *******************************************************************************/
174 #ifdef ENABLE_VERIFIER
175 bool patcher_resolve_class(u1 *sp)
177 unresolved_class *uc;
179 /* get stuff from the stack */
181 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
183 /* resolve the class and check subtype constraints */
185 if (!resolve_class_eager_no_access_check(uc))
190 #endif /* ENABLE_VERIFIER */
193 /* patcher_resolve_classref_to_classinfo ***************************************
197 <patched call postition>
198 806dffc4 lwz r3,-60(r13)
199 81adffc0 lwz r13,-64(r13)
206 <patched call position>
207 808dffc0 lwz r4,-64(r13)
208 38a10038 addi r5,r1,56
209 81adffbc lwz r13,-68(r13)
216 <patched call position>
217 808dffd8 lwz r4,-40(r13)
218 81adffd4 lwz r13,-44(r13)
222 *******************************************************************************/
224 bool patcher_resolve_classref_to_classinfo(u1 *sp)
226 constant_classref *cr;
231 /* get stuff from the stack */
233 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
234 disp = *((s4 *) (sp + 1 * 4));
235 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
237 /* get the classinfo */
239 if (!(c = resolve_classref_eager(cr)))
242 /* patch the classinfo pointer */
244 *((ptrint *) (pv + disp)) = (ptrint) c;
246 /* synchronize data cache */
248 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
254 /* patcher_resolve_classref_to_vftbl *******************************************
258 <patched call position>
259 81870000 lwz r12,0(r7)
260 800c0014 lwz r0,20(r12)
261 818dff78 lwz r12,-136(r13)
266 <patched call position>
267 817d0000 lwz r11,0(r29)
268 818dff8c lwz r12,-116(r13)
270 *******************************************************************************/
272 bool patcher_resolve_classref_to_vftbl(u1 *sp)
274 constant_classref *cr;
279 /* get stuff from the stack */
281 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
282 disp = *((s4 *) (sp + 1 * 4));
283 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
285 /* get the fieldinfo */
287 if (!(c = resolve_classref_eager(cr)))
290 /* patch super class' vftbl */
292 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
294 /* synchronize data cache */
296 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
302 /* patcher_resolve_classref_to_flags *******************************************
304 CHECKCAST/INSTANCEOF:
306 <patched call position>
307 818dff7c lwz r12,-132(r13)
309 *******************************************************************************/
311 bool patcher_resolve_classref_to_flags(u1 *sp)
313 constant_classref *cr;
318 /* get stuff from the stack */
320 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
321 disp = *((s4 *) (sp + 1 * 4));
322 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
324 /* get the fieldinfo */
326 if (!(c = resolve_classref_eager(cr)))
329 /* patch class flags */
331 *((s4 *) (pv + disp)) = (s4) c->flags;
333 /* synchronize data cache */
335 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
341 /* patcher_resolve_native_function *********************************************
345 *******************************************************************************/
347 #if !defined(WITH_STATIC_CLASSPATH)
348 bool patcher_resolve_native_function(u1 *sp)
355 /* get stuff from the stack */
357 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
358 disp = *((s4 *) (sp + 1 * 4));
359 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
361 /* resolve native function */
363 if (!(f = native_resolve_function(m)))
366 /* patch native function pointer */
368 *((ptrint *) (pv + disp)) = (ptrint) f;
370 /* synchronize data cache */
372 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
376 #endif /* !defined(WITH_STATIC_CLASSPATH) */
379 /* patcher_get_putstatic *******************************************************
383 <patched call position>
384 816dffc8 lwz r11,-56(r13)
385 80ab0000 lwz r5,0(r11)
387 *******************************************************************************/
389 bool patcher_get_putstatic(u1 *sp)
393 unresolved_field *uf;
398 /* get stuff from the stack */
400 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
401 mcode = *((u4 *) (sp + 3 * 4));
402 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
403 disp = *((s4 *) (sp + 1 * 4));
404 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
406 /* get the fieldinfo */
408 if (!(fi = resolve_field_eager(uf)))
411 /* check if the field's class is initialized */
413 if (!(fi->class->state & CLASS_INITIALIZED))
414 if (!initialize_class(fi->class))
417 /* patch the field value's address */
419 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
421 /* synchronize data cache */
423 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
429 /* patcher_get_putfield ********************************************************
433 <patched call position>
434 811f0014 lwz r8,20(r31)
436 *******************************************************************************/
438 bool patcher_get_putfield(u1 *sp)
441 unresolved_field *uf;
446 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
447 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
448 pv = (u1 *) *((ptrint *) (sp + 1 * 4));
450 /* get the fieldinfo */
452 if (!(fi = resolve_field_eager(uf)))
455 /* if we show NOPs, we have to skip them */
458 /* patch the field's offset */
460 if (IS_LNG_TYPE(fi->type)) {
461 /* If the field has type long, we have to patch two
462 instructions. But we have to check which instruction
463 is first. We do that with the offset of the first
466 disp = *((u4 *) (ra + 1 * 4));
469 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
470 *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
473 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
474 *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
478 *((u4 *) (ra + 1 * 4)) |= (s2) (fi->offset & 0x0000ffff);
481 if (IS_LNG_TYPE(fi->type)) {
483 disp = *((u4 *) (sp + 3 * 4));
485 /* We patch the first instruction in the patcher stub
486 stack and the second in the code. The first
487 instruction is patched back later in
491 *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
492 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
495 *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
496 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
500 *((u4 *) (sp + 3 * 4)) |= (s2) (fi->offset & 0x0000ffff);
503 /* synchronize instruction cache */
505 md_icacheflush(ra + 1 * 4, 2 * 4);
511 /* patcher_invokestatic_special ************************************************
515 <patched call position>
516 81adffd8 lwz r13,-40(r13)
520 ******************************************************************************/
522 bool patcher_invokestatic_special(u1 *sp)
524 unresolved_method *um;
529 /* get stuff from the stack */
531 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
532 disp = *((s4 *) (sp + 1 * 4));
533 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
535 /* get the fieldinfo */
537 if (!(m = resolve_method_eager(um)))
540 /* patch stubroutine */
542 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
544 /* synchronize data cache */
546 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
552 /* patcher_invokevirtual *******************************************************
556 <patched call position>
557 81830000 lwz r12,0(r3)
558 81ac0088 lwz r13,136(r12)
562 *******************************************************************************/
564 bool patcher_invokevirtual(u1 *sp)
567 unresolved_method *um;
571 /* get stuff from the stack */
573 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
574 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
576 /* get the fieldinfo */
578 if (!(m = resolve_method_eager(um)))
581 /* if we show NOPs, we have to skip them */
586 /* patch vftbl index */
588 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
590 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
592 /* synchronize instruction cache */
594 md_icacheflush(ra + 1 * 4, 1 * 4);
600 /* patcher_invokeinterface *****************************************************
604 <patched call position>
605 81830000 lwz r12,0(r3)
606 818cffd0 lwz r12,-48(r12)
607 81ac000c lwz r13,12(r12)
611 *******************************************************************************/
613 bool patcher_invokeinterface(u1 *sp)
616 unresolved_method *um;
620 /* get stuff from the stack */
622 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
623 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
625 /* get the fieldinfo */
627 if (!(m = resolve_method_eager(um)))
630 /* if we show NOPs, we have to skip them */
635 /* patch interfacetable index */
637 disp = OFFSET(vftbl_t, interfacetable[0]) -
638 sizeof(methodptr*) * m->class->index;
640 /* XXX TWISTI: check displacement */
642 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
644 /* patch method offset */
646 disp = sizeof(methodptr) * (m - m->class->methods);
648 /* XXX TWISTI: check displacement */
650 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
652 /* synchronize instruction cache */
654 md_icacheflush(ra + 1 * 4, 2 * 4);
660 /* patcher_checkcast_interface *************************************************
664 <patched call position>
665 81870000 lwz r12,0(r7)
666 800c0010 lwz r0,16(r12)
667 34000000 addic. r0,r0,0
668 41810008 bgt- 0x014135d8
669 83c00003 lwz r30,3(0)
670 800c0000 lwz r0,0(r12)
672 *******************************************************************************/
674 bool patcher_checkcast_interface(u1 *sp)
677 constant_classref *cr;
681 /* get stuff from the stack */
683 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
684 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
686 /* get the fieldinfo */
688 if (!(c = resolve_classref_eager(cr)))
691 /* if we show NOPs, we have to skip them */
696 /* patch super class index */
700 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
702 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
704 *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
706 /* synchronize instruction cache */
708 md_icacheflush(ra + 2 * 4, 4 * 4);
714 /* patcher_instanceof_interface ************************************************
718 <patched call position>
719 81870000 lwz r12,0(r7)
720 800c0010 lwz r0,16(r12)
721 34000000 addic. r0,r0,0
722 41810008 bgt- 0x014135d8
723 83c00003 lwz r30,3(0)
724 800c0000 lwz r0,0(r12)
726 *******************************************************************************/
728 bool patcher_instanceof_interface(u1 *sp)
731 constant_classref *cr;
735 /* get stuff from the stack */
737 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
738 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
740 /* get the fieldinfo */
742 if (!(c = resolve_classref_eager(cr)))
745 /* if we show NOPs, we have to skip them */
750 /* patch super class index */
754 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
756 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
758 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
760 /* synchronize instruction cache */
762 md_icacheflush(ra + 2 * 4, 3 * 4);
769 * These are local overrides for various environment variables in Emacs.
770 * Please do not remove this and leave it at the end of the file, where
771 * Emacs will automagically detect them.
772 * ---------------------------------------------------------------------
775 * indent-tabs-mode: t
779 * vim:noexpandtab:sw=4:ts=4: