1 /* src/vm/jit/x86_64/patcher.c - x86_64 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 7581 2007-03-26 07:23:16Z pm $
39 #include "vm/jit/s390/codegen.h"
40 #include "vm/jit/s390/md-abi.h"
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vmcore/class.h"
46 #include "vm/exceptions.h"
47 #include "vmcore/field.h"
48 #include "vm/initialize.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
52 #include "vm/jit/patcher.h"
53 #include "vm/jit/stacktrace.h"
56 #define OOPS() assert(0);
59 /* patcher_wrapper *************************************************************
61 Wrapper for all patchers. It also creates the stackframe info
64 If the return value of the patcher function is false, it gets the
65 exception object, clears the exception pointer and returns the
68 *******************************************************************************/
70 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
80 /* define the patcher function */
82 bool (*patcher_function)(u1 *);
84 /* get stuff from the stack */
86 xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
87 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
88 f = (functionptr) *((ptrint *) (sp + 0 * 4));
90 xpc = xpc - 4; /* the patch position is 4 bytes before the RA */
92 *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
94 /* store PV into the patcher function position */
96 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
98 /* cast the passed function to a patcher function */
100 patcher_function = (bool (*)(u1 *)) (ptrint) f;
102 /* enter a monitor on the patching position */
104 PATCHER_MONITORENTER;
106 /* create the stackframeinfo */
108 /* RA is passed as NULL, but the XPC is correct and can be used in
109 stacktrace_create_extern_stackframeinfo for
110 md_codegen_get_pv_from_pc. */
112 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
114 /* call the proper patcher function */
116 result = (patcher_function)(sp);
118 /* remove the stackframeinfo */
120 stacktrace_remove_stackframeinfo(&sfi);
122 /* check for return value and exit accordingly */
124 if (result == false) {
125 e = exceptions_get_and_clear_exception();
132 PATCHER_MARK_PATCHED_MONITOREXIT;
139 java_objectheader *o;
143 java_objectheader *e;
145 /* define the patcher function */
147 bool (*patcher_function)(u1 *);
151 /* get stuff from the stack */
153 xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
154 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
155 f = (functionptr) *((ptrint *) (sp + 0 * 4));
157 /* Correct RA is calculated in codegen.c and stored in the patcher
158 stub stack. There's no need to adjust xpc. */
160 /* store PV into the patcher function position */
162 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
164 /* cast the passed function to a patcher function */
166 patcher_function = (bool (*)(u1 *)) (ptrint) f;
168 /* enter a monitor on the patching position */
170 PATCHER_MONITORENTER;
172 /* create the stackframeinfo */
174 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
176 /* call the proper patcher function */
178 result = (patcher_function)(sp);
180 /* remove the stackframeinfo */
182 stacktrace_remove_stackframeinfo(&sfi);
184 /* check for return value and exit accordingly */
186 if (result == false) {
187 e = exceptions_get_and_clear_exception();
194 PATCHER_MARK_PATCHED_MONITOREXIT;
201 /* patcher_get_putstatic *******************************************************
205 *******************************************************************************/
207 bool patcher_get_putstatic(u1 *sp)
211 unresolved_field *uf;
216 /* get stuff from the stack */
218 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
219 mcode = *((u4 *) (sp + 3 * 4));
220 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
221 disp = *((s4 *) (sp + 1 * 4));
222 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
224 /* get the fieldinfo */
226 if (!(fi = resolve_field_eager(uf)))
229 /* check if the field's class is initialized */
231 if (!(fi->class->state & CLASS_INITIALIZED))
232 if (!initialize_class(fi->class))
235 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
237 /* patch back original code */
239 *((u4 *) ra) = mcode;
245 /* patcher_get_putfield ********************************************************
249 *******************************************************************************/
251 bool patcher_get_putfield(u1 *sp)
255 unresolved_field *uf;
259 /* get stuff from the stack */
261 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
262 mcode = *((u4 *) (sp + 3 * 4));
263 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
265 /* get the fieldinfo */
267 if (!(fi = resolve_field_eager(uf)))
270 /* patch back original code */
272 *((u4 *) ra) = mcode;
274 /* If NOPs are generated, skip them */
277 ra += PATCHER_NOPS_SKIP;
279 /* patch correct offset */
281 if (fi->type == TYPE_LNG) {
282 assert(N_VALID_DISP(fi->offset + 4));
283 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
284 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
286 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
288 assert(N_VALID_DISP(fi->offset));
290 *((u4 *) ra) |= fi->offset;
297 /* patcher_putfieldconst *******************************************************
301 <patched call position>
302 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
304 *******************************************************************************/
306 bool patcher_putfieldconst(u1 *sp)
311 unresolved_field *uf;
314 /* get stuff from the stack */
316 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
317 mcode = *((u8 *) (sp + 3 * 8));
318 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
320 /* get the fieldinfo */
322 if (!(fi = resolve_field_eager(uf)))
325 /* patch back original code */
327 *((u8 *) ra) = mcode;
329 /* if we show disassembly, we have to skip the nop's */
334 /* patch the field's offset */
336 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
337 /* handle special case when the base register is %r12 */
339 if (*(ra + 2) == 0x84) {
340 *((u4 *) (ra + 4)) = (u4) (fi->offset);
341 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
344 *((u4 *) (ra + 3)) = (u4) (fi->offset);
345 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
349 /* handle special case when the base register is %r12 */
351 if (*(ra + 2) == 0x84)
352 *((u4 *) (ra + 4)) = (u4) (fi->offset);
354 *((u4 *) (ra + 3)) = (u4) (fi->offset);
361 /* patcher_aconst **************************************************************
365 <patched call position>
366 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
368 *******************************************************************************/
370 bool patcher_aconst(u1 *sp)
375 constant_classref *cr;
378 /* get stuff from the stack */
380 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
381 mcode = *((u8 *) (sp + 3 * 8));
382 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
384 /* get the classinfo */
386 if (!(c = resolve_classref_eager(cr)))
389 /* patch back original code */
391 *((u8 *) ra) = mcode;
393 /* if we show disassembly, we have to skip the nop's */
398 /* patch the classinfo pointer */
400 *((ptrint *) (ra + 2)) = (ptrint) c;
406 /* patcher_builtin_multianewarray **********************************************
410 <patched call position>
411 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
412 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
413 48 89 e2 mov %rsp,%rdx
414 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
417 *******************************************************************************/
419 bool patcher_builtin_multianewarray(u1 *sp)
424 constant_classref *cr;
427 /* get stuff from the stack */
429 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
430 mcode = *((u8 *) (sp + 3 * 8));
431 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
433 /* get the classinfo */
435 if (!(c = resolve_classref_eager(cr)))
438 /* patch back original code */
440 *((u8 *) ra) = mcode;
442 /* if we show disassembly, we have to skip the nop's */
447 /* patch the classinfo pointer */
449 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
455 /* patcher_builtin_arraycheckcast **********************************************
459 <patched call position>
460 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
461 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
464 *******************************************************************************/
466 bool patcher_builtin_arraycheckcast(u1 *sp)
471 constant_classref *cr;
474 /* get stuff from the stack */
476 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
477 mcode = *((u8 *) (sp + 3 * 8));
478 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
480 /* get the classinfo */
482 if (!(c = resolve_classref_eager(cr)))
485 /* patch back original code */
487 *((u8 *) ra) = mcode;
489 /* if we show disassembly, we have to skip the nop's */
494 /* patch the classinfo pointer */
496 *((ptrint *) (ra + 2)) = (ptrint) c;
502 /* patcher_invokestatic_special ************************************************
506 *******************************************************************************/
508 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
512 unresolved_method *um;
517 /* get stuff from the stack */
519 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
520 mcode = *((u4 *) (sp + 3 * 4));
521 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
522 disp = *((s4 *) (sp + 1 * 4));
523 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
525 /* get the fieldinfo */
527 if (!(m = resolve_method_eager(um)))
530 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
532 /* patch back original code */
534 *((u4 *) ra) = mcode;
536 /* patch stubroutine */
542 /* patcher_invokevirtual *******************************************************
546 *******************************************************************************/
548 bool patcher_invokevirtual(u1 *sp)
552 unresolved_method *um;
556 /* get stuff from the stack */
558 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
559 mcode = *((u4 *) (sp + 3 * 4));
560 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
562 /* get the fieldinfo */
564 if (!(m = resolve_method_eager(um)))
567 /* patch back original code */
569 *((u4 *) ra) = mcode;
571 /* If NOPs are generated, skip them */
574 ra += PATCHER_NOPS_SKIP;
576 /* patch vftbl index */
579 off = (s4) (OFFSET(vftbl_t, table[0]) +
580 sizeof(methodptr) * m->vftblindex);
582 assert(N_VALID_DISP(off));
584 *((s4 *)(ra + 4)) |= off;
590 /* patcher_invokeinterface *****************************************************
594 *******************************************************************************/
596 bool patcher_invokeinterface(u1 *sp)
600 unresolved_method *um;
604 /* get stuff from the stack */
606 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
607 mcode = *((u4 *) (sp + 3 * 4));
608 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
610 /* get the fieldinfo */
612 if (!(m = resolve_method_eager(um)))
615 /* patch back original code */
617 *((u4 *) ra) = mcode;
619 /* If NOPs are generated, skip them */
622 ra += PATCHER_NOPS_SKIP;
624 /* get interfacetable index */
626 idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
627 sizeof(methodptr) * m->class->index) +
630 ASSERT_VALID_DISP(idx);
632 /* get method offset */
635 (s4) (sizeof(methodptr) * (m - m->class->methods));
636 ASSERT_VALID_DISP(off);
640 *((s4 *)(ra + 4)) |= idx;
641 *((s4 *)(ra + 4 + 4)) |= off;
647 /* patcher_resolve_classref_to_flags *******************************************
649 CHECKCAST/INSTANCEOF:
651 <patched call position>
653 *******************************************************************************/
655 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
657 constant_classref *cr;
664 /* get stuff from the stack */
666 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
667 mcode = *((u4 *) (sp + 3 * 4));
668 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
669 disp = *((s4 *) (sp + 1 * 4));
670 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
672 /* get the fieldinfo */
674 if (!(c = resolve_classref_eager(cr)))
677 /* patch class flags */
679 *((s4 *) (pv + disp)) = (s4) c->flags;
681 /* patch back original code */
683 *((u4 *) ra) = mcode;
688 /* patcher_resolve_classref_to_classinfo ***************************************
694 *******************************************************************************/
696 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
698 constant_classref *cr;
705 /* get stuff from the stack */
707 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
708 mcode = *((u4 *) (sp + 3 * 4));
709 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
710 disp = *((s4 *) (sp + 1 * 4));
711 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
713 /* get the classinfo */
715 if (!(c = resolve_classref_eager(cr)))
718 /* patch the classinfo pointer */
720 *((ptrint *) (pv + disp)) = (ptrint) c;
722 /* patch back original code */
724 *((u4 *) ra) = mcode;
729 /* patcher_resolve_classref_to_vftbl *******************************************
734 *******************************************************************************/
736 bool patcher_resolve_classref_to_vftbl(u1 *sp)
738 constant_classref *cr;
745 /* get stuff from the stack */
747 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
748 mcode = *((u4 *) (sp + 3 * 4));
749 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
750 disp = *((s4 *) (sp + 1 * 4));
751 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
753 /* get the fieldinfo */
755 if (!(c = resolve_classref_eager(cr)))
758 /* patch super class' vftbl */
760 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
762 /* patch back original code */
764 *((u4 *) ra) = mcode;
769 /* patcher_checkcast_instanceof_interface **************************************
773 *******************************************************************************/
775 bool patcher_checkcast_instanceof_interface(u1 *sp)
779 constant_classref *cr;
782 /* get stuff from the stack */
784 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
785 mcode = *((u4 *) (sp + 3 * 4));
786 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
788 /* get the fieldinfo */
790 if (!(c = resolve_classref_eager(cr)))
793 /* patch back original code */
795 *((u4 *) ra) = mcode;
797 /* If NOPs are generated, skip them */
800 ra += PATCHER_NOPS_SKIP;
802 /* patch super class index */
804 /* From here, split your editor and open codegen.c */
806 switch (*(ra + 1) >> 4) {
808 /* First M_ALD is into ITMP1 */
809 /* INSTANCEOF code */
811 /* First M_ALD is into ITMP1 */
814 *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
815 *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
816 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
817 c->index * sizeof(methodptr*));
830 /* patcher_checkcast_class *****************************************************
834 <patched call position>
835 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
836 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
837 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
838 4d 29 da sub %r11,%r10
839 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
841 *******************************************************************************/
843 bool patcher_checkcast_class(u1 *sp)
848 constant_classref *cr;
851 /* get stuff from the stack */
853 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
854 mcode = *((u8 *) (sp + 3 * 8));
855 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
857 /* get the fieldinfo */
859 if (!(c = resolve_classref_eager(cr)))
862 /* patch back original code */
864 *((u8 *) ra) = mcode;
866 /* if we show disassembly, we have to skip the nop's */
871 /* patch super class' vftbl */
873 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
874 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
880 /* patcher_instanceof_class ****************************************************
884 <patched call position>
885 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
887 *******************************************************************************/
889 bool patcher_instanceof_class(u1 *sp)
894 constant_classref *cr;
897 /* get stuff from the stack */
899 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
900 mcode = *((u8 *) (sp + 3 * 8));
901 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
903 /* get the fieldinfo */
905 if (!(c = resolve_classref_eager(cr)))
908 /* patch back original code */
910 *((u8 *) ra) = mcode;
912 /* if we show disassembly, we have to skip the nop's */
917 /* patch super class' vftbl */
919 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
925 /* patcher_clinit **************************************************************
927 May be used for GET/PUTSTATIC and in native stub.
931 *******************************************************************************/
933 __PORTED__ bool patcher_clinit(u1 *sp)
939 /* get stuff from the stack */
941 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
942 mcode = *((u4 *) (sp + 3 * 4));
943 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
945 /* check if the class is initialized */
947 if (!(c->state & CLASS_INITIALIZED))
948 if (!initialize_class(c))
951 /* patch back original code */
953 *((u4 *) ra) = mcode;
959 /* patcher_athrow_areturn ******************************************************
963 <patched call position>
965 *******************************************************************************/
967 #ifdef ENABLE_VERIFIER
968 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
972 unresolved_class *uc;
974 /* get stuff from the stack */
976 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
977 mcode = *((u4 *) (sp + 3 * 4));
978 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
980 /* resolve the class and check subtype constraints */
982 if (!resolve_class_eager_no_access_check(uc))
985 /* patch back original code */
987 *((u4 *) ra) = mcode;
991 #endif /* ENABLE_VERIFIER */
994 /* patcher_resolve_native ******************************************************
996 *******************************************************************************/
998 #if !defined(WITH_STATIC_CLASSPATH)
999 __PORTED__ bool patcher_resolve_native(u1 *sp)
1008 /* get stuff from the stack */
1010 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
1011 mcode = *((u4 *) (sp + 3 * 4));
1012 disp = *((s4 *) (sp + 1 * 4));
1013 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
1014 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
1016 /* resolve native function */
1018 if (!(f = native_resolve_function(m)))
1021 /* patch native function pointer */
1023 *((ptrint *) (pv + disp)) = (ptrint) f;
1025 /* patch back original code */
1027 *((u4 *) ra) = mcode;
1031 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1035 * These are local overrides for various environment variables in Emacs.
1036 * Please do not remove this and leave it at the end of the file, where
1037 * Emacs will automagically detect them.
1038 * ---------------------------------------------------------------------
1041 * indent-tabs-mode: t
1045 * vim:noexpandtab:sw=4:ts=4: