LCOV - code coverage report
Current view: top level - vm/jit - patcher-common.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 137 60.6 %
Date: 2015-06-10 18:10:59 Functions: 12 15 80.0 %

          Line data    Source code
       1             : /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             :    Copyright (C) 2008 Theobroma Systems Ltd.
       6             : 
       7             :    This file is part of CACAO.
       8             : 
       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.
      13             : 
      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.
      18             : 
      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
      22             :    02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : 
      27             : #include "config.h"
      28             : 
      29             : #include <cassert>
      30             : #include <stdint.h>
      31             : #include <inttypes.h>
      32             : 
      33             : #include <algorithm>
      34             : #include <functional>
      35             : 
      36             : #include "codegen.hpp"                   /* for PATCHER_NOPS */
      37             : #include "md.hpp"
      38             : #include "trap.hpp"
      39             : 
      40             : #include "native/native.hpp"
      41             : 
      42             : #include "toolbox/list.hpp"
      43             : #include "toolbox/logging.hpp"           /* XXX remove me! */
      44             : 
      45             : #include "vm/breakpoint.hpp"
      46             : #include "vm/exceptions.hpp"
      47             : #include "vm/hook.hpp"
      48             : #include "vm/initialize.hpp"
      49             : #include "vm/options.hpp"
      50             : #include "vm/os.hpp"
      51             : #include "vm/resolve.hpp"
      52             : #include "vm/vm.hpp"
      53             : 
      54             : #include "vm/jit/code.hpp"
      55             : #include "vm/jit/codegen-common.hpp"
      56             : #include "vm/jit/disass.hpp"
      57             : #include "vm/jit/jit.hpp"
      58             : #include "vm/jit/patcher-common.hpp"
      59             : 
      60             : STAT_DECLARE_VAR(int,size_patchref,0)
      61             : 
      62             : /* patcher_function_list *******************************************************
      63             : 
      64             :    This is a list which maps patcher function pointers to the according
      65             :    names of the patcher functions. It is only usefull for debugging
      66             :    purposes.
      67             : 
      68             : *******************************************************************************/
      69             : 
      70             : #if !defined(NDEBUG)
      71             : typedef struct patcher_function_list_t {
      72             :         functionptr patcher;
      73             :         const char* name;
      74             : } patcher_function_list_t;
      75             : 
      76             : static patcher_function_list_t patcher_function_list[] = {
      77             :         { PATCHER_initialize_class,              "initialize_class" },
      78             : #ifdef ENABLE_VERIFIER
      79             :         { PATCHER_resolve_class,                 "resolve_class" },
      80             : #endif /* ENABLE_VERIFIER */
      81             :         { PATCHER_resolve_native_function,       "resolve_native_function" },
      82             :         { PATCHER_invokestatic_special,          "invokestatic_special" },
      83             :         { PATCHER_invokevirtual,                 "invokevirtual" },
      84             :         { PATCHER_invokeinterface,               "invokeinterface" },
      85             :         { PATCHER_breakpoint,                    "breakpoint" },
      86             :         { NULL,                                  "-UNKNOWN PATCHER FUNCTION-" }
      87             : };
      88             : #endif
      89             : 
      90             : 
      91             : /* patcher_list_create *********************************************************
      92             : 
      93             :    Creates an empty patcher list for the given codeinfo.
      94             : 
      95             : *******************************************************************************/
      96             : 
      97      105324 : void patcher_list_create(codeinfo *code)
      98             : {
      99      105324 :         code->patchers = new LockedList<patchref_t>();
     100      105324 : }
     101             : 
     102             : 
     103             : /* patcher_list_reset **********************************************************
     104             : 
     105             :    Resets the patcher list inside a codeinfo. This is usefull when
     106             :    resetting a codeinfo for recompiling.
     107             : 
     108             : *******************************************************************************/
     109             : 
     110          37 : void patcher_list_reset(codeinfo *code)
     111             : {
     112             :         STATISTICS(size_patchref -= sizeof(patchref_t) * code->patchers->size());
     113             : 
     114             :         // Free all elements of the list.
     115          37 :         code->patchers->clear();
     116          37 : }
     117             : 
     118             : /* patcher_list_free ***********************************************************
     119             : 
     120             :    Frees the patcher list and all its entries for the given codeinfo.
     121             : 
     122             : *******************************************************************************/
     123             : 
     124          37 : void patcher_list_free(codeinfo *code)
     125             : {
     126             :         // Free all elements of the list.
     127          37 :         patcher_list_reset(code);
     128             : 
     129             :         // Free the list itself.
     130          37 :         delete code->patchers;
     131          37 : }
     132             : 
     133             : 
     134             : /**
     135             :  * Find an entry inside the patcher list for the given codeinfo by
     136             :  * specifying the program counter of the patcher position.
     137             :  *
     138             :  * NOTE: Caller should hold the patcher list lock or maintain
     139             :  * exclusive access otherwise.
     140             :  *
     141             :  * @param pc Program counter to find.
     142             :  *
     143             :  * @return Pointer to patcher.
     144             :  */
     145             : 
     146             : struct foo : public std::binary_function<patchref_t, void*, bool> {
     147     5755676 :         bool operator() (const patchref_t& pr, const void* pc) const
     148             :         {
     149     5755676 :                 return (pr.mpc == (uintptr_t) pc);
     150             :         }
     151             : };
     152             : 
     153      213670 : static patchref_t* patcher_list_find(codeinfo* code, void* pc)
     154             : {
     155             :         // Search for a patcher with the given PC.
     156      213670 :         List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
     157             : 
     158      213670 :         if (it == code->patchers->end())
     159      142523 :                 return NULL;
     160             : 
     161       71147 :         return &(*it);
     162             : }
     163             : 
     164             : 
     165             : /**
     166             :  * Show the content of the whole patcher reference list for
     167             :  * debugging purposes.
     168             :  *
     169             :  * @param code The codeinfo containing the patcher list.
     170             :  */
     171             : #if !defined(NDEBUG)
     172           0 : void patcher_list_show(codeinfo *code)
     173             : {
     174           0 :         for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
     175           0 :                 patchref_t& pr = *it;
     176             : 
     177             :                 // Lookup name in patcher function list.
     178             :                 patcher_function_list_t* l;
     179           0 :                 for (l = patcher_function_list; l->patcher != NULL; l++)
     180           0 :                         if (l->patcher == pr.patcher)
     181           0 :                                 break;
     182             : 
     183             :                 // Display information about patcher.
     184           0 :                 printf("\tpatcher");
     185           0 :                 printf(" pc:0x%016"PRIxPTR,    pr.mpc);
     186           0 :                 printf(" datap:0x%016"PRIxPTR, pr.datap);
     187           0 :                 printf(" ref:0x%016"PRIxPTR,   (uintptr_t) pr.ref);
     188             : #if PATCHER_CALL_SIZE == 4
     189             :                 printf(" mcode:%08"PRIx32, (uint32_t) pr.mcode);
     190             : #elif PATCHER_CALL_SIZE == 2
     191           0 :                 printf(" mcode:%04"PRIx16, (uint16_t) pr.mcode);
     192             : #else
     193             : # error Unknown PATCHER_CALL_SIZE
     194             : #endif
     195           0 :                 printf(" type:%s\n", l->name);
     196             : 
     197             :                 // Display machine code of patched position.
     198             : #if 0 && defined(ENABLE_DISASSEMBLER)
     199             :                 printf("\t\tcurrent -> ");
     200             :                 disassinstr((uint8_t*) pr.mpc);
     201             :                 printf("\t\tapplied -> ");
     202             :                 disassinstr((uint8_t*) &(pr.mcode));
     203             : #endif
     204             :         }
     205           0 : }
     206             : #endif
     207             : 
     208             : 
     209             : /* patcher_add_patch_ref *******************************************************
     210             : 
     211             :    Appends a new patcher reference to the list of patching positions.
     212             : 
     213             :    Returns a pointer to the newly created patchref_t.
     214             : 
     215             : *******************************************************************************/
     216             : 
     217      142523 : patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
     218             : {
     219      142523 :         codegendata *cd   = jd->cd;
     220      142523 :         codeinfo    *code = jd->code;
     221             : 
     222             : #if defined(ALIGN_PATCHER_TRAP)
     223      142523 :         emit_patcher_alignment(cd);
     224             : #endif
     225             : 
     226      142523 :         int32_t patchmpc = cd->mcodeptr - cd->mcodebase;
     227             : 
     228             : #if !defined(NDEBUG)
     229      142523 :         if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
     230           0 :                 os::abort("patcher_add_patch_ref: different patchers at same position.");
     231             : #endif
     232             : 
     233             : #if defined(USES_PATCHABLE_MEMORY_BARRIER)
     234      142523 :         PATCHER_NOPS;
     235             : #endif
     236             : 
     237             :         // Set patcher information (mpc is resolved later).
     238             :         patchref_t pr;
     239             : 
     240      142523 :         pr.mpc         = patchmpc;
     241      142523 :         pr.datap       = 0;
     242      142523 :         pr.disp        = disp;
     243      142523 :         pr.disp_mb     = 0;
     244      142523 :         pr.patch_align = 0;
     245      142523 :         pr.patcher     = patcher;
     246      142523 :         pr.ref         = ref;
     247      142523 :         pr.mcode       = 0;
     248      142523 :         pr.done        = false;
     249             : 
     250             :         // Store patcher in the list (NOTE: structure is copied).
     251      142523 :         code->patchers->push_back(pr);
     252             : 
     253             :         STATISTICS(size_patchref += sizeof(patchref_t));
     254             : 
     255             : #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__SPARC_64__) || defined(__X86_64__))
     256             : 
     257             :         /* XXX We can remove that when we don't use UD2 anymore on i386
     258             :            and x86_64. */
     259             : 
     260             :         /* On some architectures the patcher stub call instruction might
     261             :            be longer than the actual instruction generated.  On this
     262             :            architectures we store the last patcher call position and after
     263             :            the basic block code generation is completed, we check the
     264             :            range and maybe generate some nop's. */
     265             :         /* The nops are generated in codegen_emit in each codegen */
     266             : 
     267      142523 :         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
     268             : #endif
     269             : 
     270      142523 :         return &code->patchers->back();
     271             : }
     272             : 
     273             : 
     274             : /**
     275             :  * Resolve all patchers in the current JIT run.
     276             :  *
     277             :  * @param jd JIT data-structure
     278             :  */
     279       99456 : void patcher_resolve(jitdata* jd)
     280             : {
     281             :         // Get required compiler data.
     282       99456 :         codeinfo* code = jd->code;
     283             : 
     284      241979 :         for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
     285      142523 :                 patchref_t& pr = *it;
     286             : 
     287      142523 :                 pr.mpc   += (intptr_t) code->entrypoint;
     288      142523 :                 pr.datap  = (intptr_t) (pr.disp + code->entrypoint);
     289             :         }
     290       99456 : }
     291             : 
     292             : 
     293             : /**
     294             :  * Check if the patcher is already patched.  This is done by comparing
     295             :  * the machine instruction.
     296             :  *
     297             :  * @param pr Patcher structure.
     298             :  *
     299             :  * @return true if patched, false otherwise.
     300             :  */
     301           1 : bool patcher_is_patched(patchref_t* pr)
     302             : {
     303             :         // Validate the instruction at the patching position is the same
     304             :         // instruction as the patcher structure contains.
     305           1 :         uint32_t mcode = *((uint32_t*) pr->mpc);
     306             : 
     307             : #if PATCHER_CALL_SIZE == 4
     308             :         if (mcode != pr->mcode) {
     309             : #elif PATCHER_CALL_SIZE == 2
     310           1 :         if ((uint16_t) mcode != (uint16_t) pr->mcode) {
     311             : #else
     312             : #error Unknown PATCHER_CALL_SIZE
     313             : #endif
     314             :                 // The code differs.
     315           0 :                 return false;
     316             :         }
     317             : 
     318           1 :         return true;
     319             : }
     320             : 
     321             : 
     322             : /**
     323             :  *
     324             :  */
     325           1 : bool patcher_is_patched_at(void* pc)
     326             : {
     327           1 :         codeinfo* code = code_find_codeinfo_for_pc(pc);
     328             : 
     329             :         // Get the patcher for the given PC.
     330           1 :         patchref_t* pr = patcher_list_find(code, pc);
     331             : 
     332           1 :         if (pr == NULL) {
     333             :                 // The given PC is not a patcher position.
     334           0 :                 return false;
     335             :         }
     336             : 
     337             :         // Validate the instruction.
     338           1 :         return patcher_is_patched(pr);
     339             : }
     340             : 
     341             : 
     342             : /* patcher_handler *************************************************************
     343             : 
     344             :    Handles the request to patch JIT code at the given patching
     345             :    position. This function is normally called by the signal
     346             :    handler.
     347             : 
     348             :    NOTE: The patcher list lock is used to maintain exclusive
     349             :    access of the patched position (in fact of the whole code).
     350             :    After patching has suceeded, the patcher reference should be
     351             :    removed from the patcher list to avoid double patching.
     352             : 
     353             : *******************************************************************************/
     354             : 
     355             : #if !defined(NDEBUG)
     356             : /* XXX this indent is not thread safe! */
     357             : /* XXX if you want it thread safe, place patcher_depth in threadobject! */
     358             : static int patcher_depth = 0;
     359             : #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
     360             : #endif /* !defined(NDEBUG) */
     361             : 
     362       71146 : bool patcher_handler(u1 *pc)
     363             : {
     364             :         codeinfo      *code;
     365             :         patchref_t    *pr;
     366             :         bool           result;
     367             : #if !defined(NDEBUG)
     368             :         patcher_function_list_t *l;
     369             :         int                      i;
     370             : #endif
     371             : 
     372             :         /* define the patcher function */
     373             : 
     374             :         bool (*patcher_function)(patchref_t *);
     375             : 
     376             :         /* search the codeinfo for the given PC */
     377             : 
     378       71146 :         code = code_find_codeinfo_for_pc(pc);
     379       71146 :         assert(code);
     380             : 
     381             :         // Enter a mutex on the patcher list.
     382       71146 :         code->patchers->lock();
     383             : 
     384             :         /* search the patcher information for the given PC */
     385             : 
     386       71146 :         pr = patcher_list_find(code, pc);
     387             : 
     388       71146 :         if (pr == NULL)
     389           0 :                 os::abort("patcher_handler: Unable to find patcher reference.");
     390             : 
     391       71146 :         if (pr->done) {
     392             : #if !defined(NDEBUG)
     393           5 :                 if (opt_DebugPatcher) {
     394           0 :                         log_println("patcher_handler: double-patching detected!");
     395             :                 }
     396             : #endif
     397           5 :                 code->patchers->unlock();
     398           5 :                 return true;
     399             :         }
     400             : 
     401             : #if !defined(NDEBUG)
     402       71141 :         if (opt_DebugPatcher) {
     403           0 :                 for (l = patcher_function_list; l->patcher != NULL; l++)
     404           0 :                         if (l->patcher == pr->patcher)
     405           0 :                                 break;
     406             : 
     407           0 :                 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
     408           0 :                 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
     409             : 
     410           0 :                 TRACE_PATCHER_INDENT;
     411           0 :                 printf("\tmachine code before = ");
     412             : 
     413             : # if defined(ENABLE_DISASSEMBLER)
     414             :                 disassinstr((u1*) (void*) pr->mpc);
     415             : # else
     416           0 :                 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
     417             : # endif
     418             : 
     419           0 :                 patcher_depth++;
     420           0 :                 assert(patcher_depth > 0);
     421             :         }
     422             : #endif
     423             : 
     424             :         /* cast the passed function to a patcher function */
     425             : 
     426       71141 :         patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
     427             : 
     428             :         /* call the proper patcher function */
     429             : 
     430       71141 :         result = (patcher_function)(pr);
     431             : 
     432             : #if !defined(NDEBUG)
     433       71141 :         if (opt_DebugPatcher) {
     434           0 :                 assert(patcher_depth > 0);
     435           0 :                 patcher_depth--;
     436             : 
     437           0 :                 TRACE_PATCHER_INDENT;
     438           0 :                 printf("\tmachine code after  = ");
     439             : 
     440             : # if defined(ENABLE_DISASSEMBLER)
     441             :                 disassinstr((u1*) (void*) pr->mpc);
     442             : # else
     443           0 :                 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
     444             : # endif
     445             : 
     446           0 :                 if (result == false) {
     447           0 :                         TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
     448             :                 }
     449             :         }
     450             : #endif
     451             : 
     452             :         // Check return value and mangle the pending exception.
     453       71141 :         if (result == false)
     454          13 :                 resolve_handle_pending_exception(true);
     455             : 
     456             :         // XXX This is only preliminary to prevent double-patching.
     457             :         else
     458       71128 :                 pr->done = true;
     459             : 
     460       71141 :         code->patchers->unlock();
     461             : 
     462       71141 :         return result;
     463             : }
     464             : 
     465             : 
     466             : /* patcher_initialize_class ****************************************************
     467             : 
     468             :    Initalizes a given classinfo pointer.
     469             :    This function does not patch any data.
     470             : 
     471             : *******************************************************************************/
     472             : 
     473         723 : bool patcher_initialize_class(patchref_t *pr)
     474             : {
     475             :         classinfo *c;
     476             : 
     477             :         /* get stuff from the patcher reference */
     478             : 
     479         723 :         c = (classinfo *) pr->ref;
     480             : 
     481             :         /* check if the class is initialized */
     482             : 
     483         723 :         if (!(c->state & CLASS_INITIALIZED))
     484         296 :                 if (!initialize_class(c))
     485           0 :                         return false;
     486             : 
     487             :         /* patch back original code */
     488             : 
     489         723 :         patcher_patch_code(pr);
     490             : 
     491         723 :         return true;
     492             : }
     493             : 
     494             : 
     495             : /* patcher_resolve_class *******************************************************
     496             : 
     497             :    Resolves a given unresolved class reference.
     498             :    This function does not patch any data.
     499             : 
     500             : *******************************************************************************/
     501             : 
     502             : #ifdef ENABLE_VERIFIER
     503        2990 : bool patcher_resolve_class(patchref_t *pr)
     504             : {
     505             :         unresolved_class *uc;
     506             : 
     507             :         /* get stuff from the patcher reference */
     508             : 
     509        2990 :         uc = (unresolved_class *) pr->ref;
     510             : 
     511             :         /* resolve the class and check subtype constraints */
     512             : 
     513        2990 :         if (!resolve_class_eager_no_access_check(uc))
     514           3 :                 return false;
     515             : 
     516             :         /* patch back original code */
     517             : 
     518        2987 :         patcher_patch_code(pr);
     519             : 
     520        2987 :         return true;
     521             : }
     522             : #endif /* ENABLE_VERIFIER */
     523             : 
     524             : 
     525             : /* patcher_resolve_native_function *********************************************
     526             : 
     527             :    Resolves the native function for a given methodinfo.
     528             :    This function patches one data segment word.
     529             : 
     530             : *******************************************************************************/
     531             : 
     532           0 : bool patcher_resolve_native_function(patchref_t *pr)
     533             : {
     534             :         methodinfo  *m;
     535             :         uint8_t     *datap;
     536             : 
     537             :         /* get stuff from the patcher reference */
     538             : 
     539           0 :         m     = (methodinfo *) pr->ref;
     540           0 :         datap = (uint8_t *)    pr->datap;
     541             : 
     542             :         /* resolve native function */
     543             : 
     544           0 :         NativeMethods& nm = VM::get_current()->get_nativemethods();
     545           0 :         void* f = nm.resolve_method(m);
     546             : 
     547           0 :         if (f == NULL)
     548           0 :                 return false;
     549             : 
     550             :         /* patch native function pointer */
     551             : 
     552           0 :         *((intptr_t*) datap) = (intptr_t) f;
     553             : 
     554             :         /* synchronize data cache */
     555             : 
     556           0 :         md_dcacheflush(datap, SIZEOF_VOID_P);
     557             : 
     558             :         /* patch back original code */
     559             : 
     560           0 :         patcher_patch_code(pr);
     561             : 
     562           0 :         return true;
     563             : }
     564             : 
     565             : 
     566             : /**
     567             :  * Deals with breakpoint instructions (ICMD_BREAKPOINT) compiled
     568             :  * into a JIT method. This patcher might never patch back the
     569             :  * original machine code because breakpoints are kept active.
     570             :  */
     571           0 : bool patcher_breakpoint(patchref_t *pr)
     572             : {
     573             :         // Get stuff from the patcher reference.
     574           0 :         Breakpoint* breakp = (Breakpoint*) pr->ref;
     575             : 
     576             :         // Hook point when a breakpoint was triggered.
     577           0 :         Hook::breakpoint(breakp);
     578             : 
     579             :         // In case the breakpoint wants to be kept active, we simply
     580             :         // fail to "patch" at this point.
     581           0 :         if (!breakp->is_oneshot)
     582           0 :                 return false;
     583             : 
     584             :         // Patch back original code.
     585           0 :         patcher_patch_code(pr);
     586             : 
     587           0 :         return true;
     588             : }
     589             : 
     590             : 
     591             : /*
     592             :  * These are local overrides for various environment variables in Emacs.
     593             :  * Please do not remove this and leave it at the end of the file, where
     594             :  * Emacs will automagically detect them.
     595             :  * ---------------------------------------------------------------------
     596             :  * Local variables:
     597             :  * mode: c++
     598             :  * indent-tabs-mode: t
     599             :  * c-basic-offset: 4
     600             :  * tab-width: 4
     601             :  * End:
     602             :  * vim:noexpandtab:sw=4:ts=4:
     603             :  */
     604             : 

Generated by: LCOV version 1.11