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 3708 2005-11-18 00:30:10Z twisti $
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
45 #include "vm/options.h"
46 #include "vm/resolve.h"
47 #include "vm/references.h"
48 #include "vm/jit/patcher.h"
51 /* patcher_get_putstatic *******************************************************
55 <patched call position>
56 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
57 49 8b 32 mov (%r10),%rsi
59 *******************************************************************************/
61 bool patcher_get_putstatic(u1 *sp)
71 /* get stuff from the stack */
73 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
74 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
75 mcode = *((u8 *) (sp + 2 * 8));
76 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 8));
77 disp = *((s4 *) (sp + 0 * 8));
79 /* calculate and set the new return address */
82 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
86 /* get the fieldinfo */
88 if (!(fi = resolve_field_eager(uf))) {
94 /* check if the field's class is initialized */
96 if (!initialize_class(fi->class)) {
102 /* patch back original code */
104 *((u8 *) ra) = mcode;
106 /* if we show disassembly, we have to skip the nop's */
108 if (opt_showdisassemble)
111 /* get RIP offset from machine instruction */
113 offset = *((u4 *) (ra + 3));
115 /* patch the field value's address (+ 7: is the size of the RIP move) */
117 *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
119 PATCHER_MARK_PATCHED_MONITOREXIT;
125 /* patcher_get_putfield ********************************************************
129 <patched call position>
130 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
132 *******************************************************************************/
134 bool patcher_get_putfield(u1 *sp)
137 java_objectheader *o;
139 unresolved_field *uf;
143 /* get stuff from the stack */
145 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
146 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
147 mcode = *((u8 *) (sp + 2 * 8));
148 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 8));
150 /* calculate and set the new return address */
153 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
155 PATCHER_MONITORENTER;
157 /* get the fieldinfo */
159 if (!(fi = resolve_field_eager(uf))) {
165 /* patch back original code (instruction code is smaller than 8 bytes) */
167 *((u4 *) (ra + 0)) = (u4) mcode;
168 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
170 /* if we show disassembly, we have to skip the nop's */
172 if (opt_showdisassemble)
175 /* patch the field's offset: we check for the field type, because the */
176 /* instructions have different lengths */
178 if (IS_INT_LNG_TYPE(fi->type)) {
179 /* check for special case: %rsp or %r12 as base register */
184 *((u4 *) (ra + 4)) = (u4) (fi->offset);
186 *((u4 *) (ra + 3)) = (u4) (fi->offset);
189 /* check for special case: %rsp or %r12 as base register */
194 *((u4 *) (ra + 6)) = (u4) (fi->offset);
196 *((u4 *) (ra + 5)) = (u4) (fi->offset);
199 PATCHER_MARK_PATCHED_MONITOREXIT;
205 /* patcher_putfieldconst *******************************************************
209 <patched call position>
210 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
212 *******************************************************************************/
214 bool patcher_putfieldconst(u1 *sp)
217 java_objectheader *o;
219 unresolved_field *uf;
222 /* get stuff from the stack */
224 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
225 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
226 mcode = *((u8 *) (sp + 2 * 8));
227 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 8));
229 /* calculate and set the new return address */
232 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
234 PATCHER_MONITORENTER;
236 /* get the fieldinfo */
238 if (!(fi = resolve_field_eager(uf))) {
244 /* patch back original code */
246 *((u8 *) ra) = mcode;
248 /* if we show disassembly, we have to skip the nop's */
250 if (opt_showdisassemble)
253 /* patch the field's offset */
255 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
256 /* handle special case when the base register is %r12 */
258 if (*(ra + 2) == 0x84) {
259 *((u4 *) (ra + 4)) = (u4) (fi->offset);
260 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
263 *((u4 *) (ra + 3)) = (u4) (fi->offset);
264 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
268 /* handle special case when the base register is %r12 */
270 if (*(ra + 2) == 0x84)
271 *((u4 *) (ra + 4)) = (u4) (fi->offset);
273 *((u4 *) (ra + 3)) = (u4) (fi->offset);
276 PATCHER_MARK_PATCHED_MONITOREXIT;
282 /* patcher_aconst **************************************************************
286 <patched call position>
287 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
289 *******************************************************************************/
291 bool patcher_aconst(u1 *sp)
294 java_objectheader *o;
296 constant_classref *cr;
299 /* get stuff from the stack */
301 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
302 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
303 mcode = *((u8 *) (sp + 2 * 8));
304 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
306 /* calculate and set the new return address */
309 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
311 PATCHER_MONITORENTER;
313 /* get the classinfo */
315 if (!(c = resolve_classref_eager(cr))) {
321 if (!use_class_as_object(c)) {
327 /* patch back original code */
329 *((u8 *) ra) = mcode;
331 /* if we show disassembly, we have to skip the nop's */
333 if (opt_showdisassemble)
336 /* patch the classinfo pointer */
338 *((ptrint *) (ra + 2)) = (ptrint) c;
340 PATCHER_MARK_PATCHED_MONITOREXIT;
346 /* patcher_builtin_multianewarray **********************************************
350 <patched call position>
351 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
352 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
353 48 89 e2 mov %rsp,%rdx
354 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
357 *******************************************************************************/
359 bool patcher_builtin_multianewarray(u1 *sp)
362 java_objectheader *o;
364 constant_classref *cr;
367 /* get stuff from the stack */
369 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
370 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
371 mcode = *((u8 *) (sp + 2 * 8));
372 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
374 /* calculate and set the new return address */
377 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
379 PATCHER_MONITORENTER;
381 /* get the classinfo */
383 if (!(c = resolve_classref_eager(cr))) {
389 /* patch back original code */
391 *((u8 *) ra) = mcode;
393 /* if we show disassembly, we have to skip the nop's */
395 if (opt_showdisassemble)
398 /* patch the classinfo pointer */
400 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
402 /* patch new function address */
404 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
406 PATCHER_MARK_PATCHED_MONITOREXIT;
412 /* patcher_builtin_arraycheckcast **********************************************
416 <patched call position>
417 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
418 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
421 *******************************************************************************/
423 bool patcher_builtin_arraycheckcast(u1 *sp)
426 java_objectheader *o;
428 constant_classref *cr;
431 /* get stuff from the stack */
433 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
434 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
435 mcode = *((u8 *) (sp + 2 * 8));
436 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
438 /* calculate and set the new return address */
441 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
443 PATCHER_MONITORENTER;
445 /* get the classinfo */
447 if (!(c = resolve_classref_eager(cr))) {
453 /* patch back original code */
455 *((u8 *) ra) = mcode;
457 /* if we show disassembly, we have to skip the nop's */
459 if (opt_showdisassemble)
462 /* patch the classinfo pointer */
464 *((ptrint *) (ra + 2)) = (ptrint) c;
466 PATCHER_MARK_PATCHED_MONITOREXIT;
472 /* patcher_invokestatic_special ************************************************
476 <patched call position>
477 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
480 *******************************************************************************/
482 bool patcher_invokestatic_special(u1 *sp)
485 java_objectheader *o;
487 unresolved_method *um;
490 /* get stuff from the stack */
492 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
493 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
494 mcode = *((u8 *) (sp + 2 * 8));
495 um = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
497 /* calculate and set the new return address */
500 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
502 PATCHER_MONITORENTER;
504 /* get the fieldinfo */
506 if (!(m = resolve_method_eager(um))) {
511 /* patch back original code */
513 *((u8 *) ra) = mcode;
515 /* if we show disassembly, we have to skip the nop's */
517 if (opt_showdisassemble)
520 /* patch stubroutine */
522 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
524 PATCHER_MARK_PATCHED_MONITOREXIT;
530 /* patcher_invokevirtual *******************************************************
534 <patched call position>
535 4c 8b 17 mov (%rdi),%r10
536 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
539 *******************************************************************************/
541 bool patcher_invokevirtual(u1 *sp)
544 java_objectheader *o;
546 unresolved_method *um;
549 /* get stuff from the stack */
551 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
552 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
553 mcode = *((u8 *) (sp + 2 * 8));
554 um = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
556 /* calculate and set the new return address */
559 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
561 PATCHER_MONITORENTER;
563 /* get the fieldinfo */
565 if (!(m = resolve_method_eager(um))) {
571 /* patch back original code */
573 *((u8 *) ra) = mcode;
575 /* if we show disassembly, we have to skip the nop's */
577 if (opt_showdisassemble)
580 /* patch vftbl index */
582 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
583 sizeof(methodptr) * m->vftblindex);
585 PATCHER_MARK_PATCHED_MONITOREXIT;
591 /* patcher_invokeinterface *****************************************************
595 <patched call position>
596 4c 8b 17 mov (%rdi),%r10
597 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
598 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
601 *******************************************************************************/
603 bool patcher_invokeinterface(u1 *sp)
606 java_objectheader *o;
608 unresolved_method *um;
611 /* get stuff from the stack */
613 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
614 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
615 mcode = *((u8 *) (sp + 2 * 8));
616 um = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
618 /* calculate and set the new return address */
621 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
623 PATCHER_MONITORENTER;
625 /* get the fieldinfo */
627 if (!(m = resolve_method_eager(um))) {
633 /* patch back original code */
635 *((u8 *) ra) = mcode;
637 /* if we show disassembly, we have to skip the nop's */
639 if (opt_showdisassemble)
642 /* patch interfacetable index */
644 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
645 sizeof(methodptr) * m->class->index);
647 /* patch method offset */
649 *((s4 *) (ra + 3 + 7 + 3)) =
650 (s4) (sizeof(methodptr) * (m - m->class->methods));
652 PATCHER_MARK_PATCHED_MONITOREXIT;
658 /* patcher_checkcast_instanceof_flags ******************************************
662 <patched call position>
663 41 ba 00 00 00 00 mov $0x0,%r10d
664 41 81 e2 00 02 00 00 and $0x200,%r10d
665 0f 84 35 00 00 00 je 0x00002aaaaab01479
667 *******************************************************************************/
669 bool patcher_checkcast_instanceof_flags(u1 *sp)
672 java_objectheader *o;
674 constant_classref *cr;
677 /* get stuff from the stack */
679 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
680 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
681 mcode = *((u8 *) (sp + 2 * 8));
682 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
684 /* calculate and set the new return address */
687 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
689 PATCHER_MONITORENTER;
691 /* get the fieldinfo */
693 if (!(c = resolve_classref_eager(cr))) {
699 /* patch back original code */
701 *((u8 *) ra) = mcode;
703 /* if we show disassembly, we have to skip the nop's */
705 if (opt_showdisassemble)
708 /* patch class flags */
710 *((s4 *) (ra + 2)) = (s4) c->flags;
712 PATCHER_MARK_PATCHED_MONITOREXIT;
718 /* patcher_checkcast_instanceof_interface **************************************
722 <patched call position>
723 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
724 49 81 eb 00 00 00 00 sub $0x0,%r11
725 4d 85 db test %r11,%r11
726 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
727 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
729 *******************************************************************************/
731 bool patcher_checkcast_instanceof_interface(u1 *sp)
734 java_objectheader *o;
736 constant_classref *cr;
739 /* get stuff from the stack */
741 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
742 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
743 mcode = *((u8 *) (sp + 2 * 8));
744 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
746 /* calculate and set the new return address */
749 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
751 PATCHER_MONITORENTER;
753 /* get the fieldinfo */
755 if (!(c = resolve_classref_eager(cr))) {
761 /* patch back original code */
763 *((u8 *) ra) = mcode;
765 /* if we show disassembly, we have to skip the nop's */
767 if (opt_showdisassemble)
770 /* patch super class index */
772 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
774 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
775 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
776 c->index * sizeof(methodptr*));
778 PATCHER_MARK_PATCHED_MONITOREXIT;
784 /* patcher_checkcast_class *****************************************************
788 <patched call position>
789 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
790 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
791 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
792 4d 29 da sub %r11,%r10
793 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
795 *******************************************************************************/
797 bool patcher_checkcast_class(u1 *sp)
800 java_objectheader *o;
802 constant_classref *cr;
805 /* get stuff from the stack */
807 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
808 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
809 mcode = *((u8 *) (sp + 2 * 8));
810 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
812 /* calculate and set the new return address */
815 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
817 PATCHER_MONITORENTER;
819 /* get the fieldinfo */
821 if (!(c = resolve_classref_eager(cr))) {
827 /* patch back original code */
829 *((u8 *) ra) = mcode;
831 /* if we show disassembly, we have to skip the nop's */
833 if (opt_showdisassemble)
836 /* patch super class' vftbl */
838 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
839 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
841 PATCHER_MARK_PATCHED_MONITOREXIT;
847 /* patcher_instanceof_class ****************************************************
851 <patched call position>
852 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
854 *******************************************************************************/
856 bool patcher_instanceof_class(u1 *sp)
859 java_objectheader *o;
861 constant_classref *cr;
864 /* get stuff from the stack */
866 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
867 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
868 mcode = *((u8 *) (sp + 2 * 8));
869 cr = (constant_classref *) *((ptrint *) (sp + 1 * 8));
871 /* calculate and set the new return address */
874 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
876 PATCHER_MONITORENTER;
878 /* get the fieldinfo */
880 if (!(c = resolve_classref_eager(cr))) {
886 /* patch back original code */
888 *((u8 *) ra) = mcode;
890 /* if we show disassembly, we have to skip the nop's */
892 if (opt_showdisassemble)
895 /* patch super class' vftbl */
897 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
899 PATCHER_MARK_PATCHED_MONITOREXIT;
905 /* patcher_clinit **************************************************************
907 May be used for GET/PUTSTATIC and in native stub.
911 <patched call position>
912 4d 8b 15 92 ff ff ff mov -110(%rip),%r10
913 49 89 1a mov %rbx,(%r10)
915 *******************************************************************************/
917 bool patcher_clinit(u1 *sp)
920 java_objectheader *o;
924 /* get stuff from the stack */
926 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
927 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
928 mcode = *((u8 *) (sp + 2 * 8));
929 c = (classinfo *) *((ptrint *) (sp + 1 * 8));
931 /* calculate and set the new return address */
934 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
936 PATCHER_MONITORENTER;
938 /* check if the class is initialized */
940 if (!initialize_class(c)) {
946 /* patch back original code */
948 *((u8 *) ra) = mcode;
950 PATCHER_MARK_PATCHED_MONITOREXIT;
956 /* patcher_athrow_areturn ******************************************************
960 <patched call position>
962 *******************************************************************************/
964 bool patcher_athrow_areturn(u1 *sp)
967 java_objectheader *o;
969 unresolved_class *uc;
972 /* get stuff from the stack */
974 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
975 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
976 mcode = *((u8 *) (sp + 2 * 8));
977 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 8));
979 /* calculate and set the new return address */
982 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
984 PATCHER_MONITORENTER;
986 /* resolve the class */
988 if (!resolve_class(uc, resolveEager, false, &c)) {
994 /* patch back original code */
996 *((u8 *) ra) = mcode;
998 PATCHER_MARK_PATCHED_MONITOREXIT;
1004 /* patcher_resolve_native ******************************************************
1008 <patched call position>
1009 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
1010 48 ff d0 callq *%rax
1012 *******************************************************************************/
1014 #if !defined(ENABLE_STATICVM)
1015 bool patcher_resolve_native(u1 *sp)
1018 java_objectheader *o;
1023 /* get stuff from the stack */
1025 ra = (u1 *) *((ptrint *) (sp + 4 * 8));
1026 o = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
1027 mcode = *((u8 *) (sp + 2 * 8));
1028 m = (methodinfo *) *((ptrint *) (sp + 1 * 8));
1030 /* calculate and set the new return address */
1033 *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
1035 PATCHER_MONITORENTER;
1037 /* resolve native function */
1039 if (!(f = native_resolve_function(m))) {
1040 PATCHER_MONITOREXIT;
1045 /* patch back original code */
1047 *((u8 *) ra) = mcode;
1049 /* if we show disassembly, we have to skip the nop's */
1051 if (opt_showdisassemble)
1054 /* patch native function pointer */
1056 *((ptrint *) (ra + 2)) = (ptrint) f;
1058 PATCHER_MARK_PATCHED_MONITOREXIT;
1062 #endif /* !defined(ENABLE_STATICVM) */
1066 * These are local overrides for various environment variables in Emacs.
1067 * Please do not remove this and leave it at the end of the file, where
1068 * Emacs will automagically detect them.
1069 * ---------------------------------------------------------------------
1072 * indent-tabs-mode: t
1076 * vim:noexpandtab:sw=4:ts=4: