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_patch_code **********************************************************
71 Just patches back the original machine code.
73 *******************************************************************************/
75 void patcher_patch_code(patchref_t *pr)
77 PATCH_BACK_ORIGINAL_MCODE;
81 /* patcher_get_putstatic *******************************************************
85 <patched call position>
86 e51c103c ldr r1, [ip, #-60]
88 *******************************************************************************/
90 bool patcher_get_putstatic(patchref_t *pr)
96 /* get stuff from the stack */
98 uf = (unresolved_field *) pr->ref;
99 datap = (u1 *) pr->datap;
101 /* get the fieldinfo */
103 if (!(fi = resolve_field_eager(uf)))
106 /* check if the field's class is initialized */
108 if (!(fi->class->state & CLASS_INITIALIZED))
109 if (!initialize_class(fi->class))
112 PATCH_BACK_ORIGINAL_MCODE;
114 /* patch the field value's address */
116 *((intptr_t *) datap) = (intptr_t) fi->value;
122 /* patcher_get_putfield ********************************************************
126 <patched call position>
127 e58a8000 str r8, [sl, #__]
129 *******************************************************************************/
131 bool patcher_get_putfield(patchref_t *pr)
135 unresolved_field *uf;
138 /* get stuff from the stack */
141 uf = (unresolved_field*) pr->ref;
143 /* get the fieldinfo */
145 if (!(fi = resolve_field_eager(uf)))
148 PATCH_BACK_ORIGINAL_MCODE;
150 /* if we show disassembly, we have to skip the nop */
155 /* patch the field's offset into the instruction */
160 #if defined(ENABLE_SOFTFLOAT)
163 assert(fi->offset <= 0x0fff);
164 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
168 #if defined(ENABLE_SOFTFLOAT)
171 assert((fi->offset + 4) <= 0x0fff);
172 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
173 *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
174 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
177 #if !defined(ENABLE_SOFTFLOAT)
180 assert(fi->offset <= 0x03ff);
181 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
186 /* synchronize instruction cache */
188 md_icacheflush(ra, 2 * 4);
194 /* patcher_resolve_classref_to_classinfo ***************************************
196 ACONST - Machine code:
198 <patched call postition>
199 e51cc030 ldr r0, [ip, #-48]
201 MULTIANEWARRAY - Machine code:
203 <patched call position>
204 e3a00002 mov r0, #2 ; 0x2
205 e51c1064 ldr r1, [ip, #-100]
208 e51cf068 ldr pc, [ip, #-104]
210 ARRAYCHECKCAST - Machine code:
212 <patched call position>
213 e51c1120 ldr r1, [ip, #-288]
215 e51cf124 ldr pc, [ip, #-292]
217 *******************************************************************************/
219 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
221 constant_classref *cr;
225 /* get stuff from the stack */
227 cr = (constant_classref *) pr->ref;
228 datap = (u1 *) pr->datap;
230 /* get the classinfo */
232 if (!(c = resolve_classref_eager(cr)))
235 PATCH_BACK_ORIGINAL_MCODE;
237 /* patch the classinfo pointer */
239 *((ptrint *) datap) = (ptrint) c;
245 /* patcher_invokestatic_special ************************************************
249 <patched call position>
250 e51cc02c ldr ip, [ip, #-44]
254 ******************************************************************************/
256 bool patcher_invokestatic_special(patchref_t *pr)
258 unresolved_method *um;
262 /* get stuff from the stack */
264 um = (unresolved_method*) pr->ref;
265 datap = (u1 *) pr->datap;
267 /* get the methodinfo */
269 if (!(m = resolve_method_eager(um)))
272 PATCH_BACK_ORIGINAL_MCODE;
274 /* patch stubroutine */
276 *((ptrint *) datap) = (ptrint) m->stubroutine;
282 /* patcher_invokevirtual *******************************************************
286 <patched call position>
287 e590b000 ldr fp, [r0]
288 e59bc000 ldr ip, [fp, #__]
292 *******************************************************************************/
294 bool patcher_invokevirtual(patchref_t *pr)
297 unresolved_method *um;
300 /* get stuff from the stack */
303 um = (unresolved_method *) pr->ref;
305 /* get the methodinfo */
307 if (!(m = resolve_method_eager(um)))
310 PATCH_BACK_ORIGINAL_MCODE;
312 /* if we show disassembly, we have to skip the nop */
317 /* patch vftbl index */
319 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
321 /* synchronize instruction cache */
323 md_icacheflush(ra + 1 * 4, 1 * 4);
329 /* patcher_invokeinterface *****************************************************
333 <patched call position>
334 e590b000 ldr fp, [r0]
335 e59bb000 ldr fp, [fp, #__]
336 e59bc000 ldr ip, [fp, #__]
341 *******************************************************************************/
343 bool patcher_invokeinterface(patchref_t *pr)
346 unresolved_method *um;
349 /* get stuff from the stack */
352 um = (unresolved_method *) pr->ref;
354 /* get the methodinfo */
356 if (!(m = resolve_method_eager(um)))
359 PATCH_BACK_ORIGINAL_MCODE;
361 /* if we show disassembly, we have to skip the nop */
366 /* patch interfacetable index */
368 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
370 /* patch method offset */
372 gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
374 /* synchronize instruction cache */
376 md_icacheflush(ra + 1 * 4, 2 * 4);
382 /* patcher_checkcast_instanceof_flags ******************************************
386 <patched call position>
388 *******************************************************************************/
390 bool patcher_resolve_classref_to_flags(patchref_t *pr)
392 constant_classref *cr;
396 /* get stuff from the stack */
398 cr = (constant_classref *) pr->ref;
399 datap = (u1 *) pr->datap;
401 /* get the classinfo */
403 if (!(c = resolve_classref_eager(cr)))
406 PATCH_BACK_ORIGINAL_MCODE;
408 /* patch class flags */
410 *((s4 *) datap) = (s4) c->flags;
416 /* patcher_resolve_classref_to_index *******************************************
420 <patched call position>
422 *******************************************************************************/
424 bool patcher_resolve_classref_to_index(patchref_t *pr)
426 constant_classref *cr;
430 /* get stuff from the stack */
432 cr = (constant_classref *) pr->ref;
433 datap = (u1 *) pr->datap;
435 /* get the classinfo */
437 if (!(c = resolve_classref_eager(cr)))
440 PATCH_BACK_ORIGINAL_MCODE;
442 /* patch super class index */
444 *((s4 *) datap) = (s4) c->index;
450 /* patcher_resolve_classref_to_vftbl *******************************************
454 <patched call position>
456 *******************************************************************************/
458 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
460 constant_classref *cr;
464 /* get stuff from the stack */
466 cr = (constant_classref *) pr->ref;
467 datap = (u1 *) pr->datap;
469 /* get the classinfo */
471 if (!(c = resolve_classref_eager(cr)))
474 PATCH_BACK_ORIGINAL_MCODE;
476 /* patch super class' vftbl */
478 *((ptrint *) datap) = (ptrint) c->vftbl;
485 * These are local overrides for various environment variables in Emacs.
486 * Please do not remove this and leave it at the end of the file, where
487 * Emacs will automagically detect them.
488 * ---------------------------------------------------------------------
491 * indent-tabs-mode: t
495 * vim:noexpandtab:sw=4:ts=4: