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 8027 2007-06-07 10:30:33Z michi $
33 GENERATED PATCHER BRANCH AFTER PATCH
37 foo bras %r14, OFFSET foo
41 Short patcher call with nops:
44 nop bras %r14, OFFSET nop --+
45 nop ===> nop ===> nop |
50 PATCHER_LONGBRANCHES_NOPS_SKIP <-+
52 br exit: ild itmp3, disp(pv) br exit -+
53 nop aadd pv, itmp3 aadd pv, itmp3 |
54 nop ===> nop ===> nop |
56 nop basr itmp3, itmp3 basr itmp3, itmp3 -+
65 #include "vm/jit/s390/codegen.h"
66 #include "vm/jit/s390/md-abi.h"
68 #include "mm/memory.h"
69 #include "native/native.h"
70 #include "vm/builtin.h"
71 #include "vmcore/class.h"
72 #include "vm/exceptions.h"
73 #include "vmcore/field.h"
74 #include "vm/initialize.h"
75 #include "vmcore/options.h"
76 #include "vmcore/references.h"
77 #include "vm/resolve.h"
78 #include "vm/jit/patcher.h"
79 #include "vm/jit/stacktrace.h"
82 #define OOPS() assert(0);
85 /* A normal patcher branch done using BRAS */
86 #define PATCHER_IS_SHORTBRANCH(brcode) ((brcode & 0xFF0F0000) == 0xA7050000)
88 /* patcher_wrapper *************************************************************
90 Wrapper for all patchers. It also creates the stackframe info
93 If the return value of the patcher function is false, it gets the
94 exception object, clears the exception pointer and returns the
97 *******************************************************************************/
99 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
103 java_objectheader *o;
106 java_objectheader *e;
108 /* define the patcher function */
110 bool (*patcher_function)(u1 *);
112 /* get stuff from the stack */
114 xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
115 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
116 f = (functionptr) *((ptrint *) (sp + 0 * 4));
118 /* For a normal branch, the patch position is SZ_BRAS bytes before the RA.
119 * For long branches it is PATCHER_LONGBRANCHES_NOPS_SKIP before the RA.
122 if (PATCHER_IS_SHORTBRANCH(*(u4 *)(xpc - SZ_BRAS))) {
125 xpc = xpc - PATCHER_LONGBRANCHES_NOPS_SKIP;
128 *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
130 /* store PV into the patcher function position */
132 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
134 /* cast the passed function to a patcher function */
136 patcher_function = (bool (*)(u1 *)) (ptrint) f;
138 /* enter a monitor on the patching position */
140 PATCHER_MONITORENTER;
142 /* create the stackframeinfo */
144 /* RA is passed as NULL, but the XPC is correct and can be used in
145 stacktrace_create_extern_stackframeinfo for
146 md_codegen_get_pv_from_pc. */
148 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
150 /* call the proper patcher function */
152 result = (patcher_function)(sp);
154 /* remove the stackframeinfo */
156 stacktrace_remove_stackframeinfo(&sfi);
158 /* check for return value and exit accordingly */
160 if (result == false) {
161 e = exceptions_get_and_clear_exception();
168 PATCHER_MARK_PATCHED_MONITOREXIT;
174 /* patcher_get_putstatic *******************************************************
178 *******************************************************************************/
180 bool patcher_get_putstatic(u1 *sp)
184 unresolved_field *uf;
189 /* get stuff from the stack */
191 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
192 mcode = *((u4 *) (sp + 3 * 4));
193 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
194 disp = *((s4 *) (sp + 1 * 4));
195 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
197 /* get the fieldinfo */
199 if (!(fi = resolve_field_eager(uf)))
202 /* check if the field's class is initialized */
204 if (!(fi->class->state & CLASS_INITIALIZED))
205 if (!initialize_class(fi->class))
208 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
210 /* patch back original code */
212 *((u4 *) ra) = mcode;
218 /* patcher_get_putfield ********************************************************
222 *******************************************************************************/
224 bool patcher_get_putfield(u1 *sp)
228 unresolved_field *uf;
233 /* get stuff from the stack */
235 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
236 mcode = *((u4 *) (sp + 3 * 4));
237 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
238 disp = *((s4 *) (sp + 1 * 4));
240 /* get the fieldinfo */
242 if (!(fi = resolve_field_eager(uf)))
245 /* patch back original code */
247 brcode = *((u4 *) ra);
248 *((u4 *) ra) = mcode;
250 /* If NOPs are generated, skip them */
252 if (! PATCHER_IS_SHORTBRANCH(brcode))
253 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
254 else if (opt_shownops)
255 ra += PATCHER_NOPS_SKIP;
257 /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
261 /* patch correct offset */
263 if (fi->type == TYPE_LNG) {
264 assert(N_VALID_DISP(fi->offset + 4));
265 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
266 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
268 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
270 assert(N_VALID_DISP(fi->offset));
272 *((u4 *) ra) |= fi->offset;
279 /* patcher_putfieldconst *******************************************************
283 <patched call position>
284 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
286 *******************************************************************************/
288 bool patcher_putfieldconst(u1 *sp)
293 unresolved_field *uf;
296 /* get stuff from the stack */
298 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
299 mcode = *((u8 *) (sp + 3 * 8));
300 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
302 /* get the fieldinfo */
304 if (!(fi = resolve_field_eager(uf)))
307 /* patch back original code */
309 *((u8 *) ra) = mcode;
311 /* if we show disassembly, we have to skip the nop's */
316 /* patch the field's offset */
318 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
319 /* handle special case when the base register is %r12 */
321 if (*(ra + 2) == 0x84) {
322 *((u4 *) (ra + 4)) = (u4) (fi->offset);
323 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
326 *((u4 *) (ra + 3)) = (u4) (fi->offset);
327 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
331 /* handle special case when the base register is %r12 */
333 if (*(ra + 2) == 0x84)
334 *((u4 *) (ra + 4)) = (u4) (fi->offset);
336 *((u4 *) (ra + 3)) = (u4) (fi->offset);
343 /* patcher_aconst **************************************************************
347 <patched call position>
348 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
350 *******************************************************************************/
352 bool patcher_aconst(u1 *sp)
357 constant_classref *cr;
360 /* get stuff from the stack */
362 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
363 mcode = *((u8 *) (sp + 3 * 8));
364 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
366 /* get the classinfo */
368 if (!(c = resolve_classref_eager(cr)))
371 /* patch back original code */
373 *((u8 *) ra) = mcode;
375 /* if we show disassembly, we have to skip the nop's */
380 /* patch the classinfo pointer */
382 *((ptrint *) (ra + 2)) = (ptrint) c;
388 /* patcher_builtin_multianewarray **********************************************
392 <patched call position>
393 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
394 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
395 48 89 e2 mov %rsp,%rdx
396 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
399 *******************************************************************************/
401 bool patcher_builtin_multianewarray(u1 *sp)
406 constant_classref *cr;
409 /* get stuff from the stack */
411 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
412 mcode = *((u8 *) (sp + 3 * 8));
413 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
415 /* get the classinfo */
417 if (!(c = resolve_classref_eager(cr)))
420 /* patch back original code */
422 *((u8 *) ra) = mcode;
424 /* if we show disassembly, we have to skip the nop's */
429 /* patch the classinfo pointer */
431 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
437 /* patcher_builtin_arraycheckcast **********************************************
441 <patched call position>
442 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
443 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
446 *******************************************************************************/
448 bool patcher_builtin_arraycheckcast(u1 *sp)
453 constant_classref *cr;
456 /* get stuff from the stack */
458 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
459 mcode = *((u8 *) (sp + 3 * 8));
460 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
462 /* get the classinfo */
464 if (!(c = resolve_classref_eager(cr)))
467 /* patch back original code */
469 *((u8 *) ra) = mcode;
471 /* if we show disassembly, we have to skip the nop's */
476 /* patch the classinfo pointer */
478 *((ptrint *) (ra + 2)) = (ptrint) c;
484 /* patcher_invokestatic_special ************************************************
488 *******************************************************************************/
490 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
494 unresolved_method *um;
499 /* get stuff from the stack */
501 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
502 mcode = *((u4 *) (sp + 3 * 4));
503 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
504 disp = *((s4 *) (sp + 1 * 4));
505 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
507 /* get the fieldinfo */
509 if (!(m = resolve_method_eager(um)))
512 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
514 /* patch back original code */
516 *((u4 *) ra) = mcode;
518 /* patch stubroutine */
524 /* patcher_invokevirtual *******************************************************
528 *******************************************************************************/
530 bool patcher_invokevirtual(u1 *sp)
534 unresolved_method *um;
538 /* get stuff from the stack */
540 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
541 mcode = *((u4 *) (sp + 3 * 4));
542 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
544 /* get the fieldinfo */
546 if (!(m = resolve_method_eager(um)))
549 /* patch back original code */
551 brcode = *((u4 *) ra);
552 *((u4 *) ra) = mcode;
554 /* If NOPs are generated, skip them */
556 if (! PATCHER_IS_SHORTBRANCH(brcode))
557 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
558 else if (opt_shownops)
559 ra += PATCHER_NOPS_SKIP;
561 /* patch vftbl index */
564 off = (s4) (OFFSET(vftbl_t, table[0]) +
565 sizeof(methodptr) * m->vftblindex);
567 assert(N_VALID_DISP(off));
569 *((s4 *)(ra + 4)) |= off;
575 /* patcher_invokeinterface *****************************************************
579 *******************************************************************************/
581 bool patcher_invokeinterface(u1 *sp)
585 unresolved_method *um;
589 /* get stuff from the stack */
591 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
592 mcode = *((u4 *) (sp + 3 * 4));
593 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
595 /* get the fieldinfo */
597 if (!(m = resolve_method_eager(um)))
600 /* patch back original code */
602 brcode = *((u4 *) ra);
603 *((u4 *) ra) = mcode;
605 /* If NOPs are generated, skip them */
607 if (! PATCHER_IS_SHORTBRANCH(brcode))
608 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
609 else if (opt_shownops)
610 ra += PATCHER_NOPS_SKIP;
612 /* get interfacetable index */
614 idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
615 sizeof(methodptr) * m->class->index) +
618 ASSERT_VALID_DISP(idx);
620 /* get method offset */
623 (s4) (sizeof(methodptr) * (m - m->class->methods));
624 ASSERT_VALID_DISP(off);
628 *((s4 *)(ra + 4)) |= idx;
629 *((s4 *)(ra + 4 + 4)) |= off;
635 /* patcher_resolve_classref_to_flags *******************************************
637 CHECKCAST/INSTANCEOF:
639 <patched call position>
641 *******************************************************************************/
643 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
645 constant_classref *cr;
652 /* get stuff from the stack */
654 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
655 mcode = *((u4 *) (sp + 3 * 4));
656 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
657 disp = *((s4 *) (sp + 1 * 4));
658 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
660 /* get the fieldinfo */
662 if (!(c = resolve_classref_eager(cr)))
665 /* patch class flags */
667 *((s4 *) (pv + disp)) = (s4) c->flags;
669 /* patch back original code */
671 *((u4 *) ra) = mcode;
676 /* patcher_resolve_classref_to_classinfo ***************************************
682 *******************************************************************************/
684 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
686 constant_classref *cr;
693 /* get stuff from the stack */
695 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
696 mcode = *((u4 *) (sp + 3 * 4));
697 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
698 disp = *((s4 *) (sp + 1 * 4));
699 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
701 /* get the classinfo */
703 if (!(c = resolve_classref_eager(cr)))
706 /* patch the classinfo pointer */
708 *((ptrint *) (pv + disp)) = (ptrint) c;
710 /* patch back original code */
712 *((u4 *) ra) = mcode;
717 /* patcher_resolve_classref_to_vftbl *******************************************
722 *******************************************************************************/
724 bool patcher_resolve_classref_to_vftbl(u1 *sp)
726 constant_classref *cr;
733 /* get stuff from the stack */
735 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
736 mcode = *((u4 *) (sp + 3 * 4));
737 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
738 disp = *((s4 *) (sp + 1 * 4));
739 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
741 /* get the fieldinfo */
743 if (!(c = resolve_classref_eager(cr)))
746 /* patch super class' vftbl */
748 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
750 /* patch back original code */
752 *((u4 *) ra) = mcode;
757 /* patcher_checkcast_instanceof_interface **************************************
761 *******************************************************************************/
763 bool patcher_checkcast_instanceof_interface(u1 *sp)
767 constant_classref *cr;
770 /* get stuff from the stack */
772 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
773 mcode = *((u4 *) (sp + 3 * 4));
774 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
776 /* get the fieldinfo */
778 if (!(c = resolve_classref_eager(cr)))
781 /* patch back original code */
783 brcode = *((u4 *) ra);
784 *((u4 *) ra) = mcode;
786 /* If NOPs are generated, skip them */
788 if (! PATCHER_IS_SHORTBRANCH(brcode))
789 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
790 else if (opt_shownops)
791 ra += PATCHER_NOPS_SKIP;
793 /* patch super class index */
795 /* From here, split your editor and open codegen.c */
797 switch (*(ra + 1) >> 4) {
799 /* First M_ALD is into ITMP1 */
800 /* INSTANCEOF code */
802 *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
803 *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
804 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
805 c->index * sizeof(methodptr*));
810 /* First M_ALD is into ITMP2 */
813 *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
814 *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL) |=
815 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
816 c->index * sizeof(methodptr*));
829 /* patcher_checkcast_class *****************************************************
833 <patched call position>
834 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
835 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
836 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
837 4d 29 da sub %r11,%r10
838 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
840 *******************************************************************************/
842 bool patcher_checkcast_class(u1 *sp)
847 constant_classref *cr;
850 /* get stuff from the stack */
852 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
853 mcode = *((u8 *) (sp + 3 * 8));
854 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
856 /* get the fieldinfo */
858 if (!(c = resolve_classref_eager(cr)))
861 /* patch back original code */
863 *((u8 *) ra) = mcode;
865 /* if we show disassembly, we have to skip the nop's */
870 /* patch super class' vftbl */
872 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
873 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
879 /* patcher_instanceof_class ****************************************************
883 <patched call position>
884 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
886 *******************************************************************************/
888 bool patcher_instanceof_class(u1 *sp)
893 constant_classref *cr;
896 /* get stuff from the stack */
898 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
899 mcode = *((u8 *) (sp + 3 * 8));
900 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
902 /* get the fieldinfo */
904 if (!(c = resolve_classref_eager(cr)))
907 /* patch back original code */
909 *((u8 *) ra) = mcode;
911 /* if we show disassembly, we have to skip the nop's */
916 /* patch super class' vftbl */
918 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
924 /* patcher_clinit **************************************************************
926 May be used for GET/PUTSTATIC and in native stub.
930 *******************************************************************************/
932 __PORTED__ bool patcher_clinit(u1 *sp)
938 /* get stuff from the stack */
940 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
941 mcode = *((u4 *) (sp + 3 * 4));
942 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
944 /* check if the class is initialized */
946 if (!(c->state & CLASS_INITIALIZED))
947 if (!initialize_class(c))
950 /* patch back original code */
952 *((u4 *) ra) = mcode;
958 /* patcher_athrow_areturn ******************************************************
962 <patched call position>
964 *******************************************************************************/
966 #ifdef ENABLE_VERIFIER
967 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
971 unresolved_class *uc;
973 /* get stuff from the stack */
975 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
976 mcode = *((u4 *) (sp + 3 * 4));
977 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
979 /* resolve the class and check subtype constraints */
981 if (!resolve_class_eager_no_access_check(uc))
984 /* patch back original code */
986 *((u4 *) ra) = mcode;
990 #endif /* ENABLE_VERIFIER */
993 /* patcher_resolve_native ******************************************************
995 *******************************************************************************/
997 #if !defined(WITH_STATIC_CLASSPATH)
998 __PORTED__ bool patcher_resolve_native(u1 *sp)
1007 /* get stuff from the stack */
1009 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
1010 mcode = *((u4 *) (sp + 3 * 4));
1011 disp = *((s4 *) (sp + 1 * 4));
1012 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
1013 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
1015 /* resolve native function */
1017 if (!(f = native_resolve_function(m)))
1020 /* patch native function pointer */
1022 *((ptrint *) (pv + disp)) = (ptrint) f;
1024 /* patch back original code */
1026 *((u4 *) ra) = mcode;
1030 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1034 * These are local overrides for various environment variables in Emacs.
1035 * Please do not remove this and leave it at the end of the file, where
1036 * Emacs will automagically detect them.
1037 * ---------------------------------------------------------------------
1040 * indent-tabs-mode: t
1044 * vim:noexpandtab:sw=4:ts=4: