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 2360 2005-04-24 13:07:57Z jowenn $
36 #include "vm/jit/x86_64/types.h"
37 #include "vm/builtin.h"
39 #include "vm/initialize.h"
40 #include "vm/references.h"
41 #include "vm/jit/helper.h"
42 #include "vm/exceptions.h"
44 /* patcher_get_putstatic *******************************************************
50 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
52 *******************************************************************************/
54 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 /* get RIP offset from machine instruction */
121 ripoffset = *((u4 *) (ra + 3));
123 /* calculate address in data segment (+ 7: is the size of the RIP move) */
125 dataaddress = (ptrint *) (ra + ripoffset + 7);
127 /* patch the field value's address */
129 *dataaddress = (ptrint) &(fi->value);
135 /* patcher_get_putfield ********************************************************
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 /* patch the field's offset: we check for the field type, because the */
179 /* instructions have different lengths */
181 if (IS_FLT_DBL_TYPE(fi->type)) {
182 *((u4 *) (ra + 5)) = (u4) (fi->offset);
187 /* check for special case: %rsp or %r12 as base register */
192 *((u4 *) (ra + 4)) = (u4) (fi->offset);
194 *((u4 *) (ra + 3)) = (u4) (fi->offset);
197 *dontfillinexceptionstacktrace=false;
202 /* patcher_builtin_new *********************************************************
208 *******************************************************************************/
210 bool patcher_builtin_new(constant_classref *cr, u1 *sp)
215 /* get stuff from the stack */
217 ra = (u1 *) *((ptrint *) (sp + 0 * 8));
219 /* calculate and set the new return address */
221 ra = ra - (10 + 10 + 3);
222 *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
224 *dontfillinexceptionstacktrace=true;
226 /* get the classinfo */
228 if (!(c = helper_resolve_classinfo(cr)))
230 *dontfillinexceptionstacktrace=false;
234 /* patch the classinfo pointer */
236 *((ptrint *) (ra + 2)) = (ptrint) c;
238 /* patch new function address */
240 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
242 *dontfillinexceptionstacktrace=false;
247 /* patcher_builtin_newarray ****************************************************
253 *******************************************************************************/
255 bool patcher_builtin_newarray(u1 *sp, constant_classref *cr)
260 /* get stuff from the stack */
262 ra = (u1 *) *((ptrint *) (sp + 0 * 8));
264 /* calculate and set the new return address */
266 ra = ra - (10 + 10 + 3);
267 *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
270 *dontfillinexceptionstacktrace=true;
273 /* get the classinfo */
275 if (!(c = helper_resolve_classinfo(cr)))
277 *dontfillinexceptionstacktrace=false;
280 /* patch the class' vftbl pointer */
282 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
284 /* patch new function address */
286 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
288 *dontfillinexceptionstacktrace=false;
293 /* patcher_builtin_multianewarray **********************************************
299 *******************************************************************************/
301 bool patcher_builtin_multianewarray(u1 *sp, constant_classref *cr)
306 /* get stuff from the stack */
308 ra = (u1 *) *((ptrint *) (sp + 0 * 8));
310 /* calculate and set the new return address */
312 ra = ra - (10 + 10 + 3 + 10 + 3);
313 *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
315 *dontfillinexceptionstacktrace=true;
317 /* get the classinfo */
319 if (!(c = helper_resolve_classinfo(cr))) {
320 *dontfillinexceptionstacktrace=false;
323 /* patch the class' vftbl pointer */
325 *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
327 /* patch new function address */
329 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
331 *dontfillinexceptionstacktrace=false;
336 /* patcher_builtin_checkarraycast **********************************************
342 *******************************************************************************/
344 bool patcher_builtin_checkarraycast(u1 *sp, constant_classref *cr)
349 /* get stuff from the stack */
351 ra = (u1 *) *((ptrint *) (sp + 0 * 8));
353 /* calculate and set the new return address */
355 ra = ra - (10 + 10 + 3);
356 *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
358 *dontfillinexceptionstacktrace=true;
360 /* get the classinfo */
362 if (!(c = helper_resolve_classinfo(cr)))
364 *dontfillinexceptionstacktrace=false;
368 /* patch the class' vftbl pointer */
370 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
372 /* patch new function address */
374 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_checkarraycast;
376 *dontfillinexceptionstacktrace=false;
381 /* patcher_builtin_arrayinstanceof *********************************************
387 *******************************************************************************/
389 bool patcher_builtin_arrayinstanceof(u1 *sp, constant_classref *cr)
394 /* get stuff from the stack */
396 ra = (u1 *) *((ptrint *) (sp + 0 * 8));
398 /* calculate and set the new return address */
400 ra = ra - (10 + 10 + 3);
401 *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
404 *dontfillinexceptionstacktrace=true;
407 /* get the classinfo */
409 if (!(c = helper_resolve_classinfo(cr)))
411 *dontfillinexceptionstacktrace=false;
415 /* patch the class' vftbl pointer */
417 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
419 /* patch new function address */
421 *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
423 *dontfillinexceptionstacktrace=false;
428 /* patcher_invokestatic_special ************************************************
432 *******************************************************************************/
434 bool patcher_invokestatic_special(u1 *sp)
438 unresolved_method *um;
441 /* get stuff from the stack */
443 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
444 mcode = *((u8 *) (sp + 1 * 8));
445 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
447 /* calculate and set the new return address */
450 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
452 *dontfillinexceptionstacktrace=true;
455 /* get the fieldinfo */
457 if (!(m = helper_resolve_methodinfo(um)))
459 *dontfillinexceptionstacktrace=false;
462 /* patch back original code */
464 *((u8 *) ra) = mcode;
466 /* patch stubroutine */
468 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
470 *dontfillinexceptionstacktrace=false;
475 /* patcher_invokevirtual *******************************************************
479 *******************************************************************************/
481 bool patcher_invokevirtual(u1 *sp)
485 unresolved_method *um;
488 /* get stuff from the stack */
490 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
491 mcode = *((u8 *) (sp + 1 * 8));
492 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
494 /* calculate and set the new return address */
497 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
499 *dontfillinexceptionstacktrace=true;
501 /* get the fieldinfo */
503 if (!(m = helper_resolve_methodinfo(um)))
505 *dontfillinexceptionstacktrace=false;
509 /* patch back original code */
511 *((u8 *) ra) = mcode;
513 /* patch vftbl index */
515 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
516 sizeof(methodptr) * m->vftblindex);
518 *dontfillinexceptionstacktrace=false;
523 /* patcher_invokeinterface *****************************************************
527 *******************************************************************************/
529 bool patcher_invokeinterface(u1 *sp)
533 unresolved_method *um;
536 /* get stuff from the stack */
538 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
539 mcode = *((u8 *) (sp + 1 * 8));
540 um = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
542 /* calculate and set the new return address */
545 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
547 *dontfillinexceptionstacktrace=true;
549 /* get the fieldinfo */
551 if (!(m = helper_resolve_methodinfo(um)))
553 *dontfillinexceptionstacktrace=false;
557 /* patch back original code */
559 *((u8 *) ra) = mcode;
561 /* patch interfacetable index */
563 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
564 sizeof(methodptr) * m->class->index);
566 /* patch method offset */
568 *((s4 *) (ra + 3 + 7 + 3)) =
569 (s4) (sizeof(methodptr) * (m - m->class->methods));
571 *dontfillinexceptionstacktrace=false;
576 /* patcher_checkcast_instanceof_flags ******************************************
580 *******************************************************************************/
582 bool patcher_checkcast_instanceof_flags(u1 *sp)
586 constant_classref *cr;
589 /* get stuff from the stack */
591 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
592 mcode = *((u8 *) (sp + 1 * 8));
593 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
595 /* calculate and set the new return address */
598 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
600 *dontfillinexceptionstacktrace=true;
602 /* get the fieldinfo */
604 if (!(c = helper_resolve_classinfo(cr)))
606 *dontfillinexceptionstacktrace=false;
609 /* patch back original code */
611 *((u8 *) ra) = mcode;
613 /* patch class flags */
615 *((s4 *) (ra + 2)) = (s4) c->flags;
617 *dontfillinexceptionstacktrace=false;
622 /* patcher_checkcast_instanceof_interface **************************************
626 *******************************************************************************/
628 bool patcher_checkcast_instanceof_interface(u1 *sp)
632 constant_classref *cr;
635 /* get stuff from the stack */
637 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
638 mcode = *((u8 *) (sp + 1 * 8));
639 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
641 /* calculate and set the new return address */
644 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
647 *dontfillinexceptionstacktrace=true;
649 /* get the fieldinfo */
651 if (!(c = helper_resolve_classinfo(cr)))
653 *dontfillinexceptionstacktrace=false;
657 /* patch back original code */
659 *((u8 *) ra) = mcode;
661 /* patch super class index */
663 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
665 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
666 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
667 c->index * sizeof(methodptr*));
669 *dontfillinexceptionstacktrace=false;
674 /* patcher_checkcast_class *****************************************************
678 *******************************************************************************/
680 bool patcher_checkcast_class(u1 *sp)
684 constant_classref *cr;
687 /* get stuff from the stack */
689 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
690 mcode = *((u8 *) (sp + 1 * 8));
691 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
693 /* calculate and set the new return address */
696 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
698 *dontfillinexceptionstacktrace=true;
700 /* get the fieldinfo */
702 if (!(c = helper_resolve_classinfo(cr)))
704 *dontfillinexceptionstacktrace=false;
708 /* patch back original code */
710 *((u8 *) ra) = mcode;
712 /* patch super class' vftbl */
714 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
715 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
717 *dontfillinexceptionstacktrace=false;
722 /* patcher_instanceof_class ****************************************************
726 *******************************************************************************/
728 bool patcher_instanceof_class(u1 *sp)
732 constant_classref *cr;
735 /* get stuff from the stack */
737 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
738 mcode = *((u8 *) (sp + 1 * 8));
739 cr = (constant_classref *) *((ptrint *) (sp + 0 * 8));
741 /* calculate and set the new return address */
744 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
746 *dontfillinexceptionstacktrace=true;
748 /* get the fieldinfo */
750 if (!(c = helper_resolve_classinfo(cr)))
752 *dontfillinexceptionstacktrace=false;
756 /* patch back original code */
758 *((u8 *) ra) = mcode;
760 /* patch super class' vftbl */
762 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
764 *dontfillinexceptionstacktrace=false;
769 /* patcher_clinit **************************************************************
773 *******************************************************************************/
775 bool patcher_clinit(u1 *sp)
780 void *beginJavaStack;
782 /* get stuff from the stack */
784 ra = (u1 *) *((ptrint *) (sp + 2 * 8));
785 mcode = *((u8 *) (sp + 1 * 8));
786 c = (classinfo *) *((ptrint *) (sp + 0 * 8));
787 beginJavaStack = (void*) (sp+2*8);
789 /* calculate and set the new return address */
792 *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
794 /* check if the class is initialized */
800 /*struct native_stackframeinfo {
801 void *oldThreadspecificHeadValue;
802 void **addressOfThreadspecificHead;
804 void *beginOfJavaStackframe; only used if != 0
805 void *returnToFromNative;
807 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
808 native_stackframeinfo sfi;
809 sfi.returnToFromNative=(void*)ra;
810 sfi.beginOfJavaStackframe=beginJavaStack;
811 sfi.method=0; /*internal*/
812 sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
813 sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
814 *(sfi.addressOfThreadspecificHead)=&sfi;
816 init=initialize_class(c);
818 *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
826 /* patch back original code */
828 *((u8 *) ra) = mcode;
835 * These are local overrides for various environment variables in Emacs.
836 * Please do not remove this and leave it at the end of the file, where
837 * Emacs will automagically detect them.
838 * ---------------------------------------------------------------------
841 * indent-tabs-mode: t
845 * vim:noexpandtab:sw=4:ts=4: