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 7431 2007-03-01 13:49:14Z edwin $
33 #include "vm/jit/x86_64/codegen.h"
35 #include "mm/memory.h"
37 #include "native/native.h"
39 #include "vm/builtin.h"
40 #include "vm/exceptions.h"
41 #include "vm/initialize.h"
43 #include "vm/jit/patcher.h"
44 #include "vm/jit/stacktrace.h"
46 #include "vmcore/class.h"
47 #include "vmcore/field.h"
48 #include "vmcore/options.h"
49 #include "vmcore/references.h"
50 #include "vmcore/resolve.h"
53 /* patcher_wrapper *************************************************************
55 Wrapper for all patchers. It also creates the stackframe info
58 If the return value of the patcher function is false, it gets the
59 exception object, clears the exception pointer and returns the
62 *******************************************************************************/
64 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
73 /* define the patcher function */
75 bool (*patcher_function)(u1 *);
77 /* get stuff from the stack */
79 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
80 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
81 f = (functionptr) *((ptrint *) (sp + 0 * 8));
83 /* calculate and set the new return address */
85 xpc = xpc - PATCHER_CALL_SIZE;
87 *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
89 /* cast the passed function to a patcher function */
91 patcher_function = (bool (*)(u1 *)) (ptrint) f;
93 /* enter a monitor on the patching position */
97 /* create the stackframeinfo */
99 /* RA is passed as NULL, but the XPC is correct and can be used in
100 stacktrace_create_extern_stackframeinfo for
101 md_codegen_get_pv_from_pc. */
103 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, xpc, xpc);
105 /* call the proper patcher function */
107 result = (patcher_function)(sp);
109 /* remove the stackframeinfo */
111 stacktrace_remove_stackframeinfo(&sfi);
113 /* check for return value and exit accordingly */
115 if (result == false) {
116 e = exceptions_get_and_clear_exception();
123 PATCHER_MARK_PATCHED_MONITOREXIT;
129 /* patcher_get_putstatic *******************************************************
133 <patched call position>
134 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
135 49 8b 32 mov (%r10),%rsi
137 *******************************************************************************/
139 bool patcher_get_putstatic(u1 *sp)
143 unresolved_field *uf;
147 /* get stuff from the stack */
149 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
150 mcode = *((u8 *) (sp + 3 * 8));
151 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
152 disp = *((s4 *) (sp + 1 * 8));
154 /* get the fieldinfo */
156 if (!(fi = resolve_field_eager(uf)))
159 /* check if the field's class is initialized */
161 if (!(fi->class->state & CLASS_INITIALIZED))
162 if (!initialize_class(fi->class))
165 /* patch back original code */
167 *((u8 *) ra) = mcode;
169 /* if we show disassembly, we have to skip the nop's */
174 /* patch the field value's address */
176 *((ptrint *) (ra + 7 + disp)) = (ptrint) &(fi->value);
182 /* patcher_get_putfield ********************************************************
186 <patched call position>
187 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
189 *******************************************************************************/
191 bool patcher_get_putfield(u1 *sp)
195 unresolved_field *uf;
199 /* get stuff from the stack */
201 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
202 mcode = *((u8 *) (sp + 3 * 8));
203 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
205 /* get the fieldinfo */
207 if (!(fi = resolve_field_eager(uf)))
210 /* patch back original code (instruction code is smaller than 8 bytes) */
212 *((u4 *) (ra + 0)) = (u4) mcode;
213 *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
215 /* if we show disassembly, we have to skip the nop's */
220 /* patch the field's offset: we check for the field type, because the */
221 /* instructions have different lengths */
223 if (IS_INT_LNG_TYPE(fi->type)) {
224 /* check for special case: %rsp or %r12 as base register */
229 *((u4 *) (ra + 4)) = (u4) (fi->offset);
231 *((u4 *) (ra + 3)) = (u4) (fi->offset);
234 /* check for special case: %rsp or %r12 as base register */
239 *((u4 *) (ra + 6)) = (u4) (fi->offset);
241 *((u4 *) (ra + 5)) = (u4) (fi->offset);
248 /* patcher_putfieldconst *******************************************************
252 <patched call position>
253 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
255 *******************************************************************************/
257 bool patcher_putfieldconst(u1 *sp)
261 unresolved_field *uf;
264 /* get stuff from the stack */
266 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
267 mcode = *((u8 *) (sp + 3 * 8));
268 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
270 /* get the fieldinfo */
272 if (!(fi = resolve_field_eager(uf)))
275 /* patch back original code */
277 *((u8 *) ra) = mcode;
279 /* if we show disassembly, we have to skip the nop's */
284 /* patch the field's offset */
286 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
287 /* handle special case when the base register is %r12 */
289 if (*(ra + 2) == 0x84) {
290 *((u4 *) (ra + 4)) = (u4) (fi->offset);
291 *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
294 *((u4 *) (ra + 3)) = (u4) (fi->offset);
295 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
299 /* handle special case when the base register is %r12 */
301 if (*(ra + 2) == 0x84)
302 *((u4 *) (ra + 4)) = (u4) (fi->offset);
304 *((u4 *) (ra + 3)) = (u4) (fi->offset);
311 /* patcher_aconst **************************************************************
315 <patched call position>
316 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
318 *******************************************************************************/
320 bool patcher_aconst(u1 *sp)
324 constant_classref *cr;
327 /* get stuff from the stack */
329 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
330 mcode = *((u8 *) (sp + 3 * 8));
331 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
333 /* get the classinfo */
335 if (!(c = resolve_classref_eager(cr)))
338 /* patch back original code */
340 *((u8 *) ra) = mcode;
342 /* if we show disassembly, we have to skip the nop's */
347 /* patch the classinfo pointer */
349 *((ptrint *) (ra + 2)) = (ptrint) c;
355 /* patcher_builtin_multianewarray **********************************************
359 <patched call position>
360 48 bf 02 00 00 00 00 00 00 00 mov $0x2,%rdi
361 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
362 48 89 e2 mov %rsp,%rdx
363 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
366 *******************************************************************************/
368 bool patcher_builtin_multianewarray(u1 *sp)
372 constant_classref *cr;
375 /* get stuff from the stack */
377 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
378 mcode = *((u8 *) (sp + 3 * 8));
379 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
381 /* get the classinfo */
383 if (!(c = resolve_classref_eager(cr)))
386 /* patch back original code */
388 *((u8 *) ra) = mcode;
390 /* if we show disassembly, we have to skip the nop's */
395 /* patch the classinfo pointer */
397 *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
403 /* patcher_builtin_arraycheckcast **********************************************
407 <patched call position>
408 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
409 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
412 *******************************************************************************/
414 bool patcher_builtin_arraycheckcast(u1 *sp)
418 constant_classref *cr;
421 /* get stuff from the stack */
423 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
424 mcode = *((u8 *) (sp + 3 * 8));
425 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
427 /* get the classinfo */
429 if (!(c = resolve_classref_eager(cr)))
432 /* patch back original code */
434 *((u8 *) ra) = mcode;
436 /* if we show disassembly, we have to skip the nop's */
441 /* patch the classinfo pointer */
443 *((ptrint *) (ra + 2)) = (ptrint) c;
449 /* patcher_invokestatic_special ************************************************
453 <patched call position>
454 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
457 *******************************************************************************/
459 bool patcher_invokestatic_special(u1 *sp)
463 unresolved_method *um;
467 /* get stuff from the stack */
469 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
470 mcode = *((u8 *) (sp + 3 * 8));
471 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
472 disp = *((s4 *) (sp + 1 * 8));
474 /* get the fieldinfo */
476 if (!(m = resolve_method_eager(um)))
479 /* patch back original code */
481 *((u8 *) ra) = mcode;
483 /* if we show disassembly, we have to skip the nop's */
488 /* patch stubroutine */
490 /* *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
491 *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
497 /* patcher_invokevirtual *******************************************************
501 <patched call position>
502 4c 8b 17 mov (%rdi),%r10
503 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
506 *******************************************************************************/
508 bool patcher_invokevirtual(u1 *sp)
512 unresolved_method *um;
515 /* get stuff from the stack */
517 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
518 mcode = *((u8 *) (sp + 3 * 8));
519 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
521 /* get the fieldinfo */
523 if (!(m = resolve_method_eager(um)))
526 /* patch back original code */
528 *((u8 *) ra) = mcode;
530 /* if we show disassembly, we have to skip the nop's */
535 /* patch vftbl index */
537 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
538 sizeof(methodptr) * m->vftblindex);
544 /* patcher_invokeinterface *****************************************************
548 <patched call position>
549 4c 8b 17 mov (%rdi),%r10
550 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
551 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
554 *******************************************************************************/
556 bool patcher_invokeinterface(u1 *sp)
560 unresolved_method *um;
563 /* get stuff from the stack */
565 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
566 mcode = *((u8 *) (sp + 3 * 8));
567 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
569 /* get the fieldinfo */
571 if (!(m = resolve_method_eager(um)))
574 /* patch back original code */
576 *((u8 *) ra) = mcode;
578 /* if we show disassembly, we have to skip the nop's */
583 /* patch interfacetable index */
585 *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
586 sizeof(methodptr) * m->class->index);
588 /* patch method offset */
590 *((s4 *) (ra + 3 + 7 + 3)) =
591 (s4) (sizeof(methodptr) * (m - m->class->methods));
597 /* patcher_checkcast_instanceof_flags ******************************************
601 <patched call position>
602 41 ba 00 00 00 00 mov $0x0,%r10d
603 41 81 e2 00 02 00 00 and $0x200,%r10d
604 0f 84 35 00 00 00 je 0x00002aaaaab01479
606 *******************************************************************************/
608 bool patcher_checkcast_instanceof_flags(u1 *sp)
612 constant_classref *cr;
615 /* get stuff from the stack */
617 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
618 mcode = *((u8 *) (sp + 3 * 8));
619 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
621 /* get the fieldinfo */
623 if (!(c = resolve_classref_eager(cr)))
626 /* patch back original code */
628 *((u8 *) ra) = mcode;
630 /* if we show disassembly, we have to skip the nop's */
635 /* patch class flags */
637 *((s4 *) (ra + 2)) = (s4) c->flags;
643 /* patcher_checkcast_instanceof_interface **************************************
647 <patched call position>
648 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
649 49 81 eb 00 00 00 00 sub $0x0,%r11
650 4d 85 db test %r11,%r11
651 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
652 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
654 *******************************************************************************/
656 bool patcher_checkcast_instanceof_interface(u1 *sp)
660 constant_classref *cr;
663 /* get stuff from the stack */
665 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
666 mcode = *((u8 *) (sp + 3 * 8));
667 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
669 /* get the fieldinfo */
671 if (!(c = resolve_classref_eager(cr)))
674 /* patch back original code */
676 *((u8 *) ra) = mcode;
678 /* if we show disassembly, we have to skip the nop's */
683 /* patch super class index */
685 *((s4 *) (ra + 7 + 3)) = (s4) c->index;
687 *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
688 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
689 c->index * sizeof(methodptr*));
695 /* patcher_checkcast_class *****************************************************
699 <patched call position>
700 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
701 45 8b 92 20 00 00 00 mov 0x20(%r10),%r10d
702 45 8b 9b 20 00 00 00 mov 0x20(%r11),%r11d
703 4d 29 da sub %r11,%r10
704 49 bb 00 00 00 00 00 00 00 00 mov $0x0,%r11
706 *******************************************************************************/
708 bool patcher_checkcast_class(u1 *sp)
712 constant_classref *cr;
715 /* get stuff from the stack */
717 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
718 mcode = *((u8 *) (sp + 3 * 8));
719 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
721 /* get the fieldinfo */
723 if (!(c = resolve_classref_eager(cr)))
726 /* patch back original code */
728 *((u8 *) ra) = mcode;
730 /* if we show disassembly, we have to skip the nop's */
735 /* patch super class' vftbl */
737 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
738 *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
744 /* patcher_instanceof_class ****************************************************
748 <patched call position>
749 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
751 *******************************************************************************/
753 bool patcher_instanceof_class(u1 *sp)
757 constant_classref *cr;
760 /* get stuff from the stack */
762 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
763 mcode = *((u8 *) (sp + 3 * 8));
764 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
766 /* get the fieldinfo */
768 if (!(c = resolve_classref_eager(cr)))
771 /* patch back original code */
773 *((u8 *) ra) = mcode;
775 /* if we show disassembly, we have to skip the nop's */
780 /* patch super class' vftbl */
782 *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
788 /* patcher_clinit **************************************************************
790 May be used for GET/PUTSTATIC and in native stub.
794 <patched call position>
795 4d 8b 15 92 ff ff ff mov -110(%rip),%r10
796 49 89 1a mov %rbx,(%r10)
798 *******************************************************************************/
800 bool patcher_clinit(u1 *sp)
806 /* get stuff from the stack */
808 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
809 mcode = *((u8 *) (sp + 3 * 8));
810 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
812 /* check if the class is initialized */
814 if (!(c->state & CLASS_INITIALIZED))
815 if (!initialize_class(c))
818 /* patch back original code */
820 *((u8 *) ra) = mcode;
826 /* patcher_athrow_areturn ******************************************************
830 <patched call position>
832 *******************************************************************************/
834 #ifdef ENABLE_VERIFIER
835 bool patcher_athrow_areturn(u1 *sp)
839 unresolved_class *uc;
841 /* get stuff from the stack */
843 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
844 mcode = *((u8 *) (sp + 3 * 8));
845 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
847 /* resolve the class and check subtype constraints */
849 if (!resolve_class_eager_no_access_check(uc))
852 /* patch back original code */
854 *((u8 *) ra) = mcode;
858 #endif /* ENABLE_VERIFIER */
861 /* patcher_resolve_native ******************************************************
865 <patched call position>
866 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
869 *******************************************************************************/
871 #if !defined(WITH_STATIC_CLASSPATH)
872 bool patcher_resolve_native(u1 *sp)
879 /* get stuff from the stack */
881 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
882 mcode = *((u8 *) (sp + 3 * 8));
883 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
885 /* resolve native function */
887 if (!(f = native_resolve_function(m)))
890 /* patch back original code */
892 *((u8 *) ra) = mcode;
894 /* if we show disassembly, we have to skip the nop's */
899 /* patch native function pointer */
901 *((ptrint *) (ra + 2)) = (ptrint) f;
905 #endif /* !defined(WITH_STATIC_CLASSPATH) */
909 * These are local overrides for various environment variables in Emacs.
910 * Please do not remove this and leave it at the end of the file, where
911 * Emacs will automagically detect them.
912 * ---------------------------------------------------------------------
915 * indent-tabs-mode: t
919 * vim:noexpandtab:sw=4:ts=4: