1 /* src/vm/jit/arm/patcher.c - ARM 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
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/asmpart.h"
44 #include "vm/jit/md.h"
45 #include "vm/jit/patcher-common.h"
47 #include "vmcore/field.h"
48 #include "vmcore/options.h"
49 #include "vmcore/references.h"
50 #include "vm/resolve.h"
53 #define PATCH_BACK_ORIGINAL_MCODE \
54 *((u4 *) pr->mpc) = (u4) pr->mcode; \
55 md_icacheflush((u1 *) pr->mpc, 1 * 4);
57 #define gen_resolveload(inst,offset) \
58 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
59 assert(!((inst) & 0x0fff)); \
61 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
62 /*(inst) &= ~(1 << 23);*/ \
64 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
65 /*(inst) |= (1 << 23);*/ \
69 /* patcher_get_putstatic *******************************************************
73 <patched call position>
74 e51c103c ldr r1, [ip, #-60]
76 *******************************************************************************/
78 bool patcher_get_putstatic(patchref_t *pr)
84 /* get stuff from the stack */
86 uf = (unresolved_field *) pr->ref;
87 datap = (u1 *) pr->datap;
89 /* get the fieldinfo */
91 if (!(fi = resolve_field_eager(uf)))
94 /* check if the field's class is initialized */
96 if (!(fi->class->state & CLASS_INITIALIZED))
97 if (!initialize_class(fi->class))
100 PATCH_BACK_ORIGINAL_MCODE;
102 /* patch the field value's address */
104 *((intptr_t *) datap) = (intptr_t) fi->value;
110 /* patcher_get_putfield ********************************************************
114 <patched call position>
115 e58a8000 str r8, [sl, #__]
117 *******************************************************************************/
119 bool patcher_get_putfield(patchref_t *pr)
123 unresolved_field *uf;
126 /* get stuff from the stack */
129 uf = (unresolved_field*) pr->ref;
131 /* get the fieldinfo */
133 if (!(fi = resolve_field_eager(uf)))
136 PATCH_BACK_ORIGINAL_MCODE;
138 /* if we show disassembly, we have to skip the nop */
140 if (opt_showdisassemble)
143 /* patch the field's offset into the instruction */
148 #if defined(ENABLE_SOFTFLOAT)
151 assert(fi->offset <= 0x0fff);
152 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
156 #if defined(ENABLE_SOFTFLOAT)
159 assert((fi->offset + 4) <= 0x0fff);
160 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
161 *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
162 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
165 #if !defined(ENABLE_SOFTFLOAT)
168 assert(fi->offset <= 0x03ff);
169 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
174 /* synchronize instruction cache */
176 md_icacheflush(ra, 2 * 4);
182 /* patcher_resolve_classref_to_classinfo ***************************************
184 ACONST - Machine code:
186 <patched call postition>
187 e51cc030 ldr r0, [ip, #-48]
189 MULTIANEWARRAY - Machine code:
191 <patched call position>
192 e3a00002 mov r0, #2 ; 0x2
193 e51c1064 ldr r1, [ip, #-100]
196 e51cf068 ldr pc, [ip, #-104]
198 ARRAYCHECKCAST - Machine code:
200 <patched call position>
201 e51c1120 ldr r1, [ip, #-288]
203 e51cf124 ldr pc, [ip, #-292]
205 *******************************************************************************/
207 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
209 constant_classref *cr;
213 /* get stuff from the stack */
215 cr = (constant_classref *) pr->ref;
216 datap = (u1 *) pr->datap;
218 /* get the classinfo */
220 if (!(c = resolve_classref_eager(cr)))
223 PATCH_BACK_ORIGINAL_MCODE;
225 /* patch the classinfo pointer */
227 *((ptrint *) datap) = (ptrint) c;
233 /* patcher_invokestatic_special ************************************************
237 <patched call position>
238 e51cc02c ldr ip, [ip, #-44]
242 ******************************************************************************/
244 bool patcher_invokestatic_special(patchref_t *pr)
246 unresolved_method *um;
250 /* get stuff from the stack */
252 um = (unresolved_method*) pr->ref;
253 datap = (u1 *) pr->datap;
255 /* get the methodinfo */
257 if (!(m = resolve_method_eager(um)))
260 PATCH_BACK_ORIGINAL_MCODE;
262 /* patch stubroutine */
264 *((ptrint *) datap) = (ptrint) m->stubroutine;
270 /* patcher_invokevirtual *******************************************************
274 <patched call position>
275 e590b000 ldr fp, [r0]
276 e59bc000 ldr ip, [fp, #__]
280 *******************************************************************************/
282 bool patcher_invokevirtual(patchref_t *pr)
285 unresolved_method *um;
288 /* get stuff from the stack */
291 um = (unresolved_method *) pr->ref;
293 /* get the methodinfo */
295 if (!(m = resolve_method_eager(um)))
298 PATCH_BACK_ORIGINAL_MCODE;
300 /* if we show disassembly, we have to skip the nop */
302 if (opt_showdisassemble)
305 /* patch vftbl index */
307 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
309 /* synchronize instruction cache */
311 md_icacheflush(ra + 1 * 4, 1 * 4);
317 /* patcher_invokeinterface *****************************************************
321 <patched call position>
322 e590b000 ldr fp, [r0]
323 e59bb000 ldr fp, [fp, #__]
324 e59bc000 ldr ip, [fp, #__]
329 *******************************************************************************/
331 bool patcher_invokeinterface(patchref_t *pr)
334 unresolved_method *um;
337 /* get stuff from the stack */
340 um = (unresolved_method *) pr->ref;
342 /* get the methodinfo */
344 if (!(m = resolve_method_eager(um)))
347 PATCH_BACK_ORIGINAL_MCODE;
349 /* if we show disassembly, we have to skip the nop */
351 if (opt_showdisassemble)
354 /* patch interfacetable index */
356 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
358 /* patch method offset */
360 gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
362 /* synchronize instruction cache */
364 md_icacheflush(ra + 1 * 4, 2 * 4);
370 /* patcher_checkcast_instanceof_flags ******************************************
374 <patched call position>
376 *******************************************************************************/
378 bool patcher_resolve_classref_to_flags(patchref_t *pr)
380 constant_classref *cr;
384 /* get stuff from the stack */
386 cr = (constant_classref *) pr->ref;
387 datap = (u1 *) pr->datap;
389 /* get the classinfo */
391 if (!(c = resolve_classref_eager(cr)))
394 PATCH_BACK_ORIGINAL_MCODE;
396 /* patch class flags */
398 *((s4 *) datap) = (s4) c->flags;
404 /* patcher_resolve_classref_to_index *******************************************
408 <patched call position>
410 *******************************************************************************/
412 bool patcher_resolve_classref_to_index(patchref_t *pr)
414 constant_classref *cr;
418 /* get stuff from the stack */
420 cr = (constant_classref *) pr->ref;
421 datap = (u1 *) pr->datap;
423 /* get the classinfo */
425 if (!(c = resolve_classref_eager(cr)))
428 PATCH_BACK_ORIGINAL_MCODE;
430 /* patch super class index */
432 *((s4 *) datap) = (s4) c->index;
438 /* patcher_resolve_classref_to_vftbl *******************************************
442 <patched call position>
444 *******************************************************************************/
446 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
448 constant_classref *cr;
452 /* get stuff from the stack */
454 cr = (constant_classref *) pr->ref;
455 datap = (u1 *) pr->datap;
457 /* get the classinfo */
459 if (!(c = resolve_classref_eager(cr)))
462 PATCH_BACK_ORIGINAL_MCODE;
464 /* patch super class' vftbl */
466 *((ptrint *) datap) = (ptrint) c->vftbl;
472 /* patcher_initialize_class ****************************************************
476 *******************************************************************************/
478 bool patcher_initialize_class(patchref_t *pr)
482 /* get stuff from the stack */
484 c = (classinfo *) pr->ref;
486 /* check if the class is initialized */
488 if (!(c->state & CLASS_INITIALIZED))
489 if (!initialize_class(c))
492 PATCH_BACK_ORIGINAL_MCODE;
498 /* patcher_resolve_class *******************************************************
502 <patched call position>
504 *******************************************************************************/
506 #ifdef ENABLE_VERIFIER
507 bool patcher_resolve_class(patchref_t *pr)
509 unresolved_class *uc;
511 /* get stuff from the stack */
513 uc = (unresolved_class *) pr->ref;
515 /* resolve the class and check subtype constraints */
517 if (!resolve_class_eager_no_access_check(uc))
520 PATCH_BACK_ORIGINAL_MCODE;
524 #endif /* ENABLE_VERIFIER */
527 /* patcher_resolve_native_function *********************************************
531 *******************************************************************************/
533 #if !defined(WITH_STATIC_CLASSPATH)
534 bool patcher_resolve_native_function(patchref_t *pr)
540 /* get stuff from the stack */
542 m = (methodinfo *) pr->ref;
543 datap = (u1 *) pr->datap;
545 /* resolve native function */
547 if (!(f = native_resolve_function(m)))
550 PATCH_BACK_ORIGINAL_MCODE;
552 /* patch native function pointer */
554 *((ptrint *) datap) = (ptrint) f;
558 #endif /* !defined(WITH_STATIC_CLASSPATH) */
562 * These are local overrides for various environment variables in Emacs.
563 * Please do not remove this and leave it at the end of the file, where
564 * Emacs will automagically detect them.
565 * ---------------------------------------------------------------------
568 * indent-tabs-mode: t
572 * vim:noexpandtab:sw=4:ts=4: