1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: patcher.c 8295 2007-08-11 17:57:24Z michi $
36 #include "vm/jit/x86_64/codegen.h"
38 #include "mm/memory.h"
40 #include "native/native.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
46 #include "vm/jit/patcher.h"
47 #include "vm/jit/stacktrace.h"
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vmcore/references.h"
53 #include "vm/resolve.h"
56 /* patcher_wrapper *************************************************************
58 Wrapper for all patchers. It also creates the stackframe info
61 If the return value of the patcher function is false, it gets the
62 exception object, clears the exception pointer and returns the
65 *******************************************************************************/
67 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
76 /* define the patcher function */
78 bool (*patcher_function)(u1 *);
80 /* get stuff from the stack */
82 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
83 o = (java_object_t *) *((ptrint *) (sp + 4 * 8));
84 f = (functionptr) *((ptrint *) (sp + 0 * 8));
86 /* calculate and set the new return address */
88 xpc = xpc - PATCHER_CALL_SIZE;
90 *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
92 /* cast the passed function to a patcher function */
94 patcher_function = (bool (*)(u1 *)) (ptrint) f;
96 /* enter a monitor on the patching position */
100 /* create the stackframeinfo */
102 /* RA is passed as NULL, but the XPC is correct and can be used in
103 stacktrace_create_extern_stackframeinfo for
104 md_codegen_get_pv_from_pc. */
106 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, xpc, xpc);
108 /* call the proper patcher function */
110 result = (patcher_function)(sp);
112 /* remove the stackframeinfo */
114 stacktrace_remove_stackframeinfo(&sfi);
116 /* check for return value and exit accordingly */
118 if (result == false) {
119 e = exceptions_get_and_clear_exception();
126 PATCHER_MARK_PATCHED_MONITOREXIT;
132 /* patcher_get_putstatic *******************************************************
136 <patched call position>
137 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
138 49 8b 32 mov (%r10),%rsi
140 *******************************************************************************/
142 bool patcher_get_putstatic(u1 *sp)
146 unresolved_field *uf;
150 /* get stuff from the stack */
152 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
153 mcode = *((u8 *) (sp + 3 * 8));
154 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
155 disp = *((s4 *) (sp + 1 * 8));
157 /* get the fieldinfo */
159 if (!(fi = resolve_field_eager(uf)))
162 /* check if the field's class is initialized */
164 if (!(fi->class->state & CLASS_INITIALIZED))
165 if (!initialize_class(fi->class))
168 /* patch back original code */
170 *((u8 *) ra) = mcode;
172 /* if we show disassembly, we have to skip the nop's */
177 /* patch the field value's address */
179 *((intptr_t *) (ra + 7 + disp)) = (intptr_t) fi->value;
185 /* patcher_get_putfield ********************************************************
189 <patched call position>
190 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
192 *******************************************************************************/
194 bool patcher_get_putfield(u1 *sp)
198 unresolved_field *uf;
202 /* get stuff from the stack */
204 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
205 mcode = *((u8 *) (sp + 3 * 8));
206 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
208 /* get the fieldinfo */
210 if (!(fi = resolve_field_eager(uf)))
213 /* patch back original code (instruction code is smaller than 8 bytes) */
215 *((u4 *) (ra + 0)) = (u4) mcode;
216 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
218 /* if we show disassembly, we have to skip the nop's */
223 /* patch the field's offset: we check for the field type, because the */
224 /* instructions have different lengths */
226 if (IS_INT_LNG_TYPE(fi->type)) {
227 /* check for special case: %rsp or %r12 as base register */
232 *((int32_t *) (ra + 4)) = fi->offset;
234 *((int32_t *) (ra + 3)) = fi->offset;
237 /* check for special case: %rsp or %r12 as base register */
242 *((int32_t *) (ra + 6)) = fi->offset;
244 *((int32_t *) (ra + 5)) = fi->offset;
251 /* patcher_putfieldconst *******************************************************
255 <patched call position>
256 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
258 *******************************************************************************/
260 bool patcher_putfieldconst(u1 *sp)
264 unresolved_field *uf;
267 /* get stuff from the stack */
269 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
270 mcode = *((u8 *) (sp + 3 * 8));
271 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
273 /* get the fieldinfo */
275 if (!(fi = resolve_field_eager(uf)))
278 /* patch back original code */
280 *((u8 *) ra) = mcode;
282 /* if we show disassembly, we have to skip the nop's */
287 /* patch the field's offset */
289 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
290 /* handle special case when the base register is %r12 */
292 if (*(ra + 2) == 0x84) {
293 *((uint32_t *) (ra + 4)) = fi->offset;
294 *((uint32_t *) (ra + 12 + 4)) = fi->offset + 4;
297 *((uint32_t *) (ra + 3)) = fi->offset;
298 *((uint32_t *) (ra + 11 + 3)) = fi->offset + 4;
302 /* handle special case when the base register is %r12 */
304 if (*(ra + 2) == 0x84)
305 *((uint32_t *) (ra + 4)) = fi->offset;
307 *((uint32_t *) (ra + 3)) = fi->offset;
314 /* patcher_aconst **************************************************************
318 <patched call position>
319 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
321 *******************************************************************************/
323 bool patcher_aconst(u1 *sp)
327 constant_classref *cr;
330 /* get stuff from the stack */
332 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
333 mcode = *((u8 *) (sp + 3 * 8));
334 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
336 /* get the classinfo */
338 if (!(c = resolve_classref_eager(cr)))
341 /* patch back original code */
343 *((u8 *) ra) = mcode;
345 /* if we show disassembly, we have to skip the nop's */
350 /* patch the classinfo pointer */
352 *((ptrint *) (ra + 2)) = (ptrint) c;
358 /* patcher_builtin_multianewarray **********************************************
362 <patched call position>
363 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
364 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
365 48 89 e2 mov %rsp,%rdx
366 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
369 *******************************************************************************/
371 bool patcher_builtin_multianewarray(u1 *sp)
375 constant_classref *cr;
378 /* get stuff from the stack */
380 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
381 mcode = *((u8 *) (sp + 3 * 8));
382 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
384 /* get the classinfo */
386 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 */
398 /* patch the classinfo pointer */
400 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
406 /* patcher_builtin_arraycheckcast **********************************************
410 <patched call position>
411 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
412 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
415 *******************************************************************************/
417 bool patcher_builtin_arraycheckcast(u1 *sp)
421 constant_classref *cr;
424 /* get stuff from the stack */
426 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
427 mcode = *((u8 *) (sp + 3 * 8));
428 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
430 /* get the classinfo */
432 if (!(c = resolve_classref_eager(cr)))
435 /* patch back original code */
437 *((u8 *) ra) = mcode;
439 /* if we show disassembly, we have to skip the nop's */
444 /* patch the classinfo pointer */
446 *((ptrint *) (ra + 2)) = (ptrint) c;
452 /* patcher_invokestatic_special ************************************************
456 <patched call position>
457 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
460 *******************************************************************************/
462 bool patcher_invokestatic_special(u1 *sp)
466 unresolved_method *um;
470 /* get stuff from the stack */
472 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
473 mcode = *((u8 *) (sp + 3 * 8));
474 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
475 disp = *((s4 *) (sp + 1 * 8));
477 /* get the fieldinfo */
479 if (!(m = resolve_method_eager(um)))
482 /* patch back original code */
484 *((u8 *) ra) = mcode;
486 /* if we show disassembly, we have to skip the nop's */
489 ra = ra + PATCHER_CALL_SIZE;
491 /* patch stubroutine */
493 /* *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
494 *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
500 /* patcher_invokevirtual *******************************************************
504 <patched call position>
505 4c 8b 17 mov (%rdi),%r10
506 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
509 *******************************************************************************/
511 bool patcher_invokevirtual(u1 *sp)
515 unresolved_method *um;
518 /* get stuff from the stack */
520 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
521 mcode = *((u8 *) (sp + 3 * 8));
522 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
524 /* get the fieldinfo */
526 if (!(m = resolve_method_eager(um)))
529 /* patch back original code */
531 *((u8 *) ra) = mcode;
533 /* if we show disassembly, we have to skip the nop's */
538 /* patch vftbl index */
540 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
541 sizeof(methodptr) * m->vftblindex);
547 /* patcher_invokeinterface *****************************************************
551 <patched call position>
552 4c 8b 17 mov (%rdi),%r10
553 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
554 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
557 *******************************************************************************/
559 bool patcher_invokeinterface(u1 *sp)
563 unresolved_method *um;
566 /* get stuff from the stack */
568 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
569 mcode = *((u8 *) (sp + 3 * 8));
570 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
572 /* get the fieldinfo */
574 if (!(m = resolve_method_eager(um)))
577 /* patch back original code */
579 *((u8 *) ra) = mcode;
581 /* if we show disassembly, we have to skip the nop's */
586 /* patch interfacetable index */
588 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
589 sizeof(methodptr) * m->class->index);
591 /* patch method offset */
593 *((s4 *) (ra + 3 + 7 + 3)) =
594 (s4) (sizeof(methodptr) * (m - m->class->methods));
600 /* patcher_checkcast_instanceof_flags ******************************************
604 <patched call position>
605 41 ba 00 00 00 00 mov $0x0,%r10d
606 41 81 e2 00 02 00 00 and $0x200,%r10d
607 0f 84 35 00 00 00 je 0x00002aaaaab01479
609 *******************************************************************************/
611 bool patcher_checkcast_instanceof_flags(u1 *sp)
615 constant_classref *cr;
618 /* get stuff from the stack */
620 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
621 mcode = *((u8 *) (sp + 3 * 8));
622 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
624 /* get the fieldinfo */
626 if (!(c = resolve_classref_eager(cr)))
629 /* patch back original code */
631 *((u8 *) ra) = mcode;
633 /* if we show disassembly, we have to skip the nop's */
638 /* patch class flags */
640 *((s4 *) (ra + 2)) = (s4) c->flags;
646 /* patcher_checkcast_interface *************************************************
650 <patched call position>
651 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
652 41 81 fb 00 00 00 00 cmp $0x0,%r11d
653 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
654 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
655 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
657 *******************************************************************************/
659 bool patcher_checkcast_interface(u1 *sp)
663 constant_classref *cr;
666 /* get stuff from the stack */
668 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
669 mcode = *((u8 *) (sp + 3 * 8));
670 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
672 /* get the fieldinfo */
674 if (!(c = resolve_classref_eager(cr)))
677 /* patch back original code */
679 *((u8 *) ra) = mcode;
681 /* if we show disassembly, we have to skip the nop's */
684 ra = ra + PATCHER_CALL_SIZE;
686 /* patch super class index */
688 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
690 *((s4 *) (ra + 7 + 7 + 6 + 8 + 3)) =
691 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
692 c->index * sizeof(methodptr*));
698 /* patcher_checkcast_class *****************************************************
702 <patched call position>
703 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
704 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
705 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
706 4d 29 da sub %r11,%r10
707 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
709 *******************************************************************************/
711 bool patcher_checkcast_class(u1 *sp)
715 constant_classref *cr;
718 /* get stuff from the stack */
720 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
721 mcode = *((u8 *) (sp + 3 * 8));
722 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
724 /* get the fieldinfo */
726 if (!(c = resolve_classref_eager(cr)))
729 /* patch back original code */
731 *((u8 *) ra) = mcode;
733 /* if we show disassembly, we have to skip the nop's */
738 /* patch super class' vftbl */
740 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
741 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
747 /* patcher_instanceof_interface ************************************************
751 <patched call position>
752 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
753 41 81 fb 00 00 00 00 cmp $0x0,%r11d
754 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
755 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
757 *******************************************************************************/
759 bool patcher_instanceof_interface(u1 *sp)
763 constant_classref *cr;
766 /* get stuff from the stack */
768 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
769 mcode = *((u8 *) (sp + 3 * 8));
770 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
772 /* get the fieldinfo */
774 if (!(c = resolve_classref_eager(cr)))
777 /* patch back original code */
779 *((u8 *) ra) = mcode;
781 /* if we show disassembly, we have to skip the nop's */
784 ra = ra + PATCHER_CALL_SIZE;
786 /* patch super class index */
788 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
790 *((s4 *) (ra + 7 + 7 + 6 + 3)) =
791 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
792 c->index * sizeof(methodptr*));
798 /* patcher_instanceof_class ****************************************************
802 <patched call position>
803 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
805 *******************************************************************************/
807 bool patcher_instanceof_class(u1 *sp)
811 constant_classref *cr;
814 /* get stuff from the stack */
816 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
817 mcode = *((u8 *) (sp + 3 * 8));
818 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
820 /* get the fieldinfo */
822 if (!(c = resolve_classref_eager(cr)))
825 /* patch back original code */
827 *((u8 *) ra) = mcode;
829 /* if we show disassembly, we have to skip the nop's */
834 /* patch super class' vftbl */
836 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
842 /* patcher_clinit **************************************************************
844 May be used for GET/PUTSTATIC and in native stub.
848 <patched call position>
849 4d 8b 15 92 ff ff ff mov -110(%rip),%r10
850 49 89 1a mov %rbx,(%r10)
852 *******************************************************************************/
854 bool patcher_clinit(u1 *sp)
860 /* get stuff from the stack */
862 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
863 mcode = *((u8 *) (sp + 3 * 8));
864 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
866 /* check if the class is initialized */
868 if (!(c->state & CLASS_INITIALIZED))
869 if (!initialize_class(c))
872 /* patch back original code */
874 *((u8 *) ra) = mcode;
880 /* patcher_athrow_areturn ******************************************************
884 <patched call position>
886 *******************************************************************************/
888 #ifdef ENABLE_VERIFIER
889 bool patcher_athrow_areturn(u1 *sp)
893 unresolved_class *uc;
895 /* get stuff from the stack */
897 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
898 mcode = *((u8 *) (sp + 3 * 8));
899 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
901 /* resolve the class and check subtype constraints */
903 if (!resolve_class_eager_no_access_check(uc))
906 /* patch back original code */
908 *((u8 *) ra) = mcode;
912 #endif /* ENABLE_VERIFIER */
915 /* patcher_resolve_native ******************************************************
919 <patched call position>
920 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
923 *******************************************************************************/
925 #if !defined(WITH_STATIC_CLASSPATH)
926 bool patcher_resolve_native(u1 *sp)
933 /* get stuff from the stack */
935 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
936 mcode = *((u8 *) (sp + 3 * 8));
937 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
939 /* resolve native function */
941 if (!(f = native_resolve_function(m)))
944 /* patch back original code */
946 *((u8 *) ra) = mcode;
948 /* if we show disassembly, we have to skip the nop's */
953 /* patch native function pointer */
955 *((ptrint *) (ra + 2)) = (ptrint) f;
959 #endif /* !defined(WITH_STATIC_CLASSPATH) */
963 * These are local overrides for various environment variables in Emacs.
964 * Please do not remove this and leave it at the end of the file, where
965 * Emacs will automagically detect them.
966 * ---------------------------------------------------------------------
969 * indent-tabs-mode: t
973 * vim:noexpandtab:sw=4:ts=4: