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"
41 #include "vm/initialize.h"
42 #include "vm/options.h"
43 #include "vm/references.h"
44 #include "vm/resolve.h"
46 #include "vm/jit/patcher-common.h"
49 #define PATCH_BACK_ORIGINAL_MCODE \
51 *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
55 /* patcher_patch_code **********************************************************
57 Just patches back the original machine code.
59 *******************************************************************************/
61 void patcher_patch_code(patchref_t *pr)
63 PATCH_BACK_ORIGINAL_MCODE;
67 /* patcher_resolve_classref_to_classinfo ***************************************
71 <patched call position>
72 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
76 <patched call position>
77 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
78 48 89 e2 mov %rsp,%rdx
79 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
84 <patched call position>
85 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
86 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
89 *******************************************************************************/
91 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
93 constant_classref *cr;
97 cr = (constant_classref *) pr->ref;
98 datap = (intptr_t *) pr->datap;
100 /* get the classinfo */
102 if (!(c = resolve_classref_eager(cr)))
105 PATCH_BACK_ORIGINAL_MCODE;
107 /* patch the classinfo pointer */
109 *datap = (intptr_t) c;
115 /* patcher_resolve_classref_to_vftbl *******************************************
120 <patched call position>
122 *******************************************************************************/
124 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
126 constant_classref *cr;
130 /* get stuff from the stack */
132 cr = (constant_classref *) pr->ref;
133 datap = (intptr_t *) pr->datap;
135 /* get the fieldinfo */
137 if (!(c = resolve_classref_eager(cr)))
140 PATCH_BACK_ORIGINAL_MCODE;
142 /* patch super class' vftbl */
144 *datap = (intptr_t) c->vftbl;
150 /* patcher_resolve_classref_to_flags *******************************************
152 CHECKCAST/INSTANCEOF:
154 <patched call position>
156 *******************************************************************************/
158 bool patcher_resolve_classref_to_flags(patchref_t *pr)
160 constant_classref *cr;
165 cr = (constant_classref *) pr->ref;
166 datap = (int32_t *) pr->datap;
167 ra = (uint8_t *) pr->mpc;
169 /* get the fieldinfo */
171 if (!(c = resolve_classref_eager(cr)))
174 PATCH_BACK_ORIGINAL_MCODE;
176 /* if we show disassembly, we have to skip the nop's */
179 ra = ra + PATCHER_CALL_SIZE;
181 /* patch class flags */
183 /* *datap = c->flags; */
184 *((int32_t *) (ra + 2)) = c->flags;
190 /* patcher_get_putstatic *******************************************************
194 <patched call position>
195 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
196 49 8b 32 mov (%r10),%rsi
198 *******************************************************************************/
200 bool patcher_get_putstatic(patchref_t *pr)
202 unresolved_field *uf;
206 uf = (unresolved_field *) pr->ref;
207 datap = (intptr_t *) pr->datap;
209 /* get the fieldinfo */
211 if (!(fi = resolve_field_eager(uf)))
214 /* check if the field's class is initialized */
216 if (!(fi->clazz->state & CLASS_INITIALIZED))
217 if (!initialize_class(fi->clazz))
220 PATCH_BACK_ORIGINAL_MCODE;
222 /* patch the field value's address */
224 *datap = (intptr_t) fi->value;
230 /* patcher_get_putfield ********************************************************
234 <patched call position>
235 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
237 *******************************************************************************/
239 bool patcher_get_putfield(patchref_t *pr)
242 unresolved_field *uf;
246 ra = (uint8_t *) pr->mpc;
247 uf = (unresolved_field *) pr->ref;
249 /* get the fieldinfo */
251 if (!(fi = resolve_field_eager(uf)))
254 PATCH_BACK_ORIGINAL_MCODE;
256 /* if we show disassembly, we have to skip the nop's */
259 ra = ra + PATCHER_CALL_SIZE;
261 /* Patch the field's offset: we check for the field type, because
262 the instructions have different lengths. */
264 if (IS_INT_LNG_TYPE(fi->type)) {
265 /* Check for special case: %rsp or %r12 as base register. */
270 *((int32_t *) (ra + 4)) = fi->offset;
272 *((int32_t *) (ra + 3)) = fi->offset;
275 /* Check for special case: %rsp or %r12 as base register. */
280 *((int32_t *) (ra + 6)) = fi->offset;
282 *((int32_t *) (ra + 5)) = fi->offset;
289 /* patcher_putfieldconst *******************************************************
293 <patched call position>
294 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
296 *******************************************************************************/
298 bool patcher_putfieldconst(patchref_t *pr)
301 unresolved_field *uf;
305 ra = (uint8_t *) pr->mpc;
306 uf = (unresolved_field *) pr->ref;
308 /* get the fieldinfo */
310 if (!(fi = resolve_field_eager(uf)))
313 PATCH_BACK_ORIGINAL_MCODE;
315 /* if we show disassembly, we have to skip the nop's */
318 ra = ra + PATCHER_CALL_SIZE;
320 /* patch the field's offset */
322 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
323 /* handle special case when the base register is %r12 */
328 *((uint32_t *) (ra + 14)) = fi->offset;
331 *((uint32_t *) (ra + 13)) = fi->offset;
335 /* handle special case when the base register is %r12 */
340 *((uint32_t *) (ra + 4)) = fi->offset;
342 *((uint32_t *) (ra + 3)) = fi->offset;
349 /* patcher_invokestatic_special ************************************************
353 <patched call position>
354 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
357 *******************************************************************************/
359 bool patcher_invokestatic_special(patchref_t *pr)
361 unresolved_method *um;
365 /* get stuff from the stack */
367 um = (unresolved_method *) pr->ref;
368 datap = (intptr_t *) pr->datap;
370 /* get the fieldinfo */
372 if (!(m = resolve_method_eager(um)))
375 PATCH_BACK_ORIGINAL_MCODE;
377 /* patch stubroutine */
379 *datap = (intptr_t) m->stubroutine;
385 /* patcher_invokevirtual *******************************************************
389 <patched call position>
390 4c 8b 17 mov (%rdi),%r10
391 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
394 *******************************************************************************/
396 bool patcher_invokevirtual(patchref_t *pr)
399 unresolved_method *um;
402 ra = (uint8_t *) pr->mpc;
403 um = (unresolved_method *) pr->ref;
405 /* get the methodinfo */
407 if (!(m = resolve_method_eager(um)))
410 PATCH_BACK_ORIGINAL_MCODE;
412 /* if we show disassembly, we have to skip the nop's */
415 ra = ra + PATCHER_CALL_SIZE;
417 /* patch vftbl index */
419 *((int32_t *) (ra + 3 + 3)) =
420 (int32_t) (OFFSET(vftbl_t, table[0]) +
421 sizeof(methodptr) * m->vftblindex);
427 /* patcher_invokeinterface *****************************************************
431 <patched call position>
432 4c 8b 17 mov (%rdi),%r10
433 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
434 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
437 *******************************************************************************/
439 bool patcher_invokeinterface(patchref_t *pr)
442 unresolved_method *um;
445 /* get stuff from the stack */
447 ra = (uint8_t *) pr->mpc;
448 um = (unresolved_method *) pr->ref;
450 /* get the fieldinfo */
452 if (!(m = resolve_method_eager(um)))
455 PATCH_BACK_ORIGINAL_MCODE;
457 /* if we show disassembly, we have to skip the nop's */
460 ra = ra + PATCHER_CALL_SIZE;
462 /* patch interfacetable index */
464 *((int32_t *) (ra + 3 + 3)) =
465 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
466 sizeof(methodptr) * m->clazz->index);
468 /* patch method offset */
470 *((int32_t *) (ra + 3 + 7 + 3)) =
471 (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
477 /* patcher_checkcast_interface *************************************************
481 <patched call position>
482 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
483 41 81 fb 00 00 00 00 cmp $0x0,%r11d
484 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
485 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
486 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
488 *******************************************************************************/
490 bool patcher_checkcast_interface(patchref_t *pr)
493 constant_classref *cr;
496 ra = (uint8_t *) pr->mpc;
497 cr = (constant_classref *) pr->ref;
499 /* get the fieldinfo */
501 if (!(c = resolve_classref_eager(cr)))
504 PATCH_BACK_ORIGINAL_MCODE;
506 /* if we show disassembly, we have to skip the nop's */
509 ra = ra + PATCHER_CALL_SIZE;
511 /* patch super class index */
513 *((int32_t *) (ra + 7 + 3)) = c->index;
515 *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
516 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
517 c->index * sizeof(methodptr*));
523 /* patcher_instanceof_interface ************************************************
527 <patched call position>
528 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
529 41 81 fb 00 00 00 00 cmp $0x0,%r11d
530 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
531 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
533 *******************************************************************************/
535 bool patcher_instanceof_interface(patchref_t *pr)
538 constant_classref *cr;
541 ra = (uint8_t *) pr->mpc;
542 cr = (constant_classref *) pr->ref;
544 /* get the fieldinfo */
546 if (!(c = resolve_classref_eager(cr)))
549 PATCH_BACK_ORIGINAL_MCODE;
551 /* if we show disassembly, we have to skip the nop's */
554 ra = ra + PATCHER_CALL_SIZE;
556 /* patch super class index */
558 *((int32_t *) (ra + 7 + 3)) = c->index;
560 *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
561 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
562 c->index * sizeof(methodptr*));
569 * These are local overrides for various environment variables in Emacs.
570 * Please do not remove this and leave it at the end of the file, where
571 * Emacs will automagically detect them.
572 * ---------------------------------------------------------------------
575 * indent-tabs-mode: t
579 * vim:noexpandtab:sw=4:ts=4: