1 /* src/vm/jit/patcher-common.c - architecture independent code patching stuff
3 Copyright (C) 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
33 #include "codegen.h" /* for PATCHER_NOPS */
35 #include "mm/memory.h"
37 #include "native/native.h"
39 #include "threads/lock-common.h"
41 #include "toolbox/list.h"
42 #include "toolbox/logging.h" /* XXX remove me! */
44 #include "vm/exceptions.h"
45 #include "vm/initialize.h"
46 #include "vm/resolve.h"
47 #include "vm/vm.h" /* for vm_abort */
49 #include "vm/jit/code.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/md.h"
52 #include "vm/jit/patcher-common.h"
54 #include "vmcore/options.h"
57 /* patcher_function_list *******************************************************
59 This is a list which maps patcher function pointers to the according
60 names of the patcher functions. It is only usefull for debugging
63 *******************************************************************************/
66 typedef struct patcher_function_list_t {
69 } patcher_function_list_t;
71 static patcher_function_list_t patcher_function_list[] = {
72 { PATCHER_initialize_class, "initialize_class" },
73 { PATCHER_resolve_class, "resolve_class" },
74 { PATCHER_resolve_native_function, "resolve_native_function" },
75 { PATCHER_invokestatic_special, "invokestatic_special" },
76 { PATCHER_invokevirtual, "invokevirtual" },
77 { PATCHER_invokeinterface, "invokeinterface" },
78 { NULL, "-UNKNOWN PATCHER FUNCTION-" }
83 /* patcher_list_create *********************************************************
85 Creates an empty patcher list for the given codeinfo.
87 *******************************************************************************/
89 void patcher_list_create(codeinfo *code)
91 code->patchers = list_create(OFFSET(patchref_t, linkage));
95 /* patcher_list_reset **********************************************************
97 Resets the patcher list inside a codeinfo. This is usefull when
98 resetting a codeinfo for recompiling.
100 *******************************************************************************/
102 void patcher_list_reset(codeinfo *code)
106 /* free all elements of the list */
108 while((pr = list_first(code->patchers)) != NULL) {
109 list_remove(code->patchers, pr);
111 FREE(pr, patchref_t);
113 #if defined(ENABLE_STATISTICS)
115 size_patchref -= sizeof(patchref_t);
120 /* patcher_list_free ***********************************************************
122 Frees the patcher list and all its entries for the given codeinfo.
124 *******************************************************************************/
126 void patcher_list_free(codeinfo *code)
128 /* free all elements of the list */
130 patcher_list_reset(code);
132 /* free the list itself */
134 FREE(code->patchers, list_t);
138 /* patcher_list_find ***********************************************************
140 Find an entry inside the patcher list for the given codeinfo
141 by specifying the program counter of the patcher position.
143 NOTE: Caller should hold the patcher list lock or maintain
144 exclusive access otherwise.
146 *******************************************************************************/
148 static patchref_t *patcher_list_find(codeinfo *code, u1 *pc)
152 /* walk through all patcher references for the given codeinfo */
154 pr = list_first_unsynced(code->patchers);
157 /*#define TRACE_PATCHER_FIND*/
158 #ifdef TRACE_PATCHER_FIND
159 log_println("patcher_list_find: %p == %p", pr->mpc, pc);
162 if (pr->mpc == (ptrint) pc)
165 pr = list_next_unsynced(code->patchers, pr);
172 /* patcher_add_patch_ref *******************************************************
174 Appends a new patcher reference to the list of patching positions.
176 *******************************************************************************/
178 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
188 patchmpc = cd->mcodeptr - cd->mcodebase;
191 if (patcher_list_find(code, (u1 *) (intptr_t) patchmpc) != NULL)
192 vm_abort("patcher_add_patch_ref: different patchers at same position.");
195 /* allocate patchref on heap (at least freed together with codeinfo) */
197 pr = NEW(patchref_t);
198 list_add_first_unsynced(code->patchers, pr);
200 #if defined(ENABLE_STATISTICS)
202 size_patchref += sizeof(patchref_t);
205 /* set patcher information (mpc is resolved later) */
209 pr->patcher = patcher;
214 /* Generate NOPs for opt_shownops. */
219 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
221 /* XXX We can remove that when we don't use UD2 anymore on i386
224 /* On some architectures the patcher stub call instruction might
225 be longer than the actual instruction generated. On this
226 architectures we store the last patcher call position and after
227 the basic block code generation is completed, we check the
228 range and maybe generate some nop's. */
229 /* The nops are generated in codegen_emit in each codegen */
231 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
236 /* patcher_handler *************************************************************
238 Handles the request to patch JIT code at the given patching
239 position. This function is normally called by the signal
242 NOTE: The patcher list lock is used to maintain exclusive
243 access of the patched position (in fact of the whole code).
244 After patching has suceeded, the patcher reference should be
245 removed from the patcher list to avoid double patching.
247 *******************************************************************************/
250 /* XXX this indent is not thread safe! */
251 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
252 static int patcher_depth = 0;
253 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
254 #endif /* !defined(NDEBUG) */
256 java_handle_t *patcher_handler(u1 *pc)
263 patcher_function_list_t *l;
267 /* define the patcher function */
269 bool (*patcher_function)(patchref_t *);
271 /* search the codeinfo for the given PC */
273 code = code_find_codeinfo_for_pc(pc);
276 /* enter a monitor on the patcher list */
278 LOCK_MONITOR_ENTER(code->patchers);
280 /* search the patcher information for the given PC */
282 pr = patcher_list_find(code, pc);
285 vm_abort("patcher_handler: Unable to find patcher reference.");
288 log_println("patcher_handler: double-patching detected!");
289 LOCK_MONITOR_EXIT(code->patchers);
294 if (opt_DebugPatcher) {
295 for (l = patcher_function_list; l->patcher != NULL; l++)
296 if (l->patcher == pr->patcher)
299 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
300 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) pr->patcher);
301 TRACE_PATCHER_INDENT; printf("\tmcodes before = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
303 assert(patcher_depth > 0);
307 /* cast the passed function to a patcher function */
309 patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
311 /* call the proper patcher function */
313 result = (patcher_function)(pr);
316 if (opt_DebugPatcher) {
317 assert(patcher_depth > 0);
319 TRACE_PATCHER_INDENT; printf("\tmcodes after = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
320 if (result == false) {
321 TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
326 /* check for return value and exit accordingly */
328 if (result == false) {
329 e = exceptions_get_and_clear_exception();
331 LOCK_MONITOR_EXIT(code->patchers);
336 pr->done = true; /* XXX this is only preliminary to prevent double-patching */
338 LOCK_MONITOR_EXIT(code->patchers);
344 /* patcher_initialize_class ****************************************************
346 Initalizes a given classinfo pointer.
347 This function does not patch any data.
349 *******************************************************************************/
351 bool patcher_initialize_class(patchref_t *pr)
355 /* get stuff from the patcher reference */
357 c = (classinfo *) pr->ref;
359 /* check if the class is initialized */
361 if (!(c->state & CLASS_INITIALIZED))
362 if (!initialize_class(c))
365 /* patch back original code */
367 patcher_patch_code(pr);
373 /* patcher_resolve_class *******************************************************
375 Resolves a given unresolved class reference.
376 This function does not patch any data.
378 *******************************************************************************/
380 #ifdef ENABLE_VERIFIER
381 bool patcher_resolve_class(patchref_t *pr)
383 unresolved_class *uc;
385 /* get stuff from the patcher reference */
387 uc = (unresolved_class *) pr->ref;
389 /* resolve the class and check subtype constraints */
391 if (!resolve_class_eager_no_access_check(uc))
394 /* patch back original code */
396 patcher_patch_code(pr);
400 #endif /* ENABLE_VERIFIER */
403 /* patcher_resolve_native_function *********************************************
405 Resolves the native function for a given methodinfo.
406 This function patches one data segment word.
408 *******************************************************************************/
410 bool patcher_resolve_native_function(patchref_t *pr)
416 /* get stuff from the patcher reference */
418 m = (methodinfo *) pr->ref;
419 datap = (uint8_t *) pr->datap;
421 /* resolve native function */
423 if (!(f = native_resolve_function(m)))
426 /* patch native function pointer */
428 *((intptr_t *) datap) = (intptr_t) f;
430 /* synchronize data cache */
432 md_dcacheflush(datap, SIZEOF_VOID_P);
434 /* patch back original code */
436 patcher_patch_code(pr);
443 * These are local overrides for various environment variables in Emacs.
444 * Please do not remove this and leave it at the end of the file, where
445 * Emacs will automagically detect them.
446 * ---------------------------------------------------------------------
449 * indent-tabs-mode: t
453 * vim:noexpandtab:sw=4:ts=4: