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
34 #include "vm/jit/x86_64/codegen.h"
36 #include "mm/memory.h"
38 #include "native/native.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
44 #include "vm/jit/patcher-common.h"
45 #include "vm/jit/stacktrace.h"
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
54 #define PATCH_BACK_ORIGINAL_MCODE \
56 *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
60 /* patcher_patch_code **********************************************************
62 Just patches back the original machine code.
64 *******************************************************************************/
66 void patcher_patch_code(patchref_t *pr)
68 PATCH_BACK_ORIGINAL_MCODE;
72 /* patcher_resolve_classref_to_classinfo ***************************************
76 <patched call position>
77 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
81 <patched call position>
82 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
83 48 89 e2 mov %rsp,%rdx
84 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
89 <patched call position>
90 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
91 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
94 *******************************************************************************/
96 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
98 constant_classref *cr;
102 cr = (constant_classref *) pr->ref;
103 datap = (intptr_t *) pr->datap;
105 /* get the classinfo */
107 if (!(c = resolve_classref_eager(cr)))
110 PATCH_BACK_ORIGINAL_MCODE;
112 /* patch the classinfo pointer */
114 *datap = (intptr_t) c;
120 /* patcher_resolve_classref_to_vftbl *******************************************
125 <patched call position>
127 *******************************************************************************/
129 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
131 constant_classref *cr;
135 /* get stuff from the stack */
137 cr = (constant_classref *) pr->ref;
138 datap = (intptr_t *) pr->datap;
140 /* get the fieldinfo */
142 if (!(c = resolve_classref_eager(cr)))
145 PATCH_BACK_ORIGINAL_MCODE;
147 /* patch super class' vftbl */
149 *datap = (intptr_t) c->vftbl;
155 /* patcher_resolve_classref_to_flags *******************************************
157 CHECKCAST/INSTANCEOF:
159 <patched call position>
161 *******************************************************************************/
163 bool patcher_resolve_classref_to_flags(patchref_t *pr)
165 constant_classref *cr;
170 cr = (constant_classref *) pr->ref;
171 datap = (int32_t *) pr->datap;
172 ra = (uint8_t *) pr->mpc;
174 /* get the fieldinfo */
176 if (!(c = resolve_classref_eager(cr)))
179 PATCH_BACK_ORIGINAL_MCODE;
181 /* if we show disassembly, we have to skip the nop's */
184 ra = ra + PATCHER_CALL_SIZE;
186 /* patch class flags */
188 /* *datap = c->flags; */
189 *((int32_t *) (ra + 2)) = c->flags;
195 /* patcher_resolve_native_function *********************************************
199 *******************************************************************************/
201 bool patcher_resolve_native_function(patchref_t *pr)
207 m = (methodinfo *) pr->ref;
208 datap = (intptr_t *) pr->datap;
210 /* resolve native function */
212 if (!(f = native_resolve_function(m)))
215 PATCH_BACK_ORIGINAL_MCODE;
217 /* patch native function pointer */
219 *datap = (intptr_t) f;
225 /* patcher_get_putstatic *******************************************************
229 <patched call position>
230 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
231 49 8b 32 mov (%r10),%rsi
233 *******************************************************************************/
235 bool patcher_get_putstatic(patchref_t *pr)
237 unresolved_field *uf;
241 uf = (unresolved_field *) pr->ref;
242 datap = (intptr_t *) pr->datap;
244 /* get the fieldinfo */
246 if (!(fi = resolve_field_eager(uf)))
249 /* check if the field's class is initialized */
251 if (!(fi->class->state & CLASS_INITIALIZED))
252 if (!initialize_class(fi->class))
255 PATCH_BACK_ORIGINAL_MCODE;
257 /* patch the field value's address */
259 *datap = (intptr_t) fi->value;
265 /* patcher_get_putfield ********************************************************
269 <patched call position>
270 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
272 *******************************************************************************/
274 bool patcher_get_putfield(patchref_t *pr)
277 unresolved_field *uf;
281 ra = (uint8_t *) pr->mpc;
282 uf = (unresolved_field *) pr->ref;
284 /* get the fieldinfo */
286 if (!(fi = resolve_field_eager(uf)))
289 PATCH_BACK_ORIGINAL_MCODE;
291 /* if we show disassembly, we have to skip the nop's */
294 ra = ra + PATCHER_CALL_SIZE;
296 /* Patch the field's offset: we check for the field type, because
297 the instructions have different lengths. */
299 if (IS_INT_LNG_TYPE(fi->type)) {
300 /* Check for special case: %rsp or %r12 as base register. */
305 *((int32_t *) (ra + 4)) = fi->offset;
307 *((int32_t *) (ra + 3)) = fi->offset;
310 /* Check for special case: %rsp or %r12 as base register. */
315 *((int32_t *) (ra + 6)) = fi->offset;
317 *((int32_t *) (ra + 5)) = fi->offset;
324 /* patcher_putfieldconst *******************************************************
328 <patched call position>
329 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
331 *******************************************************************************/
333 bool patcher_putfieldconst(patchref_t *pr)
336 unresolved_field *uf;
340 ra = (uint8_t *) pr->mpc;
341 uf = (unresolved_field *) pr->ref;
343 /* get the fieldinfo */
345 if (!(fi = resolve_field_eager(uf)))
348 PATCH_BACK_ORIGINAL_MCODE;
350 /* if we show disassembly, we have to skip the nop's */
353 ra = ra + PATCHER_CALL_SIZE;
355 /* patch the field's offset */
357 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
358 /* handle special case when the base register is %r12 */
363 *((uint32_t *) (ra + 4)) = fi->offset;
364 *((uint32_t *) (ra + 12 + 4)) = fi->offset + 4;
367 *((uint32_t *) (ra + 3)) = fi->offset;
368 *((uint32_t *) (ra + 11 + 3)) = fi->offset + 4;
372 /* handle special case when the base register is %r12 */
377 *((uint32_t *) (ra + 4)) = fi->offset;
379 *((uint32_t *) (ra + 3)) = fi->offset;
386 /* patcher_invokestatic_special ************************************************
390 <patched call position>
391 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
394 *******************************************************************************/
396 bool patcher_invokestatic_special(patchref_t *pr)
398 unresolved_method *um;
402 /* get stuff from the stack */
404 um = (unresolved_method *) pr->ref;
405 datap = (intptr_t *) pr->datap;
407 /* get the fieldinfo */
409 if (!(m = resolve_method_eager(um)))
412 PATCH_BACK_ORIGINAL_MCODE;
414 /* patch stubroutine */
416 *datap = (intptr_t) m->stubroutine;
422 /* patcher_invokevirtual *******************************************************
426 <patched call position>
427 4c 8b 17 mov (%rdi),%r10
428 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
431 *******************************************************************************/
433 bool patcher_invokevirtual(patchref_t *pr)
436 unresolved_method *um;
439 ra = (uint8_t *) pr->mpc;
440 um = (unresolved_method *) pr->ref;
442 /* get the methodinfo */
444 if (!(m = resolve_method_eager(um)))
447 PATCH_BACK_ORIGINAL_MCODE;
449 /* if we show disassembly, we have to skip the nop's */
452 ra = ra + PATCHER_CALL_SIZE;
454 /* patch vftbl index */
456 *((int32_t *) (ra + 3 + 3)) =
457 (int32_t) (OFFSET(vftbl_t, table[0]) +
458 sizeof(methodptr) * m->vftblindex);
464 /* patcher_invokeinterface *****************************************************
468 <patched call position>
469 4c 8b 17 mov (%rdi),%r10
470 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
471 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
474 *******************************************************************************/
476 bool patcher_invokeinterface(patchref_t *pr)
479 unresolved_method *um;
482 /* get stuff from the stack */
484 ra = (uint8_t *) pr->mpc;
485 um = (unresolved_method *) pr->ref;
487 /* get the fieldinfo */
489 if (!(m = resolve_method_eager(um)))
492 PATCH_BACK_ORIGINAL_MCODE;
494 /* if we show disassembly, we have to skip the nop's */
497 ra = ra + PATCHER_CALL_SIZE;
499 /* patch interfacetable index */
501 *((int32_t *) (ra + 3 + 3)) =
502 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
503 sizeof(methodptr) * m->class->index);
505 /* patch method offset */
507 *((int32_t *) (ra + 3 + 7 + 3)) =
508 (int32_t) (sizeof(methodptr) * (m - m->class->methods));
514 /* patcher_checkcast_interface *************************************************
518 <patched call position>
519 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
520 41 81 fb 00 00 00 00 cmp $0x0,%r11d
521 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
522 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
523 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
525 *******************************************************************************/
527 bool patcher_checkcast_interface(patchref_t *pr)
530 constant_classref *cr;
533 ra = (uint8_t *) pr->mpc;
534 cr = (constant_classref *) pr->ref;
536 /* get the fieldinfo */
538 if (!(c = resolve_classref_eager(cr)))
541 PATCH_BACK_ORIGINAL_MCODE;
543 /* if we show disassembly, we have to skip the nop's */
546 ra = ra + PATCHER_CALL_SIZE;
548 /* patch super class index */
550 *((int32_t *) (ra + 7 + 3)) = c->index;
552 *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
553 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
554 c->index * sizeof(methodptr*));
560 /* patcher_instanceof_interface ************************************************
564 <patched call position>
565 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
566 41 81 fb 00 00 00 00 cmp $0x0,%r11d
567 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
568 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
570 *******************************************************************************/
572 bool patcher_instanceof_interface(patchref_t *pr)
575 constant_classref *cr;
578 ra = (uint8_t *) pr->mpc;
579 cr = (constant_classref *) pr->ref;
581 /* get the fieldinfo */
583 if (!(c = resolve_classref_eager(cr)))
586 PATCH_BACK_ORIGINAL_MCODE;
588 /* if we show disassembly, we have to skip the nop's */
591 ra = ra + PATCHER_CALL_SIZE;
593 /* patch super class index */
595 *((int32_t *) (ra + 7 + 3)) = c->index;
597 *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
598 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
599 c->index * sizeof(methodptr*));
606 * These are local overrides for various environment variables in Emacs.
607 * Please do not remove this and leave it at the end of the file, where
608 * Emacs will automagically detect them.
609 * ---------------------------------------------------------------------
612 * indent-tabs-mode: t
616 * vim:noexpandtab:sw=4:ts=4: