1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/jit/x86_64/codegen.h"
34 #include "mm/memory.h"
36 #include "native/native.h"
38 #include "vm/builtin.h"
39 #include "vm/initialize.h"
41 #include "vm/jit/patcher-common.h"
43 #include "vmcore/class.h"
44 #include "vmcore/field.h"
45 #include "vmcore/options.h"
46 #include "vmcore/references.h"
47 #include "vm/resolve.h"
50 #define PATCH_BACK_ORIGINAL_MCODE \
52 *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
56 /* patcher_patch_code **********************************************************
58 Just patches back the original machine code.
60 *******************************************************************************/
62 void patcher_patch_code(patchref_t *pr)
64 PATCH_BACK_ORIGINAL_MCODE;
68 /* patcher_resolve_classref_to_classinfo ***************************************
72 <patched call position>
73 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
77 <patched call position>
78 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
79 48 89 e2 mov %rsp,%rdx
80 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
85 <patched call position>
86 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
87 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
90 *******************************************************************************/
92 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
94 constant_classref *cr;
98 cr = (constant_classref *) pr->ref;
99 datap = (intptr_t *) pr->datap;
101 /* get the classinfo */
103 if (!(c = resolve_classref_eager(cr)))
106 PATCH_BACK_ORIGINAL_MCODE;
108 /* patch the classinfo pointer */
110 *datap = (intptr_t) c;
116 /* patcher_resolve_classref_to_vftbl *******************************************
121 <patched call position>
123 *******************************************************************************/
125 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
127 constant_classref *cr;
131 /* get stuff from the stack */
133 cr = (constant_classref *) pr->ref;
134 datap = (intptr_t *) pr->datap;
136 /* get the fieldinfo */
138 if (!(c = resolve_classref_eager(cr)))
141 PATCH_BACK_ORIGINAL_MCODE;
143 /* patch super class' vftbl */
145 *datap = (intptr_t) c->vftbl;
151 /* patcher_resolve_classref_to_flags *******************************************
153 CHECKCAST/INSTANCEOF:
155 <patched call position>
157 *******************************************************************************/
159 bool patcher_resolve_classref_to_flags(patchref_t *pr)
161 constant_classref *cr;
166 cr = (constant_classref *) pr->ref;
167 datap = (int32_t *) pr->datap;
168 ra = (uint8_t *) pr->mpc;
170 /* get the fieldinfo */
172 if (!(c = resolve_classref_eager(cr)))
175 PATCH_BACK_ORIGINAL_MCODE;
177 /* if we show disassembly, we have to skip the nop's */
180 ra = ra + PATCHER_CALL_SIZE;
182 /* patch class flags */
184 /* *datap = c->flags; */
185 *((int32_t *) (ra + 2)) = c->flags;
191 /* patcher_get_putstatic *******************************************************
195 <patched call position>
196 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
197 49 8b 32 mov (%r10),%rsi
199 *******************************************************************************/
201 bool patcher_get_putstatic(patchref_t *pr)
203 unresolved_field *uf;
207 uf = (unresolved_field *) pr->ref;
208 datap = (intptr_t *) pr->datap;
210 /* get the fieldinfo */
212 if (!(fi = resolve_field_eager(uf)))
215 /* check if the field's class is initialized */
217 if (!(fi->clazz->state & CLASS_INITIALIZED))
218 if (!initialize_class(fi->clazz))
221 PATCH_BACK_ORIGINAL_MCODE;
223 /* patch the field value's address */
225 *datap = (intptr_t) fi->value;
231 /* patcher_get_putfield ********************************************************
235 <patched call position>
236 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
238 *******************************************************************************/
240 bool patcher_get_putfield(patchref_t *pr)
243 unresolved_field *uf;
247 ra = (uint8_t *) pr->mpc;
248 uf = (unresolved_field *) pr->ref;
250 /* get the fieldinfo */
252 if (!(fi = resolve_field_eager(uf)))
255 PATCH_BACK_ORIGINAL_MCODE;
257 /* if we show disassembly, we have to skip the nop's */
260 ra = ra + PATCHER_CALL_SIZE;
262 /* Patch the field's offset: we check for the field type, because
263 the instructions have different lengths. */
265 if (IS_INT_LNG_TYPE(fi->type)) {
266 /* Check for special case: %rsp or %r12 as base register. */
271 *((int32_t *) (ra + 4)) = fi->offset;
273 *((int32_t *) (ra + 3)) = fi->offset;
276 /* Check for special case: %rsp or %r12 as base register. */
281 *((int32_t *) (ra + 6)) = fi->offset;
283 *((int32_t *) (ra + 5)) = fi->offset;
290 /* patcher_putfieldconst *******************************************************
294 <patched call position>
295 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
297 *******************************************************************************/
299 bool patcher_putfieldconst(patchref_t *pr)
302 unresolved_field *uf;
306 ra = (uint8_t *) pr->mpc;
307 uf = (unresolved_field *) pr->ref;
309 /* get the fieldinfo */
311 if (!(fi = resolve_field_eager(uf)))
314 PATCH_BACK_ORIGINAL_MCODE;
316 /* if we show disassembly, we have to skip the nop's */
319 ra = ra + PATCHER_CALL_SIZE;
321 /* patch the field's offset */
323 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
324 /* handle special case when the base register is %r12 */
329 *((uint32_t *) (ra + 14)) = fi->offset;
332 *((uint32_t *) (ra + 13)) = fi->offset;
336 /* handle special case when the base register is %r12 */
341 *((uint32_t *) (ra + 4)) = fi->offset;
343 *((uint32_t *) (ra + 3)) = fi->offset;
350 /* patcher_invokestatic_special ************************************************
354 <patched call position>
355 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
358 *******************************************************************************/
360 bool patcher_invokestatic_special(patchref_t *pr)
362 unresolved_method *um;
366 /* get stuff from the stack */
368 um = (unresolved_method *) pr->ref;
369 datap = (intptr_t *) pr->datap;
371 /* get the fieldinfo */
373 if (!(m = resolve_method_eager(um)))
376 PATCH_BACK_ORIGINAL_MCODE;
378 /* patch stubroutine */
380 *datap = (intptr_t) m->stubroutine;
386 /* patcher_invokevirtual *******************************************************
390 <patched call position>
391 4c 8b 17 mov (%rdi),%r10
392 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
395 *******************************************************************************/
397 bool patcher_invokevirtual(patchref_t *pr)
400 unresolved_method *um;
403 ra = (uint8_t *) pr->mpc;
404 um = (unresolved_method *) pr->ref;
406 /* get the methodinfo */
408 if (!(m = resolve_method_eager(um)))
411 PATCH_BACK_ORIGINAL_MCODE;
413 /* if we show disassembly, we have to skip the nop's */
416 ra = ra + PATCHER_CALL_SIZE;
418 /* patch vftbl index */
420 *((int32_t *) (ra + 3 + 3)) =
421 (int32_t) (OFFSET(vftbl_t, table[0]) +
422 sizeof(methodptr) * m->vftblindex);
428 /* patcher_invokeinterface *****************************************************
432 <patched call position>
433 4c 8b 17 mov (%rdi),%r10
434 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
435 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
438 *******************************************************************************/
440 bool patcher_invokeinterface(patchref_t *pr)
443 unresolved_method *um;
446 /* get stuff from the stack */
448 ra = (uint8_t *) pr->mpc;
449 um = (unresolved_method *) pr->ref;
451 /* get the fieldinfo */
453 if (!(m = resolve_method_eager(um)))
456 PATCH_BACK_ORIGINAL_MCODE;
458 /* if we show disassembly, we have to skip the nop's */
461 ra = ra + PATCHER_CALL_SIZE;
463 /* patch interfacetable index */
465 *((int32_t *) (ra + 3 + 3)) =
466 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
467 sizeof(methodptr) * m->clazz->index);
469 /* patch method offset */
471 *((int32_t *) (ra + 3 + 7 + 3)) =
472 (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
478 /* patcher_checkcast_interface *************************************************
482 <patched call position>
483 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
484 41 81 fb 00 00 00 00 cmp $0x0,%r11d
485 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
486 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
487 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
489 *******************************************************************************/
491 bool patcher_checkcast_interface(patchref_t *pr)
494 constant_classref *cr;
497 ra = (uint8_t *) pr->mpc;
498 cr = (constant_classref *) pr->ref;
500 /* get the fieldinfo */
502 if (!(c = resolve_classref_eager(cr)))
505 PATCH_BACK_ORIGINAL_MCODE;
507 /* if we show disassembly, we have to skip the nop's */
510 ra = ra + PATCHER_CALL_SIZE;
512 /* patch super class index */
514 *((int32_t *) (ra + 7 + 3)) = c->index;
516 *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
517 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
518 c->index * sizeof(methodptr*));
524 /* patcher_instanceof_interface ************************************************
528 <patched call position>
529 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
530 41 81 fb 00 00 00 00 cmp $0x0,%r11d
531 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
532 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
534 *******************************************************************************/
536 bool patcher_instanceof_interface(patchref_t *pr)
539 constant_classref *cr;
542 ra = (uint8_t *) pr->mpc;
543 cr = (constant_classref *) pr->ref;
545 /* get the fieldinfo */
547 if (!(c = resolve_classref_eager(cr)))
550 PATCH_BACK_ORIGINAL_MCODE;
552 /* if we show disassembly, we have to skip the nop's */
555 ra = ra + PATCHER_CALL_SIZE;
557 /* patch super class index */
559 *((int32_t *) (ra + 7 + 3)) = c->index;
561 *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
562 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
563 c->index * sizeof(methodptr*));
570 * These are local overrides for various environment variables in Emacs.
571 * Please do not remove this and leave it at the end of the file, where
572 * Emacs will automagically detect them.
573 * ---------------------------------------------------------------------
576 * indent-tabs-mode: t
580 * vim:noexpandtab:sw=4:ts=4: