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
25 $Id: patcher.c 8160 2007-06-28 01:52:19Z michi $
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/asmpart.h"
45 #include "vm/jit/md.h"
46 #include "vm/jit/patcher-common.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 \
55 *((u4 *) pr->mpc) = (u4) pr->mcode; \
56 md_icacheflush((u1 *) pr->mpc, 1 * 4);
58 #define gen_resolveload(inst,offset) \
59 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
60 assert(!((inst) & 0x0fff)); \
62 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
63 /*(inst) &= ~(1 << 23);*/ \
65 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
66 /*(inst) |= (1 << 23);*/ \
70 /* patcher_get_putstatic *******************************************************
74 <patched call position>
75 e51c103c ldr r1, [ip, #-60]
77 *******************************************************************************/
79 bool patcher_get_putstatic(patchref_t *pr)
85 /* get stuff from the stack */
87 uf = (unresolved_field *) pr->ref;
88 datap = (u1 *) pr->datap;
90 /* get the fieldinfo */
92 if (!(fi = resolve_field_eager(uf)))
95 /* check if the field's class is initialized */
97 if (!(fi->class->state & CLASS_INITIALIZED))
98 if (!initialize_class(fi->class))
101 PATCH_BACK_ORIGINAL_MCODE;
103 /* patch the field value's address */
105 *((ptrint *) datap) = (ptrint) &(fi->value);
111 /* patcher_get_putfield ********************************************************
115 <patched call position>
116 e58a8000 str r8, [sl, #__]
118 *******************************************************************************/
120 bool patcher_get_putfield(patchref_t *pr)
124 unresolved_field *uf;
127 /* get stuff from the stack */
130 uf = (unresolved_field*) pr->ref;
132 /* get the fieldinfo */
134 if (!(fi = resolve_field_eager(uf)))
137 PATCH_BACK_ORIGINAL_MCODE;
139 /* if we show disassembly, we have to skip the nop */
141 if (opt_showdisassemble)
144 /* patch the field's offset into the instruction */
149 #if defined(ENABLE_SOFTFLOAT)
152 assert(fi->offset <= 0x0fff);
153 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
157 #if defined(ENABLE_SOFTFLOAT)
160 assert((fi->offset + 4) <= 0x0fff);
161 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
162 *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
163 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
166 #if !defined(ENABLE_SOFTFLOAT)
169 assert(fi->offset <= 0x03ff);
170 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
175 /* synchronize instruction cache */
177 md_icacheflush(ra, 2 * 4);
183 /* patcher_resolve_classref_to_classinfo ***************************************
185 ACONST - Machine code:
187 <patched call postition>
188 e51cc030 ldr r0, [ip, #-48]
190 MULTIANEWARRAY - Machine code:
192 <patched call position>
193 e3a00002 mov r0, #2 ; 0x2
194 e51c1064 ldr r1, [ip, #-100]
197 e51cf068 ldr pc, [ip, #-104]
199 ARRAYCHECKCAST - Machine code:
201 <patched call position>
202 e51c1120 ldr r1, [ip, #-288]
204 e51cf124 ldr pc, [ip, #-292]
206 *******************************************************************************/
208 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
210 constant_classref *cr;
214 /* get stuff from the stack */
216 cr = (constant_classref *) pr->ref;
217 datap = (u1 *) pr->datap;
219 /* get the classinfo */
221 if (!(c = resolve_classref_eager(cr)))
224 PATCH_BACK_ORIGINAL_MCODE;
226 /* patch the classinfo pointer */
228 *((ptrint *) datap) = (ptrint) c;
234 /* patcher_invokestatic_special ************************************************
238 <patched call position>
239 e51cc02c ldr ip, [ip, #-44]
243 ******************************************************************************/
245 bool patcher_invokestatic_special(patchref_t *pr)
247 unresolved_method *um;
251 /* get stuff from the stack */
253 um = (unresolved_method*) pr->ref;
254 datap = (u1 *) pr->datap;
256 /* get the methodinfo */
258 if (!(m = resolve_method_eager(um)))
261 PATCH_BACK_ORIGINAL_MCODE;
263 /* patch stubroutine */
265 *((ptrint *) datap) = (ptrint) m->stubroutine;
271 /* patcher_invokevirtual *******************************************************
275 <patched call position>
276 e590b000 ldr fp, [r0]
277 e59bc000 ldr ip, [fp, #__]
281 *******************************************************************************/
283 bool patcher_invokevirtual(patchref_t *pr)
286 unresolved_method *um;
289 /* get stuff from the stack */
292 um = (unresolved_method *) pr->ref;
294 /* get the methodinfo */
296 if (!(m = resolve_method_eager(um)))
299 PATCH_BACK_ORIGINAL_MCODE;
301 /* if we show disassembly, we have to skip the nop */
303 if (opt_showdisassemble)
306 /* patch vftbl index */
308 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
310 /* synchronize instruction cache */
312 md_icacheflush(ra + 1 * 4, 1 * 4);
318 /* patcher_invokeinterface *****************************************************
322 <patched call position>
323 e590b000 ldr fp, [r0]
324 e59bb000 ldr fp, [fp, #__]
325 e59bc000 ldr ip, [fp, #__]
330 *******************************************************************************/
332 bool patcher_invokeinterface(patchref_t *pr)
335 unresolved_method *um;
338 /* get stuff from the stack */
341 um = (unresolved_method *) pr->ref;
343 /* get the methodinfo */
345 if (!(m = resolve_method_eager(um)))
348 PATCH_BACK_ORIGINAL_MCODE;
350 /* if we show disassembly, we have to skip the nop */
352 if (opt_showdisassemble)
355 /* patch interfacetable index */
357 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
359 /* patch method offset */
361 gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
363 /* synchronize instruction cache */
365 md_icacheflush(ra + 1 * 4, 2 * 4);
371 /* patcher_checkcast_instanceof_flags ******************************************
375 <patched call position>
377 *******************************************************************************/
379 bool patcher_resolve_classref_to_flags(patchref_t *pr)
381 constant_classref *cr;
385 /* get stuff from the stack */
387 cr = (constant_classref *) pr->ref;
388 datap = (u1 *) pr->datap;
390 /* get the classinfo */
392 if (!(c = resolve_classref_eager(cr)))
395 PATCH_BACK_ORIGINAL_MCODE;
397 /* patch class flags */
399 *((s4 *) datap) = (s4) c->flags;
405 /* patcher_resolve_classref_to_index *******************************************
409 <patched call position>
411 *******************************************************************************/
413 bool patcher_resolve_classref_to_index(patchref_t *pr)
415 constant_classref *cr;
419 /* get stuff from the stack */
421 cr = (constant_classref *) pr->ref;
422 datap = (u1 *) pr->datap;
424 /* get the classinfo */
426 if (!(c = resolve_classref_eager(cr)))
429 PATCH_BACK_ORIGINAL_MCODE;
431 /* patch super class index */
433 *((s4 *) datap) = (s4) c->index;
439 /* patcher_resolve_classref_to_vftbl *******************************************
443 <patched call position>
445 *******************************************************************************/
447 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
449 constant_classref *cr;
453 /* get stuff from the stack */
455 cr = (constant_classref *) pr->ref;
456 datap = (u1 *) pr->datap;
458 /* get the classinfo */
460 if (!(c = resolve_classref_eager(cr)))
463 PATCH_BACK_ORIGINAL_MCODE;
465 /* patch super class' vftbl */
467 *((ptrint *) datap) = (ptrint) c->vftbl;
473 /* patcher_initialize_class ****************************************************
477 *******************************************************************************/
479 bool patcher_initialize_class(patchref_t *pr)
483 /* get stuff from the stack */
485 c = (classinfo *) pr->ref;
487 /* check if the class is initialized */
489 if (!(c->state & CLASS_INITIALIZED))
490 if (!initialize_class(c))
493 PATCH_BACK_ORIGINAL_MCODE;
499 /* patcher_resolve_class *******************************************************
503 <patched call position>
505 *******************************************************************************/
507 #ifdef ENABLE_VERIFIER
508 bool patcher_resolve_class(patchref_t *pr)
510 unresolved_class *uc;
512 /* get stuff from the stack */
514 uc = (unresolved_class *) pr->ref;
516 /* resolve the class and check subtype constraints */
518 if (!resolve_class_eager_no_access_check(uc))
521 PATCH_BACK_ORIGINAL_MCODE;
525 #endif /* ENABLE_VERIFIER */
528 /* patcher_resolve_native_function *********************************************
532 *******************************************************************************/
534 #if !defined(WITH_STATIC_CLASSPATH)
535 bool patcher_resolve_native_function(patchref_t *pr)
541 /* get stuff from the stack */
543 m = (methodinfo *) pr->ref;
544 datap = (u1 *) pr->datap;
546 /* resolve native function */
548 if (!(f = native_resolve_function(m)))
551 PATCH_BACK_ORIGINAL_MCODE;
553 /* patch native function pointer */
555 *((ptrint *) datap) = (ptrint) f;
559 #endif /* !defined(WITH_STATIC_CLASSPATH) */
563 * These are local overrides for various environment variables in Emacs.
564 * Please do not remove this and leave it at the end of the file, where
565 * Emacs will automagically detect them.
566 * ---------------------------------------------------------------------
569 * indent-tabs-mode: t
573 * vim:noexpandtab:sw=4:ts=4: