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 2391 2005-04-26 19:49:15Z 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 *******************************************************
52 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
54 *******************************************************************************/
56 bool patcher_get_putstatic(u1 *sp)
65 /* get stuff from the stack */
67 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
68 mcode = *((u8 *) (sp + 1 * 8));
69 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
70 beginJavaStack= (void*)(sp+2*8);
71 /* calculate and set the new return address */
74 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
76 *dontfillinexceptionstacktrace=true;
77 /* get the fieldinfo */
78 if (!(fi = helper_resolve_fieldinfo(uf)))
80 *dontfillinexceptionstacktrace=false;
84 /* check if the field's class is initialized */
85 *dontfillinexceptionstacktrace=false;
86 if (!fi->class->initialized) {
89 /*struct native_stackframeinfo {
90 void *oldThreadspecificHeadValue;
91 void **addressOfThreadspecificHead;
93 void *beginOfJavaStackframe; only used if != 0
94 void *returnToFromNative;
96 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
97 native_stackframeinfo sfi;
98 sfi.returnToFromNative=(void*)ra;
99 sfi.beginOfJavaStackframe=beginJavaStack;
100 sfi.method=0; /*internal*/
101 sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
102 sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
103 *(sfi.addressOfThreadspecificHead)=&sfi;
105 init=initialize_class(fi->class);
107 *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
115 *dontfillinexceptionstacktrace=false;
117 /* patch back original code */
119 *((u8 *) ra) = mcode;
121 /* if we show disassembly, we have to skip the nop's */
126 /* get RIP offset from machine instruction */
128 ripoffset = *((u4 *) (ra + 3));
130 /* calculate address in data segment (+ 7: is the size of the RIP move) */
132 dataaddress = (ptrint *) (ra + ripoffset + 7);
134 /* patch the field value's address */
136 *dataaddress = (ptrint) &(fi->value);
142 /* patcher_get_putfield ********************************************************
146 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
148 *******************************************************************************/
150 bool patcher_get_putfield(u1 *sp)
154 unresolved_field *uf;
157 /* get stuff from the stack */
159 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
160 mcode = *((u8 *) (sp + 1 * 8));
161 uf = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
163 /* calculate and set the new return address */
166 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
168 *dontfillinexceptionstacktrace=true;
171 /* get the fieldinfo */
173 if (!(fi = helper_resolve_fieldinfo(uf)))
175 *dontfillinexceptionstacktrace=false;
179 /* patch back original code */
181 *((u8 *) ra) = mcode;
183 /* if we show disassembly, we have to skip the nop's */
188 /* patch the field's offset: we check for the field type, because the */
189 /* instructions have different lengths */
191 if (IS_FLT_DBL_TYPE(fi->type)) {
192 *((u4 *) (ra + 5)) = (u4) (fi->offset);
197 /* check for special case: %rsp or %r12 as base register */
202 *((u4 *) (ra + 4)) = (u4) (fi->offset);
204 *((u4 *) (ra + 3)) = (u4) (fi->offset);
207 *dontfillinexceptionstacktrace=false;
212 /* patcher_builtin_new *********************************************************
216 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
217 <patched call position>
218 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
221 *******************************************************************************/
223 bool patcher_builtin_new(u1 *sp)
227 constant_classref *cr;
230 /* get stuff from the stack */
232 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
233 mcode = *((u8 *) (sp + 1 * 8));
234 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
236 /* calculate and set the new return address */
239 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
241 *dontfillinexceptionstacktrace=true;
243 /* get the classinfo */
245 if (!(c = helper_resolve_classinfo(cr)))
247 *dontfillinexceptionstacktrace=false;
251 /* patch back original code */
253 *((u8 *) (ra + 10)) = mcode;
255 /* patch the classinfo pointer */
257 *((ptrint *) (ra + 2)) = (ptrint) c;
259 /* if we show disassembly, we have to skip the nop's */
264 /* patch new function address */
266 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
268 *dontfillinexceptionstacktrace=false;
273 /* patcher_builtin_newarray ****************************************************
277 48 be 88 13 9b 00 00 00 00 00 mov $0x9b1388,%rsi
278 <patched call position>
279 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
282 *******************************************************************************/
284 bool patcher_builtin_newarray(u1 *sp)
288 constant_classref *cr;
291 /* get stuff from the stack */
293 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
294 mcode = *((u8 *) (sp + 1 * 8));
295 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
297 /* calculate and set the new return address */
300 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
302 *dontfillinexceptionstacktrace=true;
304 /* get the classinfo */
306 if (!(c = helper_resolve_classinfo(cr))) {
307 *dontfillinexceptionstacktrace=false;
311 /* patch back original code */
313 *((u8 *) (ra + 10)) = mcode;
315 /* patch the class' vftbl pointer */
317 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
319 /* if we show disassembly, we have to skip the nop's */
324 /* patch new function address */
326 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
328 *dontfillinexceptionstacktrace=false;
333 /* patcher_builtin_multianewarray **********************************************
337 <patched call position>
338 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
339 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
340 48 89 e2 mov %rsp,%rdx
341 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
344 *******************************************************************************/
346 bool patcher_builtin_multianewarray(u1 *sp)
350 constant_classref *cr;
353 /* get stuff from the stack */
355 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
356 mcode = *((u8 *) (sp + 1 * 8));
357 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
359 /* calculate and set the new return address */
362 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
364 *dontfillinexceptionstacktrace=true;
366 /* get the classinfo */
368 if (!(c = helper_resolve_classinfo(cr))) {
369 *dontfillinexceptionstacktrace=false;
373 /* patch back original code */
375 *((u8 *) ra) = mcode;
377 /* if we show disassembly, we have to skip the nop's */
382 /* patch the class' vftbl pointer */
384 *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
386 /* patch new function address */
388 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
390 *dontfillinexceptionstacktrace=false;
395 /* patcher_builtin_checkarraycast **********************************************
399 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
400 <patched call position>
401 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
404 *******************************************************************************/
406 bool patcher_builtin_checkarraycast(u1 *sp)
410 constant_classref *cr;
413 /* get stuff from the stack */
415 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
416 mcode = *((u8 *) (sp + 1 * 8));
417 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
419 /* calculate and set the new return address */
422 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
424 *dontfillinexceptionstacktrace=true;
426 /* get the classinfo */
428 if (!(c = helper_resolve_classinfo(cr))) {
429 *dontfillinexceptionstacktrace=false;
433 /* patch back original code */
435 *((u8 *) (ra + 10)) = mcode;
437 /* if we show disassembly, we have to skip the nop's */
442 /* patch the class' vftbl pointer */
444 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
446 /* patch new function address */
448 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_checkarraycast;
450 *dontfillinexceptionstacktrace=false;
455 /* patcher_builtin_arrayinstanceof *********************************************
459 48 be 30 3c b2 00 00 00 00 00 mov $0xb23c30,%rsi
460 <patched call position>
461 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
464 *******************************************************************************/
466 bool patcher_builtin_arrayinstanceof(u1 *sp)
470 constant_classref *cr;
473 /* get stuff from the stack */
475 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
476 mcode = *((u8 *) (sp + 1 * 8));
477 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
479 /* calculate and set the new return address */
482 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
484 *dontfillinexceptionstacktrace=true;
486 /* get the classinfo */
488 if (!(c = helper_resolve_classinfo(cr))) {
489 *dontfillinexceptionstacktrace=false;
493 /* patch back original code */
495 *((u8 *) (ra + 10)) = mcode;
497 /* if we show disassembly, we have to skip the nop's */
502 /* patch the class' vftbl pointer */
504 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
506 /* patch new function address */
508 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
510 *dontfillinexceptionstacktrace=false;
515 /* patcher_invokestatic_special ************************************************
519 *******************************************************************************/
521 bool patcher_invokestatic_special(u1 *sp)
525 unresolved_method *um;
528 /* get stuff from the stack */
530 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
531 mcode = *((u8 *) (sp + 1 * 8));
532 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
534 /* calculate and set the new return address */
537 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
539 *dontfillinexceptionstacktrace=true;
542 /* get the fieldinfo */
544 if (!(m = helper_resolve_methodinfo(um)))
546 *dontfillinexceptionstacktrace=false;
549 /* patch back original code */
551 *((u8 *) ra) = mcode;
553 /* if we show disassembly, we have to skip the nop's */
558 /* patch stubroutine */
560 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
562 *dontfillinexceptionstacktrace=false;
567 /* patcher_invokevirtual *******************************************************
571 *******************************************************************************/
573 bool patcher_invokevirtual(u1 *sp)
577 unresolved_method *um;
580 /* get stuff from the stack */
582 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
583 mcode = *((u8 *) (sp + 1 * 8));
584 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
586 /* calculate and set the new return address */
589 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
591 *dontfillinexceptionstacktrace=true;
593 /* get the fieldinfo */
595 if (!(m = helper_resolve_methodinfo(um)))
597 *dontfillinexceptionstacktrace=false;
601 /* patch back original code */
603 *((u8 *) ra) = mcode;
605 /* if we show disassembly, we have to skip the nop's */
610 /* patch vftbl index */
612 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
613 sizeof(methodptr) * m->vftblindex);
615 *dontfillinexceptionstacktrace=false;
620 /* patcher_invokeinterface *****************************************************
624 *******************************************************************************/
626 bool patcher_invokeinterface(u1 *sp)
630 unresolved_method *um;
633 /* get stuff from the stack */
635 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
636 mcode = *((u8 *) (sp + 1 * 8));
637 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
639 /* calculate and set the new return address */
642 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
644 *dontfillinexceptionstacktrace=true;
646 /* get the fieldinfo */
648 if (!(m = helper_resolve_methodinfo(um)))
650 *dontfillinexceptionstacktrace=false;
654 /* patch back original code */
656 *((u8 *) ra) = mcode;
658 /* if we show disassembly, we have to skip the nop's */
663 /* patch interfacetable index */
665 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
666 sizeof(methodptr) * m->class->index);
668 /* patch method offset */
670 *((s4 *) (ra + 3 + 7 + 3)) =
671 (s4) (sizeof(methodptr) * (m - m->class->methods));
673 *dontfillinexceptionstacktrace=false;
678 /* patcher_checkcast_instanceof_flags ******************************************
682 *******************************************************************************/
684 bool patcher_checkcast_instanceof_flags(u1 *sp)
688 constant_classref *cr;
691 /* get stuff from the stack */
693 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
694 mcode = *((u8 *) (sp + 1 * 8));
695 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
697 /* calculate and set the new return address */
700 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
702 *dontfillinexceptionstacktrace=true;
704 /* get the fieldinfo */
706 if (!(c = helper_resolve_classinfo(cr))) {
707 *dontfillinexceptionstacktrace=false;
711 /* patch back original code */
713 *((u8 *) ra) = mcode;
715 /* if we show disassembly, we have to skip the nop's */
720 /* patch class flags */
722 *((s4 *) (ra + 2)) = (s4) c->flags;
724 *dontfillinexceptionstacktrace=false;
729 /* patcher_checkcast_instanceof_interface **************************************
733 *******************************************************************************/
735 bool patcher_checkcast_instanceof_interface(u1 *sp)
739 constant_classref *cr;
742 /* get stuff from the stack */
744 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
745 mcode = *((u8 *) (sp + 1 * 8));
746 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
748 /* calculate and set the new return address */
751 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
753 *dontfillinexceptionstacktrace=true;
755 /* get the fieldinfo */
757 if (!(c = helper_resolve_classinfo(cr))) {
758 *dontfillinexceptionstacktrace=false;
762 /* patch back original code */
764 *((u8 *) ra) = mcode;
766 /* if we show disassembly, we have to skip the nop's */
771 /* patch super class index */
773 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
775 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
776 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
777 c->index * sizeof(methodptr*));
779 *dontfillinexceptionstacktrace=false;
784 /* patcher_checkcast_class *****************************************************
788 *******************************************************************************/
790 bool patcher_checkcast_class(u1 *sp)
794 constant_classref *cr;
797 /* get stuff from the stack */
799 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
800 mcode = *((u8 *) (sp + 1 * 8));
801 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
803 /* calculate and set the new return address */
806 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
808 *dontfillinexceptionstacktrace=true;
810 /* get the fieldinfo */
812 if (!(c = helper_resolve_classinfo(cr))) {
813 *dontfillinexceptionstacktrace=false;
817 /* patch back original code */
819 *((u8 *) ra) = mcode;
821 /* if we show disassembly, we have to skip the nop's */
826 /* patch super class' vftbl */
828 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
829 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
831 *dontfillinexceptionstacktrace=false;
836 /* patcher_instanceof_class ****************************************************
840 *******************************************************************************/
842 bool patcher_instanceof_class(u1 *sp)
846 constant_classref *cr;
849 /* get stuff from the stack */
851 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
852 mcode = *((u8 *) (sp + 1 * 8));
853 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
855 /* calculate and set the new return address */
858 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
860 *dontfillinexceptionstacktrace=true;
862 /* get the fieldinfo */
864 if (!(c = helper_resolve_classinfo(cr))) {
865 *dontfillinexceptionstacktrace=false;
869 /* patch back original code */
871 *((u8 *) ra) = mcode;
873 /* if we show disassembly, we have to skip the nop's */
878 /* patch super class' vftbl */
880 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
882 *dontfillinexceptionstacktrace=false;
887 /* patcher_clinit **************************************************************
891 *******************************************************************************/
893 bool patcher_clinit(u1 *sp)
898 void *beginJavaStack;
900 /* get stuff from the stack */
902 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
903 mcode = *((u8 *) (sp + 1 * 8));
904 c = (classinfo *) *((ptrint *) (sp + 0 * 8));
905 beginJavaStack = (void*) (sp+2*8);
907 /* calculate and set the new return address */
910 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
912 /* check if the class is initialized */
914 if (!c->initialized) {
917 /*struct native_stackframeinfo {
918 void *oldThreadspecificHeadValue;
919 void **addressOfThreadspecificHead;
921 void *beginOfJavaStackframe; only used if != 0
922 void *returnToFromNative;
924 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
925 native_stackframeinfo sfi;
926 sfi.returnToFromNative=(void*)ra;
927 sfi.beginOfJavaStackframe=beginJavaStack;
928 sfi.method=0; /*internal*/
929 sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
930 sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
931 *(sfi.addressOfThreadspecificHead)=&sfi;
933 init=initialize_class(c);
935 *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
943 /* patch back original code */
945 *((u8 *) ra) = mcode;
952 * These are local overrides for various environment variables in Emacs.
953 * Please do not remove this and leave it at the end of the file, where
954 * Emacs will automagically detect them.
955 * ---------------------------------------------------------------------
958 * indent-tabs-mode: t
962 * vim:noexpandtab:sw=4:ts=4: