1 /* src/vm/jit/powerpc/patcher.c - PowerPC code patching functions
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: patcher.c 5081 2006-07-06 13:59:01Z tbfg $
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/resolve.h"
51 #include "vm/references.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54 #include "vm/jit/methodheader.h"
57 /* patcher_wrapper *************************************************************
59 Wrapper for all patchers. It also creates the stackframe info
62 If the return value of the patcher function is false, it gets the
63 exception object, clears the exception pointer and returns the
66 *******************************************************************************/
68 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 /* store PV into the patcher function position */
91 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
93 /* cast the passed function to a patcher function */
95 patcher_function = (bool (*)(u1 *)) (ptrint) f;
97 /* enter a monitor on the patching position */
101 /* create the stackframeinfo */
103 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
105 /* call the proper patcher function */
107 result = (patcher_function)(sp);
109 /* remove the stackframeinfo */
111 stacktrace_remove_stackframeinfo(&sfi);
113 /* check for return value and exit accordingly */
115 if (result == false) {
116 e = exceptions_get_and_clear_exception();
123 PATCHER_MARK_PATCHED_MONITOREXIT;
129 /* patcher_get_putstatic *******************************************************
133 <patched call position>
134 816dffc8 lwz r11,-56(r13)
135 80ab0000 lwz r5,0(r11)
137 *******************************************************************************/
139 bool patcher_get_putstatic(u1 *sp)
143 unresolved_field *uf;
148 /* get stuff from the stack */
150 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
151 mcode = *((u4 *) (sp + 3 * 4));
152 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
153 disp = *((s4 *) (sp + 1 * 4));
154 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
156 /* get the fieldinfo */
158 if (!(fi = resolve_field_eager(uf)))
161 /* check if the field's class is initialized */
163 if (!(fi->class->state & CLASS_INITIALIZED))
164 if (!initialize_class(fi->class))
167 /* patch back original code */
169 *((u4 *) ra) = mcode;
171 /* synchronize instruction cache */
173 md_icacheflush(ra, 4);
175 /* patch the field value's address */
177 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
179 /* synchronize data cache */
181 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
187 /* patcher_get_putfield ********************************************************
191 <patched call position>
192 811f0014 lwz r8,20(r31)
194 *******************************************************************************/
196 bool patcher_get_putfield(u1 *sp)
200 unresolved_field *uf;
204 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
205 mcode = *((u4 *) (sp + 3 * 4));
206 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
207 pv = (u1 *) *((ptrint *) (sp + 1 * 4));
209 /* get the fieldinfo */
211 if (!(fi = resolve_field_eager(uf)))
214 /* patch back original code */
216 *((u4 *) ra) = mcode;
218 /* if we show disassembly, we have to skip the nop */
220 if (opt_showdisassemble)
223 /* patch the field's offset */
225 if (fi->type == TYPE_LNG) {
228 /* If the field has type long, we have to patch two
229 instructions. But we have to check which instruction is
230 first. We do that with the offset of the first
233 disp = *((u4 *) (ra + 0));
235 #if WORDS_BIGENDIAN == 1
237 *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
238 *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
241 *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
242 *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
249 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
252 /* synchronize instruction cache */
254 md_icacheflush(ra, 8);
260 /* patcher_aconst **************************************************************
264 <patched call postition>
265 806dffc4 lwz r3,-60(r13)
266 81adffc0 lwz r13,-64(r13)
270 *******************************************************************************/
272 bool patcher_aconst(u1 *sp)
276 constant_classref *cr;
281 /* get stuff from the stack */
283 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
284 mcode = *((u4 *) (sp + 3 * 4));
285 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
286 disp = *((s4 *) (sp + 1 * 4));
287 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
289 /* get the classinfo */
291 if (!(c = resolve_classref_eager(cr)))
294 /* patch back original code */
296 *((u4 *) ra) = mcode;
298 /* synchronize instruction cache */
300 md_icacheflush(ra, 4);
302 /* patch the classinfo pointer */
304 *((ptrint *) (pv + disp)) = (ptrint) c;
306 /* synchronize data cache */
308 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
314 /* patcher_builtin_multianewarray **********************************************
318 <patched call position>
319 808dffc0 lwz r4,-64(r13)
320 38a10038 addi r5,r1,56
321 81adffbc lwz r13,-68(r13)
325 *******************************************************************************/
327 bool patcher_builtin_multianewarray(u1 *sp)
331 constant_classref *cr;
336 /* get stuff from the stack */
338 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
339 mcode = *((u4 *) (sp + 3 * 4));
340 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
341 disp = *((s4 *) (sp + 1 * 4));
342 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
344 /* get the classinfo */
346 if (!(c = resolve_classref_eager(cr)))
349 /* patch back original code */
351 *((u4 *) ra) = mcode;
353 /* synchronize instruction cache */
355 md_icacheflush(ra, 4);
357 /* patch the classinfo pointer */
359 *((ptrint *) (pv + disp)) = (ptrint) c;
361 /* synchronize data cache */
363 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
369 /* patcher_builtin_arraycheckcast **********************************************
373 <patched call position>
374 808dffd8 lwz r4,-40(r13)
375 81adffd4 lwz r13,-44(r13)
379 *******************************************************************************/
381 bool patcher_builtin_arraycheckcast(u1 *sp)
385 constant_classref *cr;
390 /* get stuff from the stack */
392 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
393 mcode = *((u4 *) (sp + 3 * 4));
394 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
395 disp = *((s4 *) (sp + 1 * 4));
396 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
398 /* get the classinfo */
400 if (!(c = resolve_classref_eager(cr)))
403 /* patch back original code */
405 *((u4 *) ra) = mcode;
407 /* synchronize instruction cache */
409 md_icacheflush(ra, 4);
411 /* patch the classinfo pointer */
413 *((ptrint *) (pv + disp)) = (ptrint) c;
415 /* synchronize data cache */
417 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
423 /* patcher_invokestatic_special ************************************************
427 <patched call position>
428 81adffd8 lwz r13,-40(r13)
432 ******************************************************************************/
434 bool patcher_invokestatic_special(u1 *sp)
438 unresolved_method *um;
443 /* get stuff from the stack */
445 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
446 mcode = *((u4 *) (sp + 3 * 4));
447 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
448 disp = *((s4 *) (sp + 1 * 4));
449 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
451 /* get the fieldinfo */
453 if (!(m = resolve_method_eager(um)))
456 /* patch back original code */
458 *((u4 *) ra) = mcode;
460 /* synchronize instruction cache */
462 md_icacheflush(ra, 4);
464 /* patch stubroutine */
466 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
468 /* synchronize data cache */
470 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
476 /* patcher_invokevirtual *******************************************************
480 <patched call position>
481 81830000 lwz r12,0(r3)
482 81ac0088 lwz r13,136(r12)
486 *******************************************************************************/
488 bool patcher_invokevirtual(u1 *sp)
492 unresolved_method *um;
496 /* get stuff from the stack */
498 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
499 mcode = *((u4 *) (sp + 3 * 4));
500 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
502 /* get the fieldinfo */
504 if (!(m = resolve_method_eager(um)))
507 /* patch back original code */
509 *((u4 *) ra) = mcode;
511 /* if we show disassembly, we have to skip the nop */
513 if (opt_showdisassemble)
516 /* patch vftbl index */
518 disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
520 *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
522 /* synchronize instruction cache */
524 md_icacheflush(ra, 2 * 4);
530 /* patcher_invokeinterface *****************************************************
534 <patched call position>
535 81830000 lwz r12,0(r3)
536 818cffd0 lwz r12,-48(r12)
537 81ac000c lwz r13,12(r12)
541 *******************************************************************************/
543 bool patcher_invokeinterface(u1 *sp)
547 unresolved_method *um;
551 /* get stuff from the stack */
553 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
554 mcode = *((u4 *) (sp + 3 * 4));
555 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
557 /* get the fieldinfo */
559 if (!(m = resolve_method_eager(um)))
562 /* patch back original code */
564 *((u4 *) ra) = mcode;
566 /* if we show disassembly, we have to skip the nop */
568 if (opt_showdisassemble)
571 /* patch interfacetable index */
573 disp = OFFSET(vftbl_t, interfacetable[0]) -
574 sizeof(methodptr*) * m->class->index;
576 /* XXX TWISTI: check displacement */
578 *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
580 /* patch method offset */
582 disp = sizeof(methodptr) * (m - m->class->methods);
584 /* XXX TWISTI: check displacement */
586 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
588 /* synchronize instruction cache */
590 md_icacheflush(ra, 3 * 4);
596 /* patcher_checkcast_instanceof_flags ******************************************
600 <patched call position>
601 818dff7c lwz r12,-132(r13)
603 *******************************************************************************/
605 bool patcher_checkcast_instanceof_flags(u1 *sp)
609 constant_classref *cr;
614 /* get stuff from the stack */
616 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
617 mcode = *((u4 *) (sp + 3 * 4));
618 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
619 disp = *((s4 *) (sp + 1 * 4));
620 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
622 /* get the fieldinfo */
624 if (!(c = resolve_classref_eager(cr)))
627 /* patch back original code */
629 *((u4 *) ra) = mcode;
631 /* synchronize instruction cache */
633 md_icacheflush(ra, 4);
635 /* patch class flags */
637 *((s4 *) (pv + disp)) = (s4) c->flags;
639 /* synchronize data cache */
641 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
647 /* patcher_checkcast_instanceof_interface **************************************
651 <patched call position>
652 81870000 lwz r12,0(r7)
653 800c0010 lwz r0,16(r12)
654 34000000 addic. r0,r0,0
655 408101fc ble- 0x3002e518
656 800c0000 lwz r0,0(r12)
658 *******************************************************************************/
660 bool patcher_checkcast_instanceof_interface(u1 *sp)
664 constant_classref *cr;
668 /* get stuff from the stack */
670 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
671 mcode = *((u4 *) (sp + 3 * 4));
672 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
674 /* get the fieldinfo */
676 if (!(c = resolve_classref_eager(cr)))
679 /* patch back original code */
681 *((u4 *) ra) = mcode;
683 /* if we show disassembly, we have to skip the nop */
685 if (opt_showdisassemble)
688 /* patch super class index */
692 *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
694 disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
696 *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
698 /* synchronize instruction cache */
700 md_icacheflush(ra, 5 * 4);
706 /* patcher_checkcast_class *****************************************************
710 <patched call position>
711 81870000 lwz r12,0(r7)
712 800c0014 lwz r0,20(r12)
713 818dff78 lwz r12,-136(r13)
715 *******************************************************************************/
717 bool patcher_checkcast_class(u1 *sp)
721 constant_classref *cr;
726 /* get stuff from the stack */
728 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
729 mcode = *((u4 *) (sp + 3 * 4));
730 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
731 disp = *((s4 *) (sp + 1 * 4));
732 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
734 /* get the fieldinfo */
736 if (!(c = resolve_classref_eager(cr)))
739 /* patch back original code */
741 *((u4 *) ra) = mcode;
743 /* synchronize instruction cache */
745 md_icacheflush(ra, 4);
747 /* patch super class' vftbl */
749 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
751 /* synchronize data cache */
753 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
759 /* patcher_instanceof_class ****************************************************
763 <patched call position>
764 817d0000 lwz r11,0(r29)
765 818dff8c lwz r12,-116(r13)
767 *******************************************************************************/
769 bool patcher_instanceof_class(u1 *sp)
773 constant_classref *cr;
778 /* get stuff from the stack */
780 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
781 mcode = *((u4 *) (sp + 3 * 4));
782 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
783 disp = *((s4 *) (sp + 1 * 4));
784 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
786 /* get the fieldinfo */
788 if (!(c = resolve_classref_eager(cr)))
791 /* patch back original code */
793 *((u4 *) ra) = mcode;
795 /* synchronize instruction cache */
797 md_icacheflush(ra, 4);
799 /* patch super class' vftbl */
801 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
803 /* synchronize data cache */
805 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
811 /* patcher_clinit **************************************************************
815 *******************************************************************************/
817 bool patcher_clinit(u1 *sp)
823 /* get stuff from the stack */
825 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
826 mcode = *((u4 *) (sp + 3 * 4));
827 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
829 /* check if the class is initialized */
831 if (!(c->state & CLASS_INITIALIZED))
832 if (!initialize_class(c))
835 /* patch back original code */
837 *((u4 *) ra) = mcode;
839 /* synchronize instruction cache */
841 md_icacheflush(ra, 4);
847 /* patcher_athrow_areturn ******************************************************
851 <patched call position>
853 *******************************************************************************/
855 #ifdef ENABLE_VERIFIER
856 bool patcher_athrow_areturn(u1 *sp)
860 unresolved_class *uc;
863 /* get stuff from the stack */
865 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
866 mcode = *((u4 *) (sp + 3 * 4));
867 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
869 /* resolve the class */
871 if (!resolve_class(uc, resolveEager, false, &c))
874 /* patch back original code */
876 *((u4 *) ra) = mcode;
878 /* synchronize instruction cache */
880 md_icacheflush(ra, 4);
884 #endif /* ENABLE_VERIFIER */
887 /* patcher_resolve_native ******************************************************
891 *******************************************************************************/
893 #if !defined(WITH_STATIC_CLASSPATH)
894 bool patcher_resolve_native(u1 *sp)
903 /* get stuff from the stack */
905 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
906 mcode = *((u4 *) (sp + 3 * 4));
907 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
908 disp = *((s4 *) (sp + 1 * 4));
909 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
911 /* calculate and set the new return address */
914 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
916 /* resolve native function */
918 if (!(f = native_resolve_function(m)))
921 /* patch back original code */
923 *((u4 *) ra) = mcode;
925 /* synchronize instruction cache */
927 md_icacheflush(ra, 4);
929 /* patch native function pointer */
931 *((ptrint *) (pv + disp)) = (ptrint) f;
933 /* synchronize data cache */
935 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
939 #endif /* !defined(WITH_STATIC_CLASSPATH) */
943 * These are local overrides for various environment variables in Emacs.
944 * Please do not remove this and leave it at the end of the file, where
945 * Emacs will automagically detect them.
946 * ---------------------------------------------------------------------
949 * indent-tabs-mode: t
953 * vim:noexpandtab:sw=4:ts=4: