1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
31 $Id: patcher.c 2581 2005-06-08 10:31:36Z twisti $
36 #include "vm/jit/x86_64/types.h"
38 #include "mm/memory.h"
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
43 #include "vm/options.h"
44 #include "vm/references.h"
45 #include "vm/jit/helper.h"
46 #include "vm/jit/patcher.h"
49 bool helper_initialize_class(void* beginOfJavaStack,classinfo *c,u1 *ra)
51 if (!c->initialized) {
52 native_stackframeinfo sfi;
55 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
56 sfi.returnToFromNative = (functionptr) (ptrint) ra;
57 sfi.beginOfJavaStackframe = beginOfJavaStack;
58 sfi.method = NULL; /*internal*/
59 sfi.addressOfThreadspecificHead = builtin_asm_get_stackframeinfo();
60 sfi.oldThreadspecificHeadValue = *(sfi.addressOfThreadspecificHead);
61 *(sfi.addressOfThreadspecificHead) = &sfi;
63 /*printf("calling static initializer (helper_initialize_class), returnaddress=%p for class %s\n",ra,c->name->text);*/
65 init=initialize_class(c);
67 *(sfi.addressOfThreadspecificHead) = sfi.oldThreadspecificHeadValue;
77 /* patcher_get_putstatic *******************************************************
81 <patched call position>
82 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
84 *******************************************************************************/
86 bool patcher_get_putstatic(u1 *sp)
96 /* get stuff from the stack */
98 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
99 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
100 mcode = *((u8 *) (sp + 1 * 8));
101 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
103 beginJavaStack= (void*)(sp + 3 * 8);
105 /* calculate and set the new return address */
108 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
110 PATCHER_MONITORENTER;
112 /* get the fieldinfo */
114 if (!(fi = helper_resolve_fieldinfo(uf))) {
120 /* check if the field's class is initialized */
122 if (!helper_initialize_class(beginJavaStack, fi->class, ra)) {
128 /* patch back original code */
130 *((u8 *) ra) = mcode;
132 /* if we show disassembly, we have to skip the nop's */
137 /* get RIP offset from machine instruction */
139 offset = *((u4 *) (ra + 3));
141 /* patch the field value's address (+ 7: is the size of the RIP move) */
143 *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
145 PATCHER_MARK_PATCHED_MONITOREXIT;
151 /* patcher_get_putfield ********************************************************
155 <patched call position>
156 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
158 *******************************************************************************/
160 bool patcher_get_putfield(u1 *sp)
163 java_objectheader *o;
165 unresolved_field *uf;
168 /* get stuff from the stack */
170 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
171 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
172 mcode = *((u8 *) (sp + 1 * 8));
173 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
175 /* calculate and set the new return address */
178 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
180 PATCHER_MONITORENTER;
182 /* get the fieldinfo */
184 if (!(fi = helper_resolve_fieldinfo(uf))) {
190 /* patch back original code */
192 *((u8 *) ra) = mcode;
194 /* if we show disassembly, we have to skip the nop's */
199 /* patch the field's offset: we check for the field type, because the */
200 /* instructions have different lengths */
202 if (IS_FLT_DBL_TYPE(fi->type)) {
203 *((u4 *) (ra + 5)) = (u4) (fi->offset);
208 /* check for special case: %rsp or %r12 as base register */
213 *((u4 *) (ra + 4)) = (u4) (fi->offset);
215 *((u4 *) (ra + 3)) = (u4) (fi->offset);
218 PATCHER_MARK_PATCHED_MONITOREXIT;
224 /* patcher_putfieldconst *******************************************************
228 <patched call position>
229 49 c7 87 10 00 00 00 00 00 00 00 movq $0x0,0x10(%r15)
231 *******************************************************************************/
233 bool patcher_putfieldconst(u1 *sp)
236 java_objectheader *o;
238 unresolved_field *uf;
241 /* get stuff from the stack */
243 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
244 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
245 mcode = *((u8 *) (sp + 1 * 8));
246 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
248 /* calculate and set the new return address */
251 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
253 PATCHER_MONITORENTER;
255 /* get the fieldinfo */
257 if (!(fi = helper_resolve_fieldinfo(uf))) {
263 /* patch back original code */
265 *((u8 *) ra) = mcode;
267 /* if we show disassembly, we have to skip the nop's */
272 /* handle special case when the base register is %r12 */
274 if (*(ra + 2) == 0x84)
277 /* patch the field's offset */
279 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
280 *((u4 *) (ra + 3)) = (u4) (fi->offset);
281 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
284 *((u4 *) (ra + 3)) = (u4) (fi->offset);
287 PATCHER_MARK_PATCHED_MONITOREXIT;
293 /* patcher_builtin_new *********************************************************
297 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
298 <patched call position>
299 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
302 *******************************************************************************/
304 bool patcher_builtin_new(u1 *sp)
307 java_objectheader *o;
309 constant_classref *cr;
311 void *beginJavaStack;
312 /* get stuff from the stack */
314 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
315 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
316 mcode = *((u8 *) (sp + 1 * 8));
317 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
318 beginJavaStack = (void*) (sp+3*8);
320 /* calculate and set the new return address */
323 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
325 PATCHER_MONITORENTER;
327 /* get the classinfo */
329 if (!(c = helper_resolve_classinfo(cr))) {
335 if (!helper_initialize_class(beginJavaStack, c, ra + 5)) {
341 /* patch back original code */
343 *((u8 *) (ra + 10)) = mcode;
345 /* patch the classinfo pointer */
347 *((ptrint *) (ra + 2)) = (ptrint) c;
349 /* if we show disassembly, we have to skip the nop's */
354 /* patch new function address */
356 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
358 PATCHER_MARK_PATCHED_MONITOREXIT;
364 /* patcher_builtin_newarray ****************************************************
368 48 be 88 13 9b 00 00 00 00 00 mov $0x9b1388,%rsi
369 <patched call position>
370 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
373 *******************************************************************************/
375 bool patcher_builtin_newarray(u1 *sp)
378 java_objectheader *o;
380 constant_classref *cr;
383 /* get stuff from the stack */
385 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
386 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
387 mcode = *((u8 *) (sp + 1 * 8));
388 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
390 /* calculate and set the new return address */
393 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
395 PATCHER_MONITORENTER;
397 /* get the classinfo */
399 if (!(c = helper_resolve_classinfo(cr))) {
405 /* patch back original code */
407 *((u8 *) (ra + 10)) = mcode;
409 /* patch the class' vftbl pointer */
411 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
413 /* if we show disassembly, we have to skip the nop's */
418 /* patch new function address */
420 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
422 PATCHER_MARK_PATCHED_MONITOREXIT;
428 /* patcher_builtin_multianewarray **********************************************
432 <patched call position>
433 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
434 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
435 48 89 e2 mov %rsp,%rdx
436 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
439 *******************************************************************************/
441 bool patcher_builtin_multianewarray(u1 *sp)
444 java_objectheader *o;
446 constant_classref *cr;
449 /* get stuff from the stack */
451 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
452 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
453 mcode = *((u8 *) (sp + 1 * 8));
454 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
456 /* calculate and set the new return address */
459 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
461 PATCHER_MONITORENTER;
463 /* get the classinfo */
465 if (!(c = helper_resolve_classinfo(cr))) {
471 /* patch back original code */
473 *((u8 *) ra) = mcode;
475 /* if we show disassembly, we have to skip the nop's */
480 /* patch the class' vftbl pointer */
482 *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
484 /* patch new function address */
486 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
488 PATCHER_MARK_PATCHED_MONITOREXIT;
494 /* patcher_builtin_arraycheckcast **********************************************
498 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
499 <patched call position>
500 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
503 *******************************************************************************/
505 bool patcher_builtin_arraycheckcast(u1 *sp)
508 java_objectheader *o;
510 constant_classref *cr;
513 /* get stuff from the stack */
515 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
516 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
517 mcode = *((u8 *) (sp + 1 * 8));
518 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
520 /* calculate and set the new return address */
523 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
525 PATCHER_MONITORENTER;
527 /* get the classinfo */
529 if (!(c = helper_resolve_classinfo(cr))) {
535 /* patch back original code */
537 *((u8 *) (ra + 10)) = mcode;
539 /* patch the class' vftbl pointer */
541 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
543 /* if we show disassembly, we have to skip the nop's */
548 /* patch new function address */
550 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arraycheckcast;
552 PATCHER_MARK_PATCHED_MONITOREXIT;
558 /* patcher_builtin_arrayinstanceof *********************************************
562 48 be 30 3c b2 00 00 00 00 00 mov $0xb23c30,%rsi
563 <patched call position>
564 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
567 *******************************************************************************/
569 bool patcher_builtin_arrayinstanceof(u1 *sp)
572 java_objectheader *o;
574 constant_classref *cr;
577 /* get stuff from the stack */
579 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
580 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
581 mcode = *((u8 *) (sp + 1 * 8));
582 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
584 /* calculate and set the new return address */
587 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
589 PATCHER_MONITORENTER;
591 /* get the classinfo */
593 if (!(c = helper_resolve_classinfo(cr))) {
599 /* patch back original code */
601 *((u8 *) (ra + 10)) = mcode;
603 /* patch the class' vftbl pointer */
605 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
607 /* if we show disassembly, we have to skip the nop's */
612 /* patch new function address */
614 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
616 PATCHER_MARK_PATCHED_MONITOREXIT;
622 /* patcher_invokestatic_special ************************************************
626 *******************************************************************************/
628 bool patcher_invokestatic_special(u1 *sp)
631 java_objectheader *o;
633 unresolved_method *um;
636 /* get stuff from the stack */
638 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
639 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
640 mcode = *((u8 *) (sp + 1 * 8));
641 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
643 /* calculate and set the new return address */
646 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
648 PATCHER_MONITORENTER;
650 /* get the fieldinfo */
652 if (!(m = helper_resolve_methodinfo(um))) {
657 /* patch back original code */
659 *((u8 *) ra) = mcode;
661 /* if we show disassembly, we have to skip the nop's */
666 /* patch stubroutine */
668 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
670 PATCHER_MARK_PATCHED_MONITOREXIT;
676 /* patcher_invokevirtual *******************************************************
680 *******************************************************************************/
682 bool patcher_invokevirtual(u1 *sp)
685 java_objectheader *o;
687 unresolved_method *um;
690 /* get stuff from the stack */
692 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
693 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
694 mcode = *((u8 *) (sp + 1 * 8));
695 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
697 /* calculate and set the new return address */
700 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
702 PATCHER_MONITORENTER;
704 /* get the fieldinfo */
706 if (!(m = helper_resolve_methodinfo(um))) {
712 /* patch back original code */
714 *((u8 *) ra) = mcode;
716 /* if we show disassembly, we have to skip the nop's */
721 /* patch vftbl index */
723 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
724 sizeof(methodptr) * m->vftblindex);
726 PATCHER_MARK_PATCHED_MONITOREXIT;
732 /* patcher_invokeinterface *****************************************************
736 *******************************************************************************/
738 bool patcher_invokeinterface(u1 *sp)
741 java_objectheader *o;
743 unresolved_method *um;
746 /* get stuff from the stack */
748 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
749 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
750 mcode = *((u8 *) (sp + 1 * 8));
751 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
753 /* calculate and set the new return address */
756 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
758 PATCHER_MONITORENTER;
760 /* get the fieldinfo */
762 if (!(m = helper_resolve_methodinfo(um))) {
768 /* patch back original code */
770 *((u8 *) ra) = mcode;
772 /* if we show disassembly, we have to skip the nop's */
777 /* patch interfacetable index */
779 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
780 sizeof(methodptr) * m->class->index);
782 /* patch method offset */
784 *((s4 *) (ra + 3 + 7 + 3)) =
785 (s4) (sizeof(methodptr) * (m - m->class->methods));
787 PATCHER_MARK_PATCHED_MONITOREXIT;
793 /* patcher_checkcast_instanceof_flags ******************************************
797 *******************************************************************************/
799 bool patcher_checkcast_instanceof_flags(u1 *sp)
802 java_objectheader *o;
804 constant_classref *cr;
807 /* get stuff from the stack */
809 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
810 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
811 mcode = *((u8 *) (sp + 1 * 8));
812 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
814 /* calculate and set the new return address */
817 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
819 PATCHER_MONITORENTER;
821 /* get the fieldinfo */
823 if (!(c = helper_resolve_classinfo(cr))) {
829 /* patch back original code */
831 *((u8 *) ra) = mcode;
833 /* if we show disassembly, we have to skip the nop's */
838 /* patch class flags */
840 *((s4 *) (ra + 2)) = (s4) c->flags;
842 PATCHER_MARK_PATCHED_MONITOREXIT;
848 /* patcher_checkcast_instanceof_interface **************************************
852 *******************************************************************************/
854 bool patcher_checkcast_instanceof_interface(u1 *sp)
857 java_objectheader *o;
859 constant_classref *cr;
862 /* get stuff from the stack */
864 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
865 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
866 mcode = *((u8 *) (sp + 1 * 8));
867 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
869 /* calculate and set the new return address */
872 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
874 PATCHER_MONITORENTER;
876 /* get the fieldinfo */
878 if (!(c = helper_resolve_classinfo(cr))) {
884 /* patch back original code */
886 *((u8 *) ra) = mcode;
888 /* if we show disassembly, we have to skip the nop's */
893 /* patch super class index */
895 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
897 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
898 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
899 c->index * sizeof(methodptr*));
901 PATCHER_MARK_PATCHED_MONITOREXIT;
907 /* patcher_checkcast_class *****************************************************
911 *******************************************************************************/
913 bool patcher_checkcast_class(u1 *sp)
916 java_objectheader *o;
918 constant_classref *cr;
921 /* get stuff from the stack */
923 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
924 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
925 mcode = *((u8 *) (sp + 1 * 8));
926 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
928 /* calculate and set the new return address */
931 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
933 PATCHER_MONITORENTER;
935 /* get the fieldinfo */
937 if (!(c = helper_resolve_classinfo(cr))) {
943 /* patch back original code */
945 *((u8 *) ra) = mcode;
947 /* if we show disassembly, we have to skip the nop's */
952 /* patch super class' vftbl */
954 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
955 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
957 PATCHER_MARK_PATCHED_MONITOREXIT;
963 /* patcher_instanceof_class ****************************************************
967 *******************************************************************************/
969 bool patcher_instanceof_class(u1 *sp)
972 java_objectheader *o;
974 constant_classref *cr;
977 /* get stuff from the stack */
979 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
980 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
981 mcode = *((u8 *) (sp + 1 * 8));
982 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
984 /* calculate and set the new return address */
987 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
989 PATCHER_MONITORENTER;
991 /* get the fieldinfo */
993 if (!(c = helper_resolve_classinfo(cr))) {
999 /* patch back original code */
1001 *((u8 *) ra) = mcode;
1003 /* if we show disassembly, we have to skip the nop's */
1005 if (showdisassemble)
1008 /* patch super class' vftbl */
1010 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1012 PATCHER_MARK_PATCHED_MONITOREXIT;
1018 /* patcher_clinit **************************************************************
1022 *******************************************************************************/
1024 bool patcher_clinit(u1 *sp)
1027 java_objectheader *o;
1030 void *beginJavaStack;
1032 /* get stuff from the stack */
1034 ra = (u1 *) *((ptrint *) (sp + 3 * 8));
1035 o = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1036 mcode = *((u8 *) (sp + 1 * 8));
1037 c = (classinfo *) *((ptrint *) (sp + 0 * 8));
1039 beginJavaStack = (void*) (sp + 3 * 8);
1041 /* calculate and set the new return address */
1044 *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1046 PATCHER_MONITORENTER;
1048 /* check if the class is initialized */
1050 if (!helper_initialize_class(beginJavaStack, c, ra)) {
1051 PATCHER_MONITOREXIT;
1056 /* patch back original code */
1058 *((u8 *) ra) = mcode;
1060 PATCHER_MARK_PATCHED_MONITOREXIT;
1067 * These are local overrides for various environment variables in Emacs.
1068 * Please do not remove this and leave it at the end of the file, where
1069 * Emacs will automagically detect them.
1070 * ---------------------------------------------------------------------
1073 * indent-tabs-mode: t
1077 * vim:noexpandtab:sw=4:ts=4: