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 7483 2007-03-08 13:17:40Z 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.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
54 #define gen_resolveload(inst,offset) \
55 assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
56 assert(!((inst) & 0x0fff)); \
58 (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
59 /*(inst) &= ~(1 << 23);*/ \
61 (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
62 /*(inst) |= (1 << 23);*/ \
66 /* patcher_wrapper *************************************************************
68 Wrapper for all patchers. It also creates the stackframe info
71 If the return value of the patcher function is false, it gets the
72 exception object, clears the exception pointer and returns the
75 *******************************************************************************/
77 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
87 /* define the patcher function */
89 bool (*patcher_function)(u1 *);
93 /* get stuff from the stack */
95 xpc = (u1 *) *((ptrint *) (sp + 4 * 4));
96 o = (java_objectheader *) *((ptrint *) (sp + 3 * 4));
97 f = (functionptr) *((ptrint *) (sp + 0 * 4));
99 /* calculate and set the new return address */
103 *((ptrint *) (sp + 4 * 4)) = (ptrint) xpc;
105 /* store PV into the patcher function position */
107 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
109 /* cast the passed function to a patcher function */
111 patcher_function = (bool (*)(u1 *)) (ptrint) f;
113 /* enter a monitor on the patching position */
115 PATCHER_MONITORENTER;
117 /* create the stackframeinfo */
119 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, xpc);
121 /* call the proper patcher function */
123 result = (patcher_function)(sp);
125 /* remove the stackframeinfo */
127 stacktrace_remove_stackframeinfo(&sfi);
129 /* check for an error, get the exception and return it */
131 if (result == false) {
132 e = exceptions_get_and_clear_exception();
139 /* patch back original code */
141 mcode = *((u4 *) (sp + 2 * 4));
143 *((u4 *) xpc) = mcode;
145 /* synchronize instruction cache */
147 md_icacheflush(xpc, 1 * 4);
149 PATCHER_MARK_PATCHED_MONITOREXIT;
155 /* patcher_get_putstatic *******************************************************
159 <patched call position>
160 e51c103c ldr r1, [ip, #-60]
162 *******************************************************************************/
164 bool patcher_get_putstatic(u1 *sp)
167 unresolved_field *uf;
171 /* get stuff from the stack */
173 disp = *((s4 *) (sp + 5 * 4));
174 uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
175 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
177 /* get the fieldinfo */
179 if (!(fi = resolve_field_eager(uf)))
182 /* check if the field's class is initialized */
184 if (!(fi->class->state & CLASS_INITIALIZED))
185 if (!initialize_class(fi->class))
188 /* patch the field value's address */
190 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
196 /* patcher_get_putfield ********************************************************
200 <patched call position>
201 e58a8000 str r8, [sl, #__]
203 *******************************************************************************/
205 bool patcher_get_putfield(u1 *sp)
209 unresolved_field *uf;
213 /* get stuff from the stack */
214 ra = (u1*) *((ptrint *) (sp + 4 * 4));
215 mcode = *((u4 *) (sp + 2 * 4));
216 uf = (unresolved_field*) *((ptrint *) (sp + 1 * 4));
217 pv = (u1*) *((ptrint *) (sp + 0 * 4));
219 /* get the fieldinfo */
221 if (!(fi = resolve_field_eager(uf)))
224 /* if we show disassembly, we have to skip the nop */
226 if (opt_showdisassemble) {
229 /* patch the field's offset into the instruction */
234 #if defined(ENABLE_SOFTFLOAT)
237 assert(fi->offset <= 0x0fff);
238 *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
242 #if defined(ENABLE_SOFTFLOAT)
245 assert((fi->offset + 4) <= 0x0fff);
246 *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
247 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
250 #if !defined(ENABLE_SOFTFLOAT)
253 assert(fi->offset <= 0x03ff);
254 *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
260 /* patch the field's offset into the instruction stored on the
261 stack and the next instruction in the code */
266 #if defined(ENABLE_SOFTFLOAT)
269 assert(fi->offset <= 0x0fff);
270 *((u4 *) (sp + 2 * 4)) |= (fi->offset & 0x0fff);
274 #if defined(ENABLE_SOFTFLOAT)
277 assert((fi->offset + 4) <= 0x0fff);
278 *((u4 *) (sp + 2 * 4)) |= ((fi->offset + 0) & 0x0fff);
279 *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
282 #if !defined(ENABLE_SOFTFLOAT)
285 assert(fi->offset <= 0x03ff);
286 *((u4 *) (sp + 2 * 4)) |= ((fi->offset >> 2) & 0x00ff);
292 /* synchronize instruction cache */
294 md_icacheflush(ra, 2 * 4);
300 /* patcher_aconst **************************************************************
304 <patched call postition>
305 e51cc030 ldr r0, [ip, #-48]
307 *******************************************************************************/
309 bool patcher_aconst(u1 *sp)
312 constant_classref *cr;
316 /* get stuff from the stack */
318 disp = *((s4 *) (sp + 5 * 4));
319 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
320 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
322 /* get the classinfo */
324 if (!(c = resolve_classref_eager(cr)))
327 /* patch the classinfo pointer */
329 *((ptrint *) (pv + disp)) = (ptrint) c;
335 /* patcher_builtin_multianewarray **********************************************
339 <patched call position>
340 e3a00002 mov r0, #2 ; 0x2
341 e51c1064 ldr r1, [ip, #-100]
344 e51cf068 ldr pc, [ip, #-104]
346 *******************************************************************************/
348 bool patcher_builtin_multianewarray(u1 *sp)
351 constant_classref *cr;
355 /* get stuff from the stack */
357 disp = *((s4 *) (sp + 5 * 4));
358 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
359 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
361 /* get the classinfo */
363 if (!(c = resolve_classref_eager(cr)))
366 /* patch the classinfo pointer */
368 *((ptrint *) (pv + disp)) = (ptrint) c;
374 /* patcher_builtin_arraycheckcast **********************************************
378 <patched call position>
379 e51c1120 ldr r1, [ip, #-288]
381 e51cf124 ldr pc, [ip, #-292]
383 *******************************************************************************/
385 bool patcher_builtin_arraycheckcast(u1 *sp)
388 constant_classref *cr;
392 /* get stuff from the stack */
394 disp = *((s4 *) (sp + 5 * 4));
395 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
396 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
398 /* get the classinfo */
400 if (!(c = resolve_classref_eager(cr)))
403 /* patch the classinfo pointer */
405 *((ptrint *) (pv + disp)) = (ptrint) c;
411 /* patcher_invokestatic_special ************************************************
415 <patched call position>
416 e51cc02c ldr ip, [ip, #-44]
420 ******************************************************************************/
422 bool patcher_invokestatic_special(u1 *sp)
425 unresolved_method *um;
429 /* get stuff from the stack */
431 disp = *((s4 *) (sp + 5 * 4));
432 um = (unresolved_method*) *((ptrint *) (sp + 1 * 4));
433 pv = (u1*) *((ptrint *) (sp + 0 * 4));
435 /* get the methodinfo */
437 if (!(m = resolve_method_eager(um)))
440 /* patch stubroutine */
442 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
448 /* patcher_invokevirtual *******************************************************
452 <patched call position>
453 e590b000 ldr fp, [r0]
454 e59bc000 ldr ip, [fp, #__]
458 *******************************************************************************/
460 bool patcher_invokevirtual(u1 *sp)
463 unresolved_method *um;
466 /* get stuff from the stack */
468 ra = (u1 *) *((ptrint *) (sp + 4 * 4));
469 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
471 /* get the methodinfo */
473 if (!(m = resolve_method_eager(um)))
476 /* if we show disassembly, we have to skip the nop */
478 if (opt_showdisassemble)
481 /* patch vftbl index */
483 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
485 /* synchronize instruction cache */
487 md_icacheflush(ra + 1 * 4, 1 * 4);
493 /* patcher_invokeinterface *****************************************************
497 <patched call position>
498 e590b000 ldr fp, [r0]
499 e59bb000 ldr fp, [fp, #__]
500 e59bc000 ldr ip, [fp, #__]
505 *******************************************************************************/
507 bool patcher_invokeinterface(u1 *sp)
510 unresolved_method *um;
513 /* get stuff from the stack */
515 ra = (u1 *) *((ptrint *) (sp + 4 * 4));
516 um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
518 /* get the methodinfo */
520 if (!(m = resolve_method_eager(um)))
523 /* if we show disassembly, we have to skip the nop */
525 if (opt_showdisassemble)
528 /* patch interfacetable index */
530 gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
532 /* patch method offset */
534 gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
536 /* synchronize instruction cache */
538 md_icacheflush(ra + 1 * 4, 2 * 4);
544 /* patcher_checkcast_instanceof_flags ******************************************
548 <patched call position>
550 *******************************************************************************/
552 bool patcher_checkcast_instanceof_flags(u1 *sp)
555 constant_classref *cr;
559 /* get stuff from the stack */
561 disp = *((s4 *) (sp + 5 * 4));
562 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
563 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
565 /* get the classinfo */
567 if (!(c = resolve_classref_eager(cr)))
570 /* patch class flags */
572 *((s4 *) (pv + disp)) = (s4) c->flags;
578 /* patcher_checkcast_instanceof_interface **************************************
582 <patched call position>
583 e59ab000 ldr fp, [sl]
584 e59b9010 ldr r9, [fp, #16]
585 e3590000 cmp r9, #0 ; 0x0
586 da000000 ble 0x000000
587 e59b9000 ldr r9, [fp, #__]
589 0a000000 beq 0x000000
591 *******************************************************************************/
593 bool patcher_checkcast_instanceof_interface(u1 *sp)
596 constant_classref *cr;
599 /* get stuff from the stack */
601 ra = (u1 *) *((ptrint *) (sp + 4 * 4));
602 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
604 /* get the classinfo */
606 if (!(c = resolve_classref_eager(cr)))
609 /* if we show disassembly, we have to skip the nop */
611 if (opt_showdisassemble)
614 /* patch super class index */
616 assert(*((s4 *) (ra + 2 * 4)) == 0xe3590000);
617 assert(c->index <= 0xff);
619 *((s4 *) (ra + 2 * 4)) |= (s4) (c->index & 0x000000ff);
621 /* patch super class vftbl index */
623 gen_resolveload(*((s4 *) (ra + 4 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * c->index));
625 /* synchronize instruction cache */
627 md_icacheflush(ra + 2 * 4, 3 * 4);
633 /* patcher_checkcast_instanceof_class ******************************************
637 <patched call position>
639 *******************************************************************************/
641 bool patcher_checkcast_instanceof_class(u1 *sp)
644 constant_classref *cr;
648 /* get stuff from the stack */
650 disp = *((s4 *) (sp + 5 * 4));
651 cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
652 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
654 /* get the classinfo */
656 if (!(c = resolve_classref_eager(cr)))
659 /* patch super class' vftbl */
661 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
667 /* patcher_clinit **************************************************************
671 *******************************************************************************/
673 bool patcher_clinit(u1 *sp)
677 /* get stuff from the stack */
679 c = (classinfo *) *((ptrint *) (sp + 1 * 4));
681 /* check if the class is initialized */
683 if (!(c->state & CLASS_INITIALIZED))
684 if (!initialize_class(c))
691 /* patcher_athrow_areturn ******************************************************
695 <patched call position>
697 *******************************************************************************/
699 #ifdef ENABLE_VERIFIER
700 bool patcher_athrow_areturn(u1 *sp)
702 unresolved_class *uc;
704 /* get stuff from the stack */
706 uc = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
708 /* resolve the class and check subtype constraints */
710 if (!resolve_class_eager_no_access_check(uc))
715 #endif /* ENABLE_VERIFIER */
718 /* patcher_resolve_native ******************************************************
722 *******************************************************************************/
724 #if !defined(WITH_STATIC_CLASSPATH)
725 bool patcher_resolve_native(u1 *sp)
732 /* get stuff from the stack */
734 disp = *((s4 *) (sp + 5 * 4));
735 m = (methodinfo *) *((ptrint *) (sp + 1 * 4));
736 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
738 /* resolve native function */
740 if (!(f = native_resolve_function(m)))
743 /* patch native function pointer */
745 *((ptrint *) (pv + disp)) = (ptrint) f;
749 #endif /* !defined(WITH_STATIC_CLASSPATH) */
753 * These are local overrides for various environment variables in Emacs.
754 * Please do not remove this and leave it at the end of the file, where
755 * Emacs will automagically detect them.
756 * ---------------------------------------------------------------------
759 * indent-tabs-mode: t
763 * vim:noexpandtab:sw=4:ts=4: