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/exceptions.h"
40 #include "vm/initialize.h"
42 #include "vm/jit/patcher-common.h"
43 #include "vm/jit/stacktrace.h"
45 #include "vmcore/class.h"
46 #include "vmcore/field.h"
47 #include "vmcore/options.h"
48 #include "vmcore/references.h"
49 #include "vm/resolve.h"
52 #define PATCH_BACK_ORIGINAL_MCODE \
54 *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
58 /* patcher_patch_code **********************************************************
60 Just patches back the original machine code.
62 *******************************************************************************/
64 void patcher_patch_code(patchref_t *pr)
66 PATCH_BACK_ORIGINAL_MCODE;
70 /* patcher_resolve_classref_to_classinfo ***************************************
74 <patched call position>
75 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
79 <patched call position>
80 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
81 48 89 e2 mov %rsp,%rdx
82 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
87 <patched call position>
88 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
89 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
92 *******************************************************************************/
94 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
96 constant_classref *cr;
100 cr = (constant_classref *) pr->ref;
101 datap = (intptr_t *) pr->datap;
103 /* get the classinfo */
105 if (!(c = resolve_classref_eager(cr)))
108 PATCH_BACK_ORIGINAL_MCODE;
110 /* patch the classinfo pointer */
112 *datap = (intptr_t) c;
118 /* patcher_resolve_classref_to_vftbl *******************************************
123 <patched call position>
125 *******************************************************************************/
127 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
129 constant_classref *cr;
133 /* get stuff from the stack */
135 cr = (constant_classref *) pr->ref;
136 datap = (intptr_t *) pr->datap;
138 /* get the fieldinfo */
140 if (!(c = resolve_classref_eager(cr)))
143 PATCH_BACK_ORIGINAL_MCODE;
145 /* patch super class' vftbl */
147 *datap = (intptr_t) c->vftbl;
153 /* patcher_resolve_classref_to_flags *******************************************
155 CHECKCAST/INSTANCEOF:
157 <patched call position>
159 *******************************************************************************/
161 bool patcher_resolve_classref_to_flags(patchref_t *pr)
163 constant_classref *cr;
168 cr = (constant_classref *) pr->ref;
169 datap = (int32_t *) pr->datap;
170 ra = (uint8_t *) pr->mpc;
172 /* get the fieldinfo */
174 if (!(c = resolve_classref_eager(cr)))
177 PATCH_BACK_ORIGINAL_MCODE;
179 /* if we show disassembly, we have to skip the nop's */
182 ra = ra + PATCHER_CALL_SIZE;
184 /* patch class flags */
186 /* *datap = c->flags; */
187 *((int32_t *) (ra + 2)) = c->flags;
193 /* patcher_get_putstatic *******************************************************
197 <patched call position>
198 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
199 49 8b 32 mov (%r10),%rsi
201 *******************************************************************************/
203 bool patcher_get_putstatic(patchref_t *pr)
205 unresolved_field *uf;
209 uf = (unresolved_field *) pr->ref;
210 datap = (intptr_t *) pr->datap;
212 /* get the fieldinfo */
214 if (!(fi = resolve_field_eager(uf)))
217 /* check if the field's class is initialized */
219 if (!(fi->clazz->state & CLASS_INITIALIZED))
220 if (!initialize_class(fi->clazz))
223 PATCH_BACK_ORIGINAL_MCODE;
225 /* patch the field value's address */
227 *datap = (intptr_t) fi->value;
233 /* patcher_get_putfield ********************************************************
237 <patched call position>
238 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
240 *******************************************************************************/
242 bool patcher_get_putfield(patchref_t *pr)
245 unresolved_field *uf;
249 ra = (uint8_t *) pr->mpc;
250 uf = (unresolved_field *) pr->ref;
252 /* get the fieldinfo */
254 if (!(fi = resolve_field_eager(uf)))
257 PATCH_BACK_ORIGINAL_MCODE;
259 /* if we show disassembly, we have to skip the nop's */
262 ra = ra + PATCHER_CALL_SIZE;
264 /* Patch the field's offset: we check for the field type, because
265 the instructions have different lengths. */
267 if (IS_INT_LNG_TYPE(fi->type)) {
268 /* Check for special case: %rsp or %r12 as base register. */
273 *((int32_t *) (ra + 4)) = fi->offset;
275 *((int32_t *) (ra + 3)) = fi->offset;
278 /* Check for special case: %rsp or %r12 as base register. */
283 *((int32_t *) (ra + 6)) = fi->offset;
285 *((int32_t *) (ra + 5)) = fi->offset;
292 /* patcher_putfieldconst *******************************************************
296 <patched call position>
297 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
299 *******************************************************************************/
301 bool patcher_putfieldconst(patchref_t *pr)
304 unresolved_field *uf;
308 ra = (uint8_t *) pr->mpc;
309 uf = (unresolved_field *) pr->ref;
311 /* get the fieldinfo */
313 if (!(fi = resolve_field_eager(uf)))
316 PATCH_BACK_ORIGINAL_MCODE;
318 /* if we show disassembly, we have to skip the nop's */
321 ra = ra + PATCHER_CALL_SIZE;
323 /* patch the field's offset */
325 if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
326 /* handle special case when the base register is %r12 */
331 *((uint32_t *) (ra + 4)) = fi->offset;
332 *((uint32_t *) (ra + 12 + 4)) = fi->offset + 4;
335 *((uint32_t *) (ra + 3)) = fi->offset;
336 *((uint32_t *) (ra + 11 + 3)) = fi->offset + 4;
340 /* handle special case when the base register is %r12 */
345 *((uint32_t *) (ra + 4)) = fi->offset;
347 *((uint32_t *) (ra + 3)) = fi->offset;
354 /* patcher_invokestatic_special ************************************************
358 <patched call position>
359 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
362 *******************************************************************************/
364 bool patcher_invokestatic_special(patchref_t *pr)
366 unresolved_method *um;
370 /* get stuff from the stack */
372 um = (unresolved_method *) pr->ref;
373 datap = (intptr_t *) pr->datap;
375 /* get the fieldinfo */
377 if (!(m = resolve_method_eager(um)))
380 PATCH_BACK_ORIGINAL_MCODE;
382 /* patch stubroutine */
384 *datap = (intptr_t) m->stubroutine;
390 /* patcher_invokevirtual *******************************************************
394 <patched call position>
395 4c 8b 17 mov (%rdi),%r10
396 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
399 *******************************************************************************/
401 bool patcher_invokevirtual(patchref_t *pr)
404 unresolved_method *um;
407 ra = (uint8_t *) pr->mpc;
408 um = (unresolved_method *) pr->ref;
410 /* get the methodinfo */
412 if (!(m = resolve_method_eager(um)))
415 PATCH_BACK_ORIGINAL_MCODE;
417 /* if we show disassembly, we have to skip the nop's */
420 ra = ra + PATCHER_CALL_SIZE;
422 /* patch vftbl index */
424 *((int32_t *) (ra + 3 + 3)) =
425 (int32_t) (OFFSET(vftbl_t, table[0]) +
426 sizeof(methodptr) * m->vftblindex);
432 /* patcher_invokeinterface *****************************************************
436 <patched call position>
437 4c 8b 17 mov (%rdi),%r10
438 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
439 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
442 *******************************************************************************/
444 bool patcher_invokeinterface(patchref_t *pr)
447 unresolved_method *um;
450 /* get stuff from the stack */
452 ra = (uint8_t *) pr->mpc;
453 um = (unresolved_method *) pr->ref;
455 /* get the fieldinfo */
457 if (!(m = resolve_method_eager(um)))
460 PATCH_BACK_ORIGINAL_MCODE;
462 /* if we show disassembly, we have to skip the nop's */
465 ra = ra + PATCHER_CALL_SIZE;
467 /* patch interfacetable index */
469 *((int32_t *) (ra + 3 + 3)) =
470 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
471 sizeof(methodptr) * m->clazz->index);
473 /* patch method offset */
475 *((int32_t *) (ra + 3 + 7 + 3)) =
476 (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
482 /* patcher_checkcast_interface *************************************************
486 <patched call position>
487 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
488 41 81 fb 00 00 00 00 cmp $0x0,%r11d
489 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
490 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
491 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
493 *******************************************************************************/
495 bool patcher_checkcast_interface(patchref_t *pr)
498 constant_classref *cr;
501 ra = (uint8_t *) pr->mpc;
502 cr = (constant_classref *) pr->ref;
504 /* get the fieldinfo */
506 if (!(c = resolve_classref_eager(cr)))
509 PATCH_BACK_ORIGINAL_MCODE;
511 /* if we show disassembly, we have to skip the nop's */
514 ra = ra + PATCHER_CALL_SIZE;
516 /* patch super class index */
518 *((int32_t *) (ra + 7 + 3)) = c->index;
520 *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
521 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
522 c->index * sizeof(methodptr*));
528 /* patcher_instanceof_interface ************************************************
532 <patched call position>
533 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
534 41 81 fb 00 00 00 00 cmp $0x0,%r11d
535 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
536 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
538 *******************************************************************************/
540 bool patcher_instanceof_interface(patchref_t *pr)
543 constant_classref *cr;
546 ra = (uint8_t *) pr->mpc;
547 cr = (constant_classref *) pr->ref;
549 /* get the fieldinfo */
551 if (!(c = resolve_classref_eager(cr)))
554 PATCH_BACK_ORIGINAL_MCODE;
556 /* if we show disassembly, we have to skip the nop's */
559 ra = ra + PATCHER_CALL_SIZE;
561 /* patch super class index */
563 *((int32_t *) (ra + 7 + 3)) = c->index;
565 *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
566 (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
567 c->index * sizeof(methodptr*));
574 * These are local overrides for various environment variables in Emacs.
575 * Please do not remove this and leave it at the end of the file, where
576 * Emacs will automagically detect them.
577 * ---------------------------------------------------------------------
580 * indent-tabs-mode: t
584 * vim:noexpandtab:sw=4:ts=4: