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 5945 2006-11-10 16:41:12Z 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_get_pv_from_pc. */
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;
148 /* get stuff from the stack */
150 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
151 mcode = *((u8 *) (sp + 3 * 8));
152 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
153 disp = *((s4 *) (sp + 1 * 8));
155 /* get the fieldinfo */
157 if (!(fi = resolve_field_eager(uf)))
160 /* check if the field's class is initialized */
162 if (!(fi->class->state & CLASS_INITIALIZED))
163 if (!initialize_class(fi->class))
166 /* patch back original code */
168 *((u8 *) ra) = mcode;
170 /* if we show disassembly, we have to skip the nop's */
175 /* patch the field value's address */
177 *((ptrint *) (ra + 7 + disp)) = (ptrint) &(fi->value);
183 /* patcher_get_putfield ********************************************************
187 <patched call position>
188 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
190 *******************************************************************************/
192 bool patcher_get_putfield(u1 *sp)
196 unresolved_field *uf;
200 /* get stuff from the stack */
202 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
203 mcode = *((u8 *) (sp + 3 * 8));
204 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
206 /* get the fieldinfo */
208 if (!(fi = resolve_field_eager(uf)))
211 /* patch back original code (instruction code is smaller than 8 bytes) */
213 *((u4 *) (ra + 0)) = (u4) mcode;
214 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
216 /* if we show disassembly, we have to skip the nop's */
221 /* patch the field's offset: we check for the field type, because the */
222 /* instructions have different lengths */
224 if (IS_INT_LNG_TYPE(fi->type)) {
225 /* check for special case: %rsp or %r12 as base register */
230 *((u4 *) (ra + 4)) = (u4) (fi->offset);
232 *((u4 *) (ra + 3)) = (u4) (fi->offset);
235 /* check for special case: %rsp or %r12 as base register */
240 *((u4 *) (ra + 6)) = (u4) (fi->offset);
242 *((u4 *) (ra + 5)) = (u4) (fi->offset);
249 /* patcher_putfieldconst *******************************************************
253 <patched call position>
254 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
256 *******************************************************************************/
258 bool patcher_putfieldconst(u1 *sp)
262 unresolved_field *uf;
265 /* get stuff from the stack */
267 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
268 mcode = *((u8 *) (sp + 3 * 8));
269 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
271 /* get the fieldinfo */
273 if (!(fi = resolve_field_eager(uf)))
276 /* patch back original code */
278 *((u8 *) ra) = mcode;
280 /* if we show disassembly, we have to skip the nop's */
285 /* patch the field's offset */
287 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
288 /* handle special case when the base register is %r12 */
290 if (*(ra + 2) == 0x84) {
291 *((u4 *) (ra + 4)) = (u4) (fi->offset);
292 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
295 *((u4 *) (ra + 3)) = (u4) (fi->offset);
296 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
300 /* handle special case when the base register is %r12 */
302 if (*(ra + 2) == 0x84)
303 *((u4 *) (ra + 4)) = (u4) (fi->offset);
305 *((u4 *) (ra + 3)) = (u4) (fi->offset);
312 /* patcher_aconst **************************************************************
316 <patched call position>
317 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
319 *******************************************************************************/
321 bool patcher_aconst(u1 *sp)
325 constant_classref *cr;
328 /* get stuff from the stack */
330 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
331 mcode = *((u8 *) (sp + 3 * 8));
332 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
334 /* get the classinfo */
336 if (!(c = resolve_classref_eager(cr)))
339 /* patch back original code */
341 *((u8 *) ra) = mcode;
343 /* if we show disassembly, we have to skip the nop's */
348 /* patch the classinfo pointer */
350 *((ptrint *) (ra + 2)) = (ptrint) c;
356 /* patcher_builtin_multianewarray **********************************************
360 <patched call position>
361 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
362 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
363 48 89 e2 mov %rsp,%rdx
364 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
367 *******************************************************************************/
369 bool patcher_builtin_multianewarray(u1 *sp)
373 constant_classref *cr;
376 /* get stuff from the stack */
378 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
379 mcode = *((u8 *) (sp + 3 * 8));
380 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
382 /* get the classinfo */
384 if (!(c = resolve_classref_eager(cr)))
387 /* patch back original code */
389 *((u8 *) ra) = mcode;
391 /* if we show disassembly, we have to skip the nop's */
396 /* patch the classinfo pointer */
398 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
404 /* patcher_builtin_arraycheckcast **********************************************
408 <patched call position>
409 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
410 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
413 *******************************************************************************/
415 bool patcher_builtin_arraycheckcast(u1 *sp)
419 constant_classref *cr;
422 /* get stuff from the stack */
424 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
425 mcode = *((u8 *) (sp + 3 * 8));
426 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
428 /* get the classinfo */
430 if (!(c = resolve_classref_eager(cr)))
433 /* patch back original code */
435 *((u8 *) ra) = mcode;
437 /* if we show disassembly, we have to skip the nop's */
442 /* patch the classinfo pointer */
444 *((ptrint *) (ra + 2)) = (ptrint) c;
450 /* patcher_invokestatic_special ************************************************
454 <patched call position>
455 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
458 *******************************************************************************/
460 bool patcher_invokestatic_special(u1 *sp)
464 unresolved_method *um;
468 /* get stuff from the stack */
470 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
471 mcode = *((u8 *) (sp + 3 * 8));
472 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
473 disp = *((s4 *) (sp + 1 * 8));
475 /* get the fieldinfo */
477 if (!(m = resolve_method_eager(um)))
480 /* patch back original code */
482 *((u8 *) ra) = mcode;
484 /* if we show disassembly, we have to skip the nop's */
489 /* patch stubroutine */
491 /* *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
492 *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
498 /* patcher_invokevirtual *******************************************************
502 <patched call position>
503 4c 8b 17 mov (%rdi),%r10
504 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
507 *******************************************************************************/
509 bool patcher_invokevirtual(u1 *sp)
513 unresolved_method *um;
516 /* get stuff from the stack */
518 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
519 mcode = *((u8 *) (sp + 3 * 8));
520 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
522 /* get the fieldinfo */
524 if (!(m = resolve_method_eager(um)))
527 /* patch back original code */
529 *((u8 *) ra) = mcode;
531 /* if we show disassembly, we have to skip the nop's */
536 /* patch vftbl index */
538 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
539 sizeof(methodptr) * m->vftblindex);
545 /* patcher_invokeinterface *****************************************************
549 <patched call position>
550 4c 8b 17 mov (%rdi),%r10
551 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
552 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
555 *******************************************************************************/
557 bool patcher_invokeinterface(u1 *sp)
561 unresolved_method *um;
564 /* get stuff from the stack */
566 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
567 mcode = *((u8 *) (sp + 3 * 8));
568 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
570 /* get the fieldinfo */
572 if (!(m = resolve_method_eager(um)))
575 /* patch back original code */
577 *((u8 *) ra) = mcode;
579 /* if we show disassembly, we have to skip the nop's */
584 /* patch interfacetable index */
586 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
587 sizeof(methodptr) * m->class->index);
589 /* patch method offset */
591 *((s4 *) (ra + 3 + 7 + 3)) =
592 (s4) (sizeof(methodptr) * (m - m->class->methods));
598 /* patcher_checkcast_instanceof_flags ******************************************
602 <patched call position>
603 41 ba 00 00 00 00 mov $0x0,%r10d
604 41 81 e2 00 02 00 00 and $0x200,%r10d
605 0f 84 35 00 00 00 je 0x00002aaaaab01479
607 *******************************************************************************/
609 bool patcher_checkcast_instanceof_flags(u1 *sp)
613 constant_classref *cr;
616 /* get stuff from the stack */
618 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
619 mcode = *((u8 *) (sp + 3 * 8));
620 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
622 /* get the fieldinfo */
624 if (!(c = resolve_classref_eager(cr)))
627 /* patch back original code */
629 *((u8 *) ra) = mcode;
631 /* if we show disassembly, we have to skip the nop's */
636 /* patch class flags */
638 *((s4 *) (ra + 2)) = (s4) c->flags;
644 /* patcher_checkcast_instanceof_interface **************************************
648 <patched call position>
649 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
650 49 81 eb 00 00 00 00 sub $0x0,%r11
651 4d 85 db test %r11,%r11
652 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
653 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
655 *******************************************************************************/
657 bool patcher_checkcast_instanceof_interface(u1 *sp)
661 constant_classref *cr;
664 /* get stuff from the stack */
666 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
667 mcode = *((u8 *) (sp + 3 * 8));
668 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
670 /* get the fieldinfo */
672 if (!(c = resolve_classref_eager(cr)))
675 /* patch back original code */
677 *((u8 *) ra) = mcode;
679 /* if we show disassembly, we have to skip the nop's */
684 /* patch super class index */
686 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
688 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
689 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
690 c->index * sizeof(methodptr*));
696 /* patcher_checkcast_class *****************************************************
700 <patched call position>
701 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
702 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
703 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
704 4d 29 da sub %r11,%r10
705 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
707 *******************************************************************************/
709 bool patcher_checkcast_class(u1 *sp)
713 constant_classref *cr;
716 /* get stuff from the stack */
718 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
719 mcode = *((u8 *) (sp + 3 * 8));
720 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
722 /* get the fieldinfo */
724 if (!(c = resolve_classref_eager(cr)))
727 /* patch back original code */
729 *((u8 *) ra) = mcode;
731 /* if we show disassembly, we have to skip the nop's */
736 /* patch super class' vftbl */
738 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
739 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
745 /* patcher_instanceof_class ****************************************************
749 <patched call position>
750 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
752 *******************************************************************************/
754 bool patcher_instanceof_class(u1 *sp)
758 constant_classref *cr;
761 /* get stuff from the stack */
763 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
764 mcode = *((u8 *) (sp + 3 * 8));
765 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
767 /* get the fieldinfo */
769 if (!(c = resolve_classref_eager(cr)))
772 /* patch back original code */
774 *((u8 *) ra) = mcode;
776 /* if we show disassembly, we have to skip the nop's */
781 /* patch super class' vftbl */
783 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
789 /* patcher_clinit **************************************************************
791 May be used for GET/PUTSTATIC and in native stub.
795 <patched call position>
796 4d 8b 15 92 ff ff ff mov -110(%rip),%r10
797 49 89 1a mov %rbx,(%r10)
799 *******************************************************************************/
801 bool patcher_clinit(u1 *sp)
807 /* get stuff from the stack */
809 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
810 mcode = *((u8 *) (sp + 3 * 8));
811 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
813 /* check if the class is initialized */
815 if (!(c->state & CLASS_INITIALIZED))
816 if (!initialize_class(c))
819 /* patch back original code */
821 *((u8 *) ra) = mcode;
827 /* patcher_athrow_areturn ******************************************************
831 <patched call position>
833 *******************************************************************************/
835 #ifdef ENABLE_VERIFIER
836 bool patcher_athrow_areturn(u1 *sp)
840 unresolved_class *uc;
843 /* get stuff from the stack */
845 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
846 mcode = *((u8 *) (sp + 3 * 8));
847 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
849 /* resolve the class */
851 if (!resolve_class(uc, resolveEager, false, &c))
854 /* patch back original code */
856 *((u8 *) ra) = mcode;
860 #endif /* ENABLE_VERIFIER */
863 /* patcher_resolve_native ******************************************************
867 <patched call position>
868 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
871 *******************************************************************************/
873 #if !defined(WITH_STATIC_CLASSPATH)
874 bool patcher_resolve_native(u1 *sp)
881 /* get stuff from the stack */
883 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
884 mcode = *((u8 *) (sp + 3 * 8));
885 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
887 /* resolve native function */
889 if (!(f = native_resolve_function(m)))
892 /* patch back original code */
894 *((u8 *) ra) = mcode;
896 /* if we show disassembly, we have to skip the nop's */
901 /* patch native function pointer */
903 *((ptrint *) (ra + 2)) = (ptrint) f;
907 #endif /* !defined(WITH_STATIC_CLASSPATH) */
911 * These are local overrides for various environment variables in Emacs.
912 * Please do not remove this and leave it at the end of the file, where
913 * Emacs will automagically detect them.
914 * ---------------------------------------------------------------------
917 * indent-tabs-mode: t
921 * vim:noexpandtab:sw=4:ts=4: