1 /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 Copyright (C) 2008 Theobroma Systems Ltd.
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35 #include "codegen.h" /* for PATCHER_NOPS */
39 #include "mm/memory.hpp"
41 #include "native/native.hpp"
43 #include "toolbox/list.hpp"
44 #include "toolbox/logging.hpp" /* XXX remove me! */
46 #include "vm/exceptions.hpp"
47 #include "vm/initialize.hpp"
48 #include "vm/options.h"
49 #include "vm/resolve.hpp"
50 #include "vm/vm.hpp" /* for vm_abort */
52 #include "vm/jit/code.hpp"
53 #include "vm/jit/disass.h"
54 #include "vm/jit/jit.hpp"
55 #include "vm/jit/patcher-common.hpp"
58 /* patcher_function_list *******************************************************
60 This is a list which maps patcher function pointers to the according
61 names of the patcher functions. It is only usefull for debugging
64 *******************************************************************************/
67 typedef struct patcher_function_list_t {
70 } patcher_function_list_t;
72 static patcher_function_list_t patcher_function_list[] = {
73 { PATCHER_initialize_class, "initialize_class" },
74 #ifdef ENABLE_VERIFIER
75 { PATCHER_resolve_class, "resolve_class" },
76 #endif /* ENABLE_VERIFIER */
77 { PATCHER_resolve_native_function, "resolve_native_function" },
78 { PATCHER_invokestatic_special, "invokestatic_special" },
79 { PATCHER_invokevirtual, "invokevirtual" },
80 { PATCHER_invokeinterface, "invokeinterface" },
81 { NULL, "-UNKNOWN PATCHER FUNCTION-" }
86 /* patcher_list_create *********************************************************
88 Creates an empty patcher list for the given codeinfo.
90 *******************************************************************************/
92 void patcher_list_create(codeinfo *code)
94 code->patchers = new LockedList<patchref_t>();
98 /* patcher_list_reset **********************************************************
100 Resets the patcher list inside a codeinfo. This is usefull when
101 resetting a codeinfo for recompiling.
103 *******************************************************************************/
105 void patcher_list_reset(codeinfo *code)
107 #if defined(ENABLE_STATISTICS)
109 size_patchref -= sizeof(patchref_t) * code->patchers->size();
112 // Free all elements of the list.
113 code->patchers->clear();
116 /* patcher_list_free ***********************************************************
118 Frees the patcher list and all its entries for the given codeinfo.
120 *******************************************************************************/
122 void patcher_list_free(codeinfo *code)
124 // Free all elements of the list.
125 patcher_list_reset(code);
127 // Free the list itself.
128 delete code->patchers;
133 * Find an entry inside the patcher list for the given codeinfo by
134 * specifying the program counter of the patcher position.
136 * NOTE: Caller should hold the patcher list lock or maintain
137 * exclusive access otherwise.
139 * @param pc Program counter to find.
141 * @return Pointer to patcher.
144 struct foo : public std::binary_function<patchref_t, void*, bool> {
145 bool operator() (const patchref_t& pr, const void* pc) const
147 return (pr.mpc == (uintptr_t) pc);
151 static patchref_t* patcher_list_find(codeinfo* code, void* pc)
153 // Search for a patcher with the given PC.
154 List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
156 if (it == code->patchers->end())
164 * Show the content of the whole patcher reference list for
165 * debugging purposes.
167 * @param code The codeinfo containing the patcher list.
170 void patcher_list_show(codeinfo *code)
172 for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
173 patchref_t& pr = *it;
175 // Lookup name in patcher function list.
176 patcher_function_list_t* l;
177 for (l = patcher_function_list; l->patcher != NULL; l++)
178 if (l->patcher == pr.patcher)
181 // Display information about patcher.
182 printf("\tpatcher pc:"PRINTF_FORMAT_INTPTR_T, pr.mpc);
183 printf(" datap:"PRINTF_FORMAT_INTPTR_T, pr.datap);
184 printf(" ref:"PRINTF_FORMAT_INTPTR_T, (intptr_t) pr.ref);
185 #if PATCHER_CALL_SIZE == 4
186 printf(" mcode:%08x", (uint32_t) pr.mcode);
187 #elif PATCHER_CALL_SIZE == 2
188 printf(" mcode:%04x", (uint16_t) pr.mcode);
190 # error Unknown PATCHER_CALL_SIZE
192 printf(" type:%s\n", l->name);
194 // Display machine code of patched position.
195 #if 0 && defined(ENABLE_DISASSEMBLER)
196 printf("\t\tcurrent -> ");
197 disassinstr((uint8_t*) pr.mpc);
198 printf("\t\tapplied -> ");
199 disassinstr((uint8_t*) &(pr.mcode));
206 /* patcher_add_patch_ref *******************************************************
208 Appends a new patcher reference to the list of patching positions.
210 *******************************************************************************/
212 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
220 patchmpc = cd->mcodeptr - cd->mcodebase;
222 #if defined(ALIGN_PATCHER_TRAP)
223 emit_patcher_alignment(cd);
224 patchmpc = cd->mcodeptr - cd->mcodebase;
228 if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
229 vm_abort("patcher_add_patch_ref: different patchers at same position.");
232 // Set patcher information (mpc is resolved later).
238 pr.patcher = patcher;
243 // Store patcher in the list (NOTE: structure is copied).
244 code->patchers->push_back(pr);
246 #if defined(ENABLE_STATISTICS)
248 size_patchref += sizeof(patchref_t);
251 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
253 /* XXX We can remove that when we don't use UD2 anymore on i386
256 /* On some architectures the patcher stub call instruction might
257 be longer than the actual instruction generated. On this
258 architectures we store the last patcher call position and after
259 the basic block code generation is completed, we check the
260 range and maybe generate some nop's. */
261 /* The nops are generated in codegen_emit in each codegen */
263 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
269 * Resolve all patchers in the current JIT run.
271 * @param jd JIT data-structure
273 void patcher_resolve(jitdata* jd)
275 // Get required compiler data.
276 codeinfo* code = jd->code;
278 for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
279 patchref_t& pr = *it;
281 pr.mpc += (intptr_t) code->entrypoint;
282 pr.datap = (intptr_t) (pr.disp + code->entrypoint);
288 * Check if the patcher is already patched. This is done by comparing
289 * the machine instruction.
291 * @param pr Patcher structure.
293 * @return true if patched, false otherwise.
295 bool patcher_is_patched(patchref_t* pr)
297 // Validate the instruction at the patching position is the same
298 // instruction as the patcher structure contains.
299 uint32_t mcode = *((uint32_t*) pr->mpc);
301 #if PATCHER_CALL_SIZE == 4
302 if (mcode != pr->mcode) {
303 #elif PATCHER_CALL_SIZE == 2
304 if ((uint16_t) mcode != (uint16_t) pr->mcode) {
306 #error Unknown PATCHER_CALL_SIZE
319 bool patcher_is_patched_at(void* pc)
321 codeinfo* code = code_find_codeinfo_for_pc(pc);
323 // Get the patcher for the given PC.
324 patchref_t* pr = patcher_list_find(code, pc);
327 // The given PC is not a patcher position.
331 // Validate the instruction.
332 return patcher_is_patched(pr);
336 /* patcher_handler *************************************************************
338 Handles the request to patch JIT code at the given patching
339 position. This function is normally called by the signal
342 NOTE: The patcher list lock is used to maintain exclusive
343 access of the patched position (in fact of the whole code).
344 After patching has suceeded, the patcher reference should be
345 removed from the patcher list to avoid double patching.
347 *******************************************************************************/
350 /* XXX this indent is not thread safe! */
351 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
352 static int patcher_depth = 0;
353 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
354 #endif /* !defined(NDEBUG) */
356 java_handle_t *patcher_handler(u1 *pc)
362 patcher_function_list_t *l;
366 /* define the patcher function */
368 bool (*patcher_function)(patchref_t *);
370 /* search the codeinfo for the given PC */
372 code = code_find_codeinfo_for_pc(pc);
375 // Enter a mutex on the patcher list.
376 code->patchers->lock();
378 /* search the patcher information for the given PC */
380 pr = patcher_list_find(code, pc);
383 vm_abort("patcher_handler: Unable to find patcher reference.");
387 if (opt_DebugPatcher) {
388 log_println("patcher_handler: double-patching detected!");
391 code->patchers->unlock();
396 if (opt_DebugPatcher) {
397 for (l = patcher_function_list; l->patcher != NULL; l++)
398 if (l->patcher == pr->patcher)
401 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
402 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
404 TRACE_PATCHER_INDENT;
405 printf("\tmachine code before = ");
407 # if defined(ENABLE_DISASSEMBLER)
408 disassinstr((u1*) (void*) pr->mpc);
410 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
414 assert(patcher_depth > 0);
418 /* cast the passed function to a patcher function */
420 patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
422 /* call the proper patcher function */
424 result = (patcher_function)(pr);
427 if (opt_DebugPatcher) {
428 assert(patcher_depth > 0);
431 TRACE_PATCHER_INDENT;
432 printf("\tmachine code after = ");
434 # if defined(ENABLE_DISASSEMBLER)
435 disassinstr((u1*) (void*) pr->mpc);
437 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
440 if (result == false) {
441 TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
446 // Check for return value and exit accordingly.
447 if (result == false) {
448 // Mangle the pending exception.
449 resolve_handle_pending_exception(true);
451 // Get the exception and return it.
452 java_handle_t* e = exceptions_get_and_clear_exception();
454 code->patchers->unlock();
459 pr->done = true; /* XXX this is only preliminary to prevent double-patching */
461 code->patchers->unlock();
467 /* patcher_initialize_class ****************************************************
469 Initalizes a given classinfo pointer.
470 This function does not patch any data.
472 *******************************************************************************/
474 bool patcher_initialize_class(patchref_t *pr)
478 /* get stuff from the patcher reference */
480 c = (classinfo *) pr->ref;
482 /* check if the class is initialized */
484 if (!(c->state & CLASS_INITIALIZED))
485 if (!initialize_class(c))
488 /* patch back original code */
490 patcher_patch_code(pr);
496 /* patcher_resolve_class *******************************************************
498 Resolves a given unresolved class reference.
499 This function does not patch any data.
501 *******************************************************************************/
503 #ifdef ENABLE_VERIFIER
504 bool patcher_resolve_class(patchref_t *pr)
506 unresolved_class *uc;
508 /* get stuff from the patcher reference */
510 uc = (unresolved_class *) pr->ref;
512 /* resolve the class and check subtype constraints */
514 if (!resolve_class_eager_no_access_check(uc))
517 /* patch back original code */
519 patcher_patch_code(pr);
523 #endif /* ENABLE_VERIFIER */
526 /* patcher_resolve_native_function *********************************************
528 Resolves the native function for a given methodinfo.
529 This function patches one data segment word.
531 *******************************************************************************/
533 bool patcher_resolve_native_function(patchref_t *pr)
538 /* get stuff from the patcher reference */
540 m = (methodinfo *) pr->ref;
541 datap = (uint8_t *) pr->datap;
543 /* resolve native function */
545 NativeMethods& nm = VM::get_current()->get_nativemethods();
546 void* f = nm.resolve_method(m);
551 /* patch native function pointer */
553 *((intptr_t*) datap) = (intptr_t) f;
555 /* synchronize data cache */
557 md_dcacheflush(datap, SIZEOF_VOID_P);
559 /* patch back original code */
561 patcher_patch_code(pr);
568 * These are local overrides for various environment variables in Emacs.
569 * Please do not remove this and leave it at the end of the file, where
570 * Emacs will automagically detect them.
571 * ---------------------------------------------------------------------
574 * indent-tabs-mode: t
578 * vim:noexpandtab:sw=4:ts=4: