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 2410 2005-04-28 13:31:55Z twisti $
36 #include "vm/jit/x86_64/types.h"
37 #include "vm/builtin.h"
39 #include "vm/initialize.h"
40 #include "vm/options.h"
41 #include "vm/references.h"
42 #include "vm/jit/helper.h"
43 #include "vm/exceptions.h"
46 /* patcher_get_putstatic *******************************************************
50 <patched call position>
51 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
53 *******************************************************************************/
55 bool patcher_get_putstatic(u1 *sp)
63 /* get stuff from the stack */
65 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
66 mcode = *((u8 *) (sp + 1 * 8));
67 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
68 beginJavaStack= (void*)(sp+2*8);
69 /* calculate and set the new return address */
72 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
74 *dontfillinexceptionstacktrace=true;
75 /* get the fieldinfo */
76 if (!(fi = helper_resolve_fieldinfo(uf)))
78 *dontfillinexceptionstacktrace=false;
82 /* check if the field's class is initialized */
83 *dontfillinexceptionstacktrace=false;
84 if (!fi->class->initialized) {
87 /*struct native_stackframeinfo {
88 void *oldThreadspecificHeadValue;
89 void **addressOfThreadspecificHead;
91 void *beginOfJavaStackframe; only used if != 0
92 void *returnToFromNative;
94 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
95 native_stackframeinfo sfi;
96 sfi.returnToFromNative=(void*)ra;
97 sfi.beginOfJavaStackframe=beginJavaStack;
98 sfi.method=0; /*internal*/
99 sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
100 sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
101 *(sfi.addressOfThreadspecificHead)=&sfi;
103 init=initialize_class(fi->class);
105 *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
113 *dontfillinexceptionstacktrace=false;
115 /* patch back original code */
117 *((u8 *) ra) = mcode;
119 /* if we show disassembly, we have to skip the nop's */
124 /* get RIP offset from machine instruction */
126 offset = *((u4 *) (ra + 3));
128 /* patch the field value's address (+ 7: is the size of the RIP move) */
130 *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
136 /* patcher_get_putfield ********************************************************
140 <patched call position>
141 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
143 *******************************************************************************/
145 bool patcher_get_putfield(u1 *sp)
149 unresolved_field *uf;
152 /* get stuff from the stack */
154 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
155 mcode = *((u8 *) (sp + 1 * 8));
156 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
158 /* calculate and set the new return address */
161 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
163 *dontfillinexceptionstacktrace=true;
166 /* get the fieldinfo */
168 if (!(fi = helper_resolve_fieldinfo(uf)))
170 *dontfillinexceptionstacktrace=false;
174 /* patch back original code */
176 *((u8 *) ra) = mcode;
178 /* if we show disassembly, we have to skip the nop's */
183 /* patch the field's offset: we check for the field type, because the */
184 /* instructions have different lengths */
186 if (IS_FLT_DBL_TYPE(fi->type)) {
187 *((u4 *) (ra + 5)) = (u4) (fi->offset);
192 /* check for special case: %rsp or %r12 as base register */
197 *((u4 *) (ra + 4)) = (u4) (fi->offset);
199 *((u4 *) (ra + 3)) = (u4) (fi->offset);
202 *dontfillinexceptionstacktrace=false;
207 /* patcher_builtin_new *********************************************************
211 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
212 <patched call position>
213 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
216 *******************************************************************************/
218 bool patcher_builtin_new(u1 *sp)
222 constant_classref *cr;
225 /* get stuff from the stack */
227 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
228 mcode = *((u8 *) (sp + 1 * 8));
229 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
231 /* calculate and set the new return address */
234 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
236 *dontfillinexceptionstacktrace=true;
238 /* get the classinfo */
240 if (!(c = helper_resolve_classinfo(cr)))
242 *dontfillinexceptionstacktrace=false;
246 /* patch back original code */
248 *((u8 *) (ra + 10)) = mcode;
250 /* patch the classinfo pointer */
252 *((ptrint *) (ra + 2)) = (ptrint) c;
254 /* if we show disassembly, we have to skip the nop's */
259 /* patch new function address */
261 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
263 *dontfillinexceptionstacktrace=false;
268 /* patcher_builtin_newarray ****************************************************
272 48 be 88 13 9b 00 00 00 00 00 mov $0x9b1388,%rsi
273 <patched call position>
274 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
277 *******************************************************************************/
279 bool patcher_builtin_newarray(u1 *sp)
283 constant_classref *cr;
286 /* get stuff from the stack */
288 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
289 mcode = *((u8 *) (sp + 1 * 8));
290 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
292 /* calculate and set the new return address */
295 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
297 *dontfillinexceptionstacktrace=true;
299 /* get the classinfo */
301 if (!(c = helper_resolve_classinfo(cr))) {
302 *dontfillinexceptionstacktrace=false;
306 /* patch back original code */
308 *((u8 *) (ra + 10)) = mcode;
310 /* patch the class' vftbl pointer */
312 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
314 /* if we show disassembly, we have to skip the nop's */
319 /* patch new function address */
321 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
323 *dontfillinexceptionstacktrace=false;
328 /* patcher_builtin_multianewarray **********************************************
332 <patched call position>
333 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
334 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
335 48 89 e2 mov %rsp,%rdx
336 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
339 *******************************************************************************/
341 bool patcher_builtin_multianewarray(u1 *sp)
345 constant_classref *cr;
348 /* get stuff from the stack */
350 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
351 mcode = *((u8 *) (sp + 1 * 8));
352 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
354 /* calculate and set the new return address */
357 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
359 *dontfillinexceptionstacktrace=true;
361 /* get the classinfo */
363 if (!(c = helper_resolve_classinfo(cr))) {
364 *dontfillinexceptionstacktrace=false;
368 /* patch back original code */
370 *((u8 *) ra) = mcode;
372 /* if we show disassembly, we have to skip the nop's */
377 /* patch the class' vftbl pointer */
379 *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
381 /* patch new function address */
383 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
385 *dontfillinexceptionstacktrace=false;
390 /* patcher_builtin_checkarraycast **********************************************
394 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
395 <patched call position>
396 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
399 *******************************************************************************/
401 bool patcher_builtin_checkarraycast(u1 *sp)
405 constant_classref *cr;
408 /* get stuff from the stack */
410 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
411 mcode = *((u8 *) (sp + 1 * 8));
412 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
414 /* calculate and set the new return address */
417 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
419 *dontfillinexceptionstacktrace=true;
421 /* get the classinfo */
423 if (!(c = helper_resolve_classinfo(cr))) {
424 *dontfillinexceptionstacktrace=false;
428 /* patch back original code */
430 *((u8 *) (ra + 10)) = mcode;
432 /* patch the class' vftbl pointer */
434 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
436 /* if we show disassembly, we have to skip the nop's */
441 /* patch new function address */
443 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_checkarraycast;
445 *dontfillinexceptionstacktrace=false;
450 /* patcher_builtin_arrayinstanceof *********************************************
454 48 be 30 3c b2 00 00 00 00 00 mov $0xb23c30,%rsi
455 <patched call position>
456 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
459 *******************************************************************************/
461 bool patcher_builtin_arrayinstanceof(u1 *sp)
465 constant_classref *cr;
468 /* get stuff from the stack */
470 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
471 mcode = *((u8 *) (sp + 1 * 8));
472 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
474 /* calculate and set the new return address */
477 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
479 *dontfillinexceptionstacktrace=true;
481 /* get the classinfo */
483 if (!(c = helper_resolve_classinfo(cr))) {
484 *dontfillinexceptionstacktrace=false;
488 /* patch back original code */
490 *((u8 *) (ra + 10)) = mcode;
492 /* patch the class' vftbl pointer */
494 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
496 /* if we show disassembly, we have to skip the nop's */
501 /* patch new function address */
503 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
505 *dontfillinexceptionstacktrace=false;
510 /* patcher_invokestatic_special ************************************************
514 *******************************************************************************/
516 bool patcher_invokestatic_special(u1 *sp)
520 unresolved_method *um;
523 /* get stuff from the stack */
525 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
526 mcode = *((u8 *) (sp + 1 * 8));
527 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
529 /* calculate and set the new return address */
532 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
534 *dontfillinexceptionstacktrace=true;
537 /* get the fieldinfo */
539 if (!(m = helper_resolve_methodinfo(um)))
541 *dontfillinexceptionstacktrace=false;
544 /* patch back original code */
546 *((u8 *) ra) = mcode;
548 /* if we show disassembly, we have to skip the nop's */
553 /* patch stubroutine */
555 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
557 *dontfillinexceptionstacktrace=false;
562 /* patcher_invokevirtual *******************************************************
566 *******************************************************************************/
568 bool patcher_invokevirtual(u1 *sp)
572 unresolved_method *um;
575 /* get stuff from the stack */
577 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
578 mcode = *((u8 *) (sp + 1 * 8));
579 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
581 /* calculate and set the new return address */
584 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
586 *dontfillinexceptionstacktrace=true;
588 /* get the fieldinfo */
590 if (!(m = helper_resolve_methodinfo(um)))
592 *dontfillinexceptionstacktrace=false;
596 /* patch back original code */
598 *((u8 *) ra) = mcode;
600 /* if we show disassembly, we have to skip the nop's */
605 /* patch vftbl index */
607 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
608 sizeof(methodptr) * m->vftblindex);
610 *dontfillinexceptionstacktrace=false;
615 /* patcher_invokeinterface *****************************************************
619 *******************************************************************************/
621 bool patcher_invokeinterface(u1 *sp)
625 unresolved_method *um;
628 /* get stuff from the stack */
630 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
631 mcode = *((u8 *) (sp + 1 * 8));
632 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
634 /* calculate and set the new return address */
637 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
639 *dontfillinexceptionstacktrace=true;
641 /* get the fieldinfo */
643 if (!(m = helper_resolve_methodinfo(um)))
645 *dontfillinexceptionstacktrace=false;
649 /* patch back original code */
651 *((u8 *) ra) = mcode;
653 /* if we show disassembly, we have to skip the nop's */
658 /* patch interfacetable index */
660 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
661 sizeof(methodptr) * m->class->index);
663 /* patch method offset */
665 *((s4 *) (ra + 3 + 7 + 3)) =
666 (s4) (sizeof(methodptr) * (m - m->class->methods));
668 *dontfillinexceptionstacktrace=false;
673 /* patcher_checkcast_instanceof_flags ******************************************
677 *******************************************************************************/
679 bool patcher_checkcast_instanceof_flags(u1 *sp)
683 constant_classref *cr;
686 /* get stuff from the stack */
688 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
689 mcode = *((u8 *) (sp + 1 * 8));
690 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
692 /* calculate and set the new return address */
695 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
697 *dontfillinexceptionstacktrace=true;
699 /* get the fieldinfo */
701 if (!(c = helper_resolve_classinfo(cr))) {
702 *dontfillinexceptionstacktrace=false;
706 /* patch back original code */
708 *((u8 *) ra) = mcode;
710 /* if we show disassembly, we have to skip the nop's */
715 /* patch class flags */
717 *((s4 *) (ra + 2)) = (s4) c->flags;
719 *dontfillinexceptionstacktrace=false;
724 /* patcher_checkcast_instanceof_interface **************************************
728 *******************************************************************************/
730 bool patcher_checkcast_instanceof_interface(u1 *sp)
734 constant_classref *cr;
737 /* get stuff from the stack */
739 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
740 mcode = *((u8 *) (sp + 1 * 8));
741 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
743 /* calculate and set the new return address */
746 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
748 *dontfillinexceptionstacktrace=true;
750 /* get the fieldinfo */
752 if (!(c = helper_resolve_classinfo(cr))) {
753 *dontfillinexceptionstacktrace=false;
757 /* patch back original code */
759 *((u8 *) ra) = mcode;
761 /* if we show disassembly, we have to skip the nop's */
766 /* patch super class index */
768 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
770 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
771 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
772 c->index * sizeof(methodptr*));
774 *dontfillinexceptionstacktrace=false;
779 /* patcher_checkcast_class *****************************************************
783 *******************************************************************************/
785 bool patcher_checkcast_class(u1 *sp)
789 constant_classref *cr;
792 /* get stuff from the stack */
794 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
795 mcode = *((u8 *) (sp + 1 * 8));
796 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
798 /* calculate and set the new return address */
801 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
803 *dontfillinexceptionstacktrace=true;
805 /* get the fieldinfo */
807 if (!(c = helper_resolve_classinfo(cr))) {
808 *dontfillinexceptionstacktrace=false;
812 /* patch back original code */
814 *((u8 *) ra) = mcode;
816 /* if we show disassembly, we have to skip the nop's */
821 /* patch super class' vftbl */
823 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
824 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
826 *dontfillinexceptionstacktrace=false;
831 /* patcher_instanceof_class ****************************************************
835 *******************************************************************************/
837 bool patcher_instanceof_class(u1 *sp)
841 constant_classref *cr;
844 /* get stuff from the stack */
846 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
847 mcode = *((u8 *) (sp + 1 * 8));
848 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
850 /* calculate and set the new return address */
853 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
855 *dontfillinexceptionstacktrace=true;
857 /* get the fieldinfo */
859 if (!(c = helper_resolve_classinfo(cr))) {
860 *dontfillinexceptionstacktrace=false;
864 /* patch back original code */
866 *((u8 *) ra) = mcode;
868 /* if we show disassembly, we have to skip the nop's */
873 /* patch super class' vftbl */
875 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
877 *dontfillinexceptionstacktrace=false;
882 /* patcher_clinit **************************************************************
886 *******************************************************************************/
888 bool patcher_clinit(u1 *sp)
893 void *beginJavaStack;
895 /* get stuff from the stack */
897 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
898 mcode = *((u8 *) (sp + 1 * 8));
899 c = (classinfo *) *((ptrint *) (sp + 0 * 8));
900 beginJavaStack = (void*) (sp+2*8);
902 /*printf("beginJavaStack: %p, ra %p\n",beginJavaStack,ra);*/
903 /* calculate and set the new return address */
906 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
908 /* check if the class is initialized */
910 if (!c->initialized) {
913 /*struct native_stackframeinfo {
914 void *oldThreadspecificHeadValue;
915 void **addressOfThreadspecificHead;
917 void *beginOfJavaStackframe; only used if != 0
918 void *returnToFromNative;
920 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
921 native_stackframeinfo sfi;
922 sfi.returnToFromNative=(void*)ra;
923 sfi.beginOfJavaStackframe=beginJavaStack;
924 sfi.method=0; /*internal*/
925 sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
926 sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
927 *(sfi.addressOfThreadspecificHead)=&sfi;
929 init=initialize_class(c);
931 *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
939 /* patch back original code */
941 *((u8 *) ra) = mcode;
948 * These are local overrides for various environment variables in Emacs.
949 * Please do not remove this and leave it at the end of the file, where
950 * Emacs will automagically detect them.
951 * ---------------------------------------------------------------------
954 * indent-tabs-mode: t
958 * vim:noexpandtab:sw=4:ts=4: