1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: patcher.c 5142 2006-07-17 09:47:02Z twisti $
39 #include "vm/jit/x86_64/codegen.h"
41 #include "mm/memory.h"
42 #include "native/native.h"
43 #include "vm/builtin.h"
45 #include "vm/exceptions.h"
47 #include "vm/initialize.h"
48 #include "vm/options.h"
49 #include "vm/references.h"
50 #include "vm/resolve.h"
51 #include "vm/jit/patcher.h"
54 /* patcher_wrapper *************************************************************
56 Wrapper for all patchers. It also creates the stackframe info
59 If the return value of the patcher function is false, it gets the
60 exception object, clears the exception pointer and returns the
63 *******************************************************************************/
65 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
74 /* define the patcher function */
76 bool (*patcher_function)(u1 *);
78 /* get stuff from the stack */
80 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
81 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
82 f = (functionptr) *((ptrint *) (sp + 0 * 8));
84 /* calculate and set the new return address */
86 xpc = xpc - PATCHER_CALL_SIZE;
88 *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
90 /* cast the passed function to a patcher function */
92 patcher_function = (bool (*)(u1 *)) (ptrint) f;
94 /* enter a monitor on the patching position */
98 /* create the stackframeinfo */
100 /* RA is passed as NULL, but the XPC is correct and can be used in
101 stacktrace_create_extern_stackframeinfo for
102 md_codegen_findmethod. */
104 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, xpc, xpc);
106 /* call the proper patcher function */
108 result = (patcher_function)(sp);
110 /* remove the stackframeinfo */
112 stacktrace_remove_stackframeinfo(&sfi);
114 /* check for return value and exit accordingly */
116 if (result == false) {
117 e = exceptions_get_and_clear_exception();
124 PATCHER_MARK_PATCHED_MONITOREXIT;
130 /* patcher_get_putstatic *******************************************************
134 <patched call position>
135 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
136 49 8b 32 mov (%r10),%rsi
138 *******************************************************************************/
140 bool patcher_get_putstatic(u1 *sp)
144 unresolved_field *uf;
149 /* get stuff from the stack */
151 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
152 mcode = *((u8 *) (sp + 3 * 8));
153 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
154 disp = *((s4 *) (sp + 1 * 8));
156 /* get the fieldinfo */
158 if (!(fi = resolve_field_eager(uf)))
161 /* check if the field's class is initialized */
163 if (!(fi->class->state & CLASS_INITIALIZED))
164 if (!initialize_class(fi->class))
167 /* patch back original code */
169 *((u8 *) ra) = mcode;
171 /* if we show disassembly, we have to skip the nop's */
173 if (opt_showdisassemble)
176 /* get RIP offset from machine instruction */
178 offset = *((u4 *) (ra + 3));
180 /* patch the field value's address (+ 7: is the size of the RIP move) */
182 *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
188 /* patcher_get_putfield ********************************************************
192 <patched call position>
193 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
195 *******************************************************************************/
197 bool patcher_get_putfield(u1 *sp)
201 unresolved_field *uf;
205 /* get stuff from the stack */
207 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
208 mcode = *((u8 *) (sp + 3 * 8));
209 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
211 /* get the fieldinfo */
213 if (!(fi = resolve_field_eager(uf)))
216 /* patch back original code (instruction code is smaller than 8 bytes) */
218 *((u4 *) (ra + 0)) = (u4) mcode;
219 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
221 /* if we show disassembly, we have to skip the nop's */
223 if (opt_showdisassemble)
226 /* patch the field's offset: we check for the field type, because the */
227 /* instructions have different lengths */
229 if (IS_INT_LNG_TYPE(fi->type)) {
230 /* check for special case: %rsp or %r12 as base register */
235 *((u4 *) (ra + 4)) = (u4) (fi->offset);
237 *((u4 *) (ra + 3)) = (u4) (fi->offset);
240 /* check for special case: %rsp or %r12 as base register */
245 *((u4 *) (ra + 6)) = (u4) (fi->offset);
247 *((u4 *) (ra + 5)) = (u4) (fi->offset);
254 /* patcher_putfieldconst *******************************************************
258 <patched call position>
259 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
261 *******************************************************************************/
263 bool patcher_putfieldconst(u1 *sp)
267 unresolved_field *uf;
270 /* get stuff from the stack */
272 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
273 mcode = *((u8 *) (sp + 3 * 8));
274 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
276 /* get the fieldinfo */
278 if (!(fi = resolve_field_eager(uf)))
281 /* patch back original code */
283 *((u8 *) ra) = mcode;
285 /* if we show disassembly, we have to skip the nop's */
287 if (opt_showdisassemble)
290 /* patch the field's offset */
292 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
293 /* handle special case when the base register is %r12 */
295 if (*(ra + 2) == 0x84) {
296 *((u4 *) (ra + 4)) = (u4) (fi->offset);
297 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
300 *((u4 *) (ra + 3)) = (u4) (fi->offset);
301 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
305 /* handle special case when the base register is %r12 */
307 if (*(ra + 2) == 0x84)
308 *((u4 *) (ra + 4)) = (u4) (fi->offset);
310 *((u4 *) (ra + 3)) = (u4) (fi->offset);
317 /* patcher_aconst **************************************************************
321 <patched call position>
322 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
324 *******************************************************************************/
326 bool patcher_aconst(u1 *sp)
330 constant_classref *cr;
333 /* get stuff from the stack */
335 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
336 mcode = *((u8 *) (sp + 3 * 8));
337 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
339 /* get the classinfo */
341 if (!(c = resolve_classref_eager(cr)))
344 /* patch back original code */
346 *((u8 *) ra) = mcode;
348 /* if we show disassembly, we have to skip the nop's */
350 if (opt_showdisassemble)
353 /* patch the classinfo pointer */
355 *((ptrint *) (ra + 2)) = (ptrint) c;
361 /* patcher_builtin_multianewarray **********************************************
365 <patched call position>
366 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
367 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
368 48 89 e2 mov %rsp,%rdx
369 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
372 *******************************************************************************/
374 bool patcher_builtin_multianewarray(u1 *sp)
378 constant_classref *cr;
381 /* get stuff from the stack */
383 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
384 mcode = *((u8 *) (sp + 3 * 8));
385 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
387 /* get the classinfo */
389 if (!(c = resolve_classref_eager(cr)))
392 /* patch back original code */
394 *((u8 *) ra) = mcode;
396 /* if we show disassembly, we have to skip the nop's */
398 if (opt_showdisassemble)
401 /* patch the classinfo pointer */
403 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
405 /* patch new function address */
407 *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
413 /* patcher_builtin_arraycheckcast **********************************************
417 <patched call position>
418 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
419 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
422 *******************************************************************************/
424 bool patcher_builtin_arraycheckcast(u1 *sp)
428 constant_classref *cr;
431 /* get stuff from the stack */
433 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
434 mcode = *((u8 *) (sp + 3 * 8));
435 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
437 /* get the classinfo */
439 if (!(c = resolve_classref_eager(cr)))
442 /* patch back original code */
444 *((u8 *) ra) = mcode;
446 /* if we show disassembly, we have to skip the nop's */
448 if (opt_showdisassemble)
451 /* patch the classinfo pointer */
453 *((ptrint *) (ra + 2)) = (ptrint) c;
459 /* patcher_invokestatic_special ************************************************
463 <patched call position>
464 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
467 *******************************************************************************/
469 bool patcher_invokestatic_special(u1 *sp)
473 unresolved_method *um;
476 /* get stuff from the stack */
478 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
479 mcode = *((u8 *) (sp + 3 * 8));
480 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
482 /* get the fieldinfo */
484 if (!(m = resolve_method_eager(um)))
487 /* patch back original code */
489 *((u8 *) ra) = mcode;
491 /* if we show disassembly, we have to skip the nop's */
493 if (opt_showdisassemble)
496 /* patch stubroutine */
498 *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
504 /* patcher_invokevirtual *******************************************************
508 <patched call position>
509 4c 8b 17 mov (%rdi),%r10
510 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
513 *******************************************************************************/
515 bool patcher_invokevirtual(u1 *sp)
519 unresolved_method *um;
522 /* get stuff from the stack */
524 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
525 mcode = *((u8 *) (sp + 3 * 8));
526 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
528 /* get the fieldinfo */
530 if (!(m = resolve_method_eager(um)))
533 /* patch back original code */
535 *((u8 *) ra) = mcode;
537 /* if we show disassembly, we have to skip the nop's */
539 if (opt_showdisassemble)
542 /* patch vftbl index */
544 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
545 sizeof(methodptr) * m->vftblindex);
551 /* patcher_invokeinterface *****************************************************
555 <patched call position>
556 4c 8b 17 mov (%rdi),%r10
557 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
558 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
561 *******************************************************************************/
563 bool patcher_invokeinterface(u1 *sp)
567 unresolved_method *um;
570 /* get stuff from the stack */
572 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
573 mcode = *((u8 *) (sp + 3 * 8));
574 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
576 /* get the fieldinfo */
578 if (!(m = resolve_method_eager(um)))
581 /* patch back original code */
583 *((u8 *) ra) = mcode;
585 /* if we show disassembly, we have to skip the nop's */
587 if (opt_showdisassemble)
590 /* patch interfacetable index */
592 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
593 sizeof(methodptr) * m->class->index);
595 /* patch method offset */
597 *((s4 *) (ra + 3 + 7 + 3)) =
598 (s4) (sizeof(methodptr) * (m - m->class->methods));
604 /* patcher_checkcast_instanceof_flags ******************************************
608 <patched call position>
609 41 ba 00 00 00 00 mov $0x0,%r10d
610 41 81 e2 00 02 00 00 and $0x200,%r10d
611 0f 84 35 00 00 00 je 0x00002aaaaab01479
613 *******************************************************************************/
615 bool patcher_checkcast_instanceof_flags(u1 *sp)
619 constant_classref *cr;
622 /* get stuff from the stack */
624 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
625 mcode = *((u8 *) (sp + 3 * 8));
626 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
628 /* get the fieldinfo */
630 if (!(c = resolve_classref_eager(cr)))
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 class flags */
644 *((s4 *) (ra + 2)) = (s4) c->flags;
650 /* patcher_checkcast_instanceof_interface **************************************
654 <patched call position>
655 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
656 49 81 eb 00 00 00 00 sub $0x0,%r11
657 4d 85 db test %r11,%r11
658 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
659 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
661 *******************************************************************************/
663 bool patcher_checkcast_instanceof_interface(u1 *sp)
667 constant_classref *cr;
670 /* get stuff from the stack */
672 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
673 mcode = *((u8 *) (sp + 3 * 8));
674 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
676 /* get the fieldinfo */
678 if (!(c = resolve_classref_eager(cr)))
681 /* patch back original code */
683 *((u8 *) ra) = mcode;
685 /* if we show disassembly, we have to skip the nop's */
687 if (opt_showdisassemble)
690 /* patch super class index */
692 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
694 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
695 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
696 c->index * sizeof(methodptr*));
702 /* patcher_checkcast_class *****************************************************
706 <patched call position>
707 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
708 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
709 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
710 4d 29 da sub %r11,%r10
711 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
713 *******************************************************************************/
715 bool patcher_checkcast_class(u1 *sp)
719 constant_classref *cr;
722 /* get stuff from the stack */
724 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
725 mcode = *((u8 *) (sp + 3 * 8));
726 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
728 /* get the fieldinfo */
730 if (!(c = resolve_classref_eager(cr)))
733 /* patch back original code */
735 *((u8 *) ra) = mcode;
737 /* if we show disassembly, we have to skip the nop's */
739 if (opt_showdisassemble)
742 /* patch super class' vftbl */
744 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
745 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
751 /* patcher_instanceof_class ****************************************************
755 <patched call position>
756 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
758 *******************************************************************************/
760 bool patcher_instanceof_class(u1 *sp)
764 constant_classref *cr;
767 /* get stuff from the stack */
769 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
770 mcode = *((u8 *) (sp + 3 * 8));
771 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
773 /* get the fieldinfo */
775 if (!(c = resolve_classref_eager(cr)))
778 /* patch back original code */
780 *((u8 *) ra) = mcode;
782 /* if we show disassembly, we have to skip the nop's */
784 if (opt_showdisassemble)
787 /* patch super class' vftbl */
789 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
795 /* patcher_clinit **************************************************************
797 May be used for GET/PUTSTATIC and in native stub.
801 <patched call position>
802 4d 8b 15 92 ff ff ff mov -110(%rip),%r10
803 49 89 1a mov %rbx,(%r10)
805 *******************************************************************************/
807 bool patcher_clinit(u1 *sp)
813 /* get stuff from the stack */
815 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
816 mcode = *((u8 *) (sp + 3 * 8));
817 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
819 /* check if the class is initialized */
821 if (!(c->state & CLASS_INITIALIZED))
822 if (!initialize_class(c))
825 /* patch back original code */
827 *((u8 *) ra) = mcode;
833 /* patcher_athrow_areturn ******************************************************
837 <patched call position>
839 *******************************************************************************/
841 #ifdef ENABLE_VERIFIER
842 bool patcher_athrow_areturn(u1 *sp)
846 unresolved_class *uc;
849 /* get stuff from the stack */
851 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
852 mcode = *((u8 *) (sp + 3 * 8));
853 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
855 /* resolve the class */
857 if (!resolve_class(uc, resolveEager, false, &c))
860 /* patch back original code */
862 *((u8 *) ra) = mcode;
866 #endif /* ENABLE_VERIFIER */
869 /* patcher_resolve_native ******************************************************
873 <patched call position>
874 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
877 *******************************************************************************/
879 #if !defined(WITH_STATIC_CLASSPATH)
880 bool patcher_resolve_native(u1 *sp)
887 /* get stuff from the stack */
889 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
890 mcode = *((u8 *) (sp + 3 * 8));
891 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
893 /* resolve native function */
895 if (!(f = native_resolve_function(m)))
898 /* patch back original code */
900 *((u8 *) ra) = mcode;
902 /* if we show disassembly, we have to skip the nop's */
904 if (opt_showdisassemble)
907 /* patch native function pointer */
909 *((ptrint *) (ra + 2)) = (ptrint) f;
913 #endif /* !defined(WITH_STATIC_CLASSPATH) */
917 * These are local overrides for various environment variables in Emacs.
918 * Please do not remove this and leave it at the end of the file, where
919 * Emacs will automagically detect them.
920 * ---------------------------------------------------------------------
923 * indent-tabs-mode: t
927 * vim:noexpandtab:sw=4:ts=4: