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 8268 2007-08-07 13:24:43Z twisti $
37 #include "mm/memory.h"
39 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/initialize.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/md.h"
47 #include "vm/jit/patcher-common.h"
49 #include "vmcore/field.h"
50 #include "vmcore/options.h"
51 #include "vmcore/references.h"
52 #include "vm/resolve.h"
55 #define PATCH_BACK_ORIGINAL_MCODE \
56 *((u4 *) pr->mpc) = (u4) pr->mcode; \
57 md_icacheflush((u1 *) pr->mpc, 1 * 4);
59 #define gen_resolveload(inst,offset) \
60 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
61 assert(!((inst) & 0x0fff)); \
63 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
64 /*(inst) &= ~(1 << 23);*/ \
66 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
67 /*(inst) |= (1 << 23);*/ \
71 /* patcher_get_putstatic *******************************************************
75 <patched call position>
76 e51c103c ldr r1, [ip, #-60]
78 *******************************************************************************/
80 bool patcher_get_putstatic(patchref_t *pr)
86 /* get stuff from the stack */
88 uf = (unresolved_field *) pr->ref;
89 datap = (u1 *) pr->datap;
91 /* get the fieldinfo */
93 if (!(fi = resolve_field_eager(uf)))
96 /* check if the field's class is initialized */
98 if (!(fi->class->state & CLASS_INITIALIZED))
99 if (!initialize_class(fi->class))
102 PATCH_BACK_ORIGINAL_MCODE;
104 /* patch the field value's address */
106 *((intptr_t *) datap) = (intptr_t) fi->value;
112 /* patcher_get_putfield ********************************************************
116 <patched call position>
117 e58a8000 str r8, [sl, #__]
119 *******************************************************************************/
121 bool patcher_get_putfield(patchref_t *pr)
125 unresolved_field *uf;
128 /* get stuff from the stack */
131 uf = (unresolved_field*) pr->ref;
133 /* get the fieldinfo */
135 if (!(fi = resolve_field_eager(uf)))
138 PATCH_BACK_ORIGINAL_MCODE;
140 /* if we show disassembly, we have to skip the nop */
142 if (opt_showdisassemble)
145 /* patch the field's offset into the instruction */
150 #if defined(ENABLE_SOFTFLOAT)
153 assert(fi->offset <= 0x0fff);
154 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
158 #if defined(ENABLE_SOFTFLOAT)
161 assert((fi->offset + 4) <= 0x0fff);
162 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
163 *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
164 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
167 #if !defined(ENABLE_SOFTFLOAT)
170 assert(fi->offset <= 0x03ff);
171 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
176 /* synchronize instruction cache */
178 md_icacheflush(ra, 2 * 4);
184 /* patcher_resolve_classref_to_classinfo ***************************************
186 ACONST - Machine code:
188 <patched call postition>
189 e51cc030 ldr r0, [ip, #-48]
191 MULTIANEWARRAY - Machine code:
193 <patched call position>
194 e3a00002 mov r0, #2 ; 0x2
195 e51c1064 ldr r1, [ip, #-100]
198 e51cf068 ldr pc, [ip, #-104]
200 ARRAYCHECKCAST - Machine code:
202 <patched call position>
203 e51c1120 ldr r1, [ip, #-288]
205 e51cf124 ldr pc, [ip, #-292]
207 *******************************************************************************/
209 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
211 constant_classref *cr;
215 /* get stuff from the stack */
217 cr = (constant_classref *) pr->ref;
218 datap = (u1 *) pr->datap;
220 /* get the classinfo */
222 if (!(c = resolve_classref_eager(cr)))
225 PATCH_BACK_ORIGINAL_MCODE;
227 /* patch the classinfo pointer */
229 *((ptrint *) datap) = (ptrint) c;
235 /* patcher_invokestatic_special ************************************************
239 <patched call position>
240 e51cc02c ldr ip, [ip, #-44]
244 ******************************************************************************/
246 bool patcher_invokestatic_special(patchref_t *pr)
248 unresolved_method *um;
252 /* get stuff from the stack */
254 um = (unresolved_method*) pr->ref;
255 datap = (u1 *) pr->datap;
257 /* get the methodinfo */
259 if (!(m = resolve_method_eager(um)))
262 PATCH_BACK_ORIGINAL_MCODE;
264 /* patch stubroutine */
266 *((ptrint *) datap) = (ptrint) m->stubroutine;
272 /* patcher_invokevirtual *******************************************************
276 <patched call position>
277 e590b000 ldr fp, [r0]
278 e59bc000 ldr ip, [fp, #__]
282 *******************************************************************************/
284 bool patcher_invokevirtual(patchref_t *pr)
287 unresolved_method *um;
290 /* get stuff from the stack */
293 um = (unresolved_method *) pr->ref;
295 /* get the methodinfo */
297 if (!(m = resolve_method_eager(um)))
300 PATCH_BACK_ORIGINAL_MCODE;
302 /* if we show disassembly, we have to skip the nop */
304 if (opt_showdisassemble)
307 /* patch vftbl index */
309 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
311 /* synchronize instruction cache */
313 md_icacheflush(ra + 1 * 4, 1 * 4);
319 /* patcher_invokeinterface *****************************************************
323 <patched call position>
324 e590b000 ldr fp, [r0]
325 e59bb000 ldr fp, [fp, #__]
326 e59bc000 ldr ip, [fp, #__]
331 *******************************************************************************/
333 bool patcher_invokeinterface(patchref_t *pr)
336 unresolved_method *um;
339 /* get stuff from the stack */
342 um = (unresolved_method *) pr->ref;
344 /* get the methodinfo */
346 if (!(m = resolve_method_eager(um)))
349 PATCH_BACK_ORIGINAL_MCODE;
351 /* if we show disassembly, we have to skip the nop */
353 if (opt_showdisassemble)
356 /* patch interfacetable index */
358 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
360 /* patch method offset */
362 gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
364 /* synchronize instruction cache */
366 md_icacheflush(ra + 1 * 4, 2 * 4);
372 /* patcher_checkcast_instanceof_flags ******************************************
376 <patched call position>
378 *******************************************************************************/
380 bool patcher_resolve_classref_to_flags(patchref_t *pr)
382 constant_classref *cr;
386 /* get stuff from the stack */
388 cr = (constant_classref *) pr->ref;
389 datap = (u1 *) pr->datap;
391 /* get the classinfo */
393 if (!(c = resolve_classref_eager(cr)))
396 PATCH_BACK_ORIGINAL_MCODE;
398 /* patch class flags */
400 *((s4 *) datap) = (s4) c->flags;
406 /* patcher_resolve_classref_to_index *******************************************
410 <patched call position>
412 *******************************************************************************/
414 bool patcher_resolve_classref_to_index(patchref_t *pr)
416 constant_classref *cr;
420 /* get stuff from the stack */
422 cr = (constant_classref *) pr->ref;
423 datap = (u1 *) pr->datap;
425 /* get the classinfo */
427 if (!(c = resolve_classref_eager(cr)))
430 PATCH_BACK_ORIGINAL_MCODE;
432 /* patch super class index */
434 *((s4 *) datap) = (s4) c->index;
440 /* patcher_resolve_classref_to_vftbl *******************************************
444 <patched call position>
446 *******************************************************************************/
448 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
450 constant_classref *cr;
454 /* get stuff from the stack */
456 cr = (constant_classref *) pr->ref;
457 datap = (u1 *) pr->datap;
459 /* get the classinfo */
461 if (!(c = resolve_classref_eager(cr)))
464 PATCH_BACK_ORIGINAL_MCODE;
466 /* patch super class' vftbl */
468 *((ptrint *) datap) = (ptrint) c->vftbl;
474 /* patcher_initialize_class ****************************************************
478 *******************************************************************************/
480 bool patcher_initialize_class(patchref_t *pr)
484 /* get stuff from the stack */
486 c = (classinfo *) pr->ref;
488 /* check if the class is initialized */
490 if (!(c->state & CLASS_INITIALIZED))
491 if (!initialize_class(c))
494 PATCH_BACK_ORIGINAL_MCODE;
500 /* patcher_resolve_class *******************************************************
504 <patched call position>
506 *******************************************************************************/
508 #ifdef ENABLE_VERIFIER
509 bool patcher_resolve_class(patchref_t *pr)
511 unresolved_class *uc;
513 /* get stuff from the stack */
515 uc = (unresolved_class *) pr->ref;
517 /* resolve the class and check subtype constraints */
519 if (!resolve_class_eager_no_access_check(uc))
522 PATCH_BACK_ORIGINAL_MCODE;
526 #endif /* ENABLE_VERIFIER */
529 /* patcher_resolve_native_function *********************************************
533 *******************************************************************************/
535 #if !defined(WITH_STATIC_CLASSPATH)
536 bool patcher_resolve_native_function(patchref_t *pr)
542 /* get stuff from the stack */
544 m = (methodinfo *) pr->ref;
545 datap = (u1 *) pr->datap;
547 /* resolve native function */
549 if (!(f = native_resolve_function(m)))
552 PATCH_BACK_ORIGINAL_MCODE;
554 /* patch native function pointer */
556 *((ptrint *) datap) = (ptrint) f;
560 #endif /* !defined(WITH_STATIC_CLASSPATH) */
564 * These are local overrides for various environment variables in Emacs.
565 * Please do not remove this and leave it at the end of the file, where
566 * Emacs will automagically detect them.
567 * ---------------------------------------------------------------------
570 * indent-tabs-mode: t
574 * vim:noexpandtab:sw=4:ts=4: