LCOV - code coverage report
Current view: top level - vm/jit - patcher-common.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 122 63.9 %
Date: 2017-07-14 10:03:36 Functions: 11 14 78.6 %

          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             : #define DEBUG_NAME "Patcher"
      61             : 
      62             : STAT_DECLARE_VAR(int,size_patchref,0)
      63             : 
      64             : /* patcher_list_create *********************************************************
      65             : 
      66             :    Creates an empty patcher list for the given codeinfo.
      67             : 
      68             : *******************************************************************************/
      69             : 
      70      105324 : void patcher_list_create(codeinfo *code)
      71             : {
      72      105324 :         code->patchers = new PatcherListTy();
      73      105323 : }
      74             : 
      75             : 
      76             : /* patcher_list_reset **********************************************************
      77             : 
      78             :    Resets the patcher list inside a codeinfo. This is usefull when
      79             :    resetting a codeinfo for recompiling.
      80             : 
      81             : *******************************************************************************/
      82             : 
      83          37 : void patcher_list_reset(codeinfo *code)
      84             : {
      85             :         STATISTICS(size_patchref -= sizeof(patchref_t) * code->patchers->size());
      86             : 
      87             :         // Free all elements of the list.
      88          37 :         code->patchers->clear();
      89          37 : }
      90             : 
      91             : /* patcher_list_free ***********************************************************
      92             : 
      93             :    Frees the patcher list and all its entries for the given codeinfo.
      94             : 
      95             : *******************************************************************************/
      96             : 
      97          37 : void patcher_list_free(codeinfo *code)
      98             : {
      99             :         // Free all elements of the list.
     100          37 :         patcher_list_reset(code);
     101             : 
     102             :         // Free the list itself.
     103          37 :         delete code->patchers;
     104          37 : }
     105             : 
     106             : 
     107             : namespace {
     108             : /**
     109             :  * Find an entry inside the patcher list for the given codeinfo by
     110             :  * specifying the program counter of the patcher position.
     111             :  *
     112             :  * NOTE: Caller should hold the patcher list lock or maintain
     113             :  * exclusive access otherwise.
     114             :  *
     115             :  * @param pc Program counter to find.
     116             :  *
     117             :  * @return Pointer to patcher.
     118             :  */
     119             : 
     120             : struct find_patcher : public std::binary_function<PatcherPtrTy, void*, bool> {
     121             : 
     122     5755676 :         bool operator() (const PatcherPtrTy& pr,
     123             :                         const void* pc) const {
     124     5755676 :                 return (pr->get_mpc() == (uintptr_t) pc);
     125             :         }
     126             : };
     127             : 
     128             : } // end anonymous namespace
     129             : 
     130      213671 : static PatcherPtrTy* patcher_list_find(codeinfo* code, void* pc)
     131             : {
     132             :         // Search for a patcher with the given PC.
     133             :         PatcherListTy::iterator it = std::find_if(code->patchers->begin(),
     134      213671 :                 code->patchers->end(), std::bind2nd(find_patcher(), pc));
     135             : 
     136      213671 :         if (it == code->patchers->end())
     137      142524 :                 return NULL;
     138             : 
     139       71147 :         return &(*it);
     140             : }
     141             : 
     142             : 
     143             : /**
     144             :  * Show the content of the whole patcher reference list for
     145             :  * debugging purposes.
     146             :  *
     147             :  * @param code The codeinfo containing the patcher list.
     148             :  */
     149             : #if !defined(NDEBUG)
     150           0 : void patcher_list_show(codeinfo *code)
     151             : {
     152           0 :         for (PatcherListTy::iterator i = code->patchers->begin(),
     153           0 :                         e = code->patchers->end(); i != e; ++i) {
     154           0 :                 PatcherPtrTy& pr = (*i);
     155             : 
     156           0 :                 pr->print(cacao::out());
     157           0 :                 cacao::out() << cacao::nl;
     158             : 
     159             :         }
     160           0 : }
     161             : #endif
     162             : 
     163             : 
     164             : /* patcher_add_patch_ref *******************************************************
     165             : 
     166             :    Appends a new patcher reference to the list of patching positions.
     167             : 
     168             :    Returns a pointer to the newly created patchref_t.
     169             : 
     170             : *******************************************************************************/
     171             : 
     172      142524 : patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
     173             : {
     174      142524 :         codegendata *cd   = jd->cd;
     175      142524 :         codeinfo    *code = jd->code;
     176             : 
     177             : #if defined(ALIGN_PATCHER_TRAP)
     178      142524 :         emit_patcher_alignment(cd);
     179             : #endif
     180             : 
     181      142524 :         int32_t patchmpc = cd->mcodeptr - cd->mcodebase;
     182             : 
     183             : #if !defined(NDEBUG)
     184      142524 :         if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
     185           0 :                 os::abort("patcher_add_patch_ref: different patchers at same position.");
     186             : #endif
     187             : 
     188             : #if defined(USES_PATCHABLE_MEMORY_BARRIER)
     189      142524 :         PATCHER_NOPS;
     190             : #endif
     191             : 
     192             :         // Set patcher information (mpc is resolved later).
     193             :         patchref_t pr;
     194             : 
     195      142524 :         pr.mpc         = patchmpc;
     196      142524 :         pr.datap       = 0;
     197      142524 :         pr.disp        = disp;
     198      142524 :         pr.disp_mb     = 0;
     199      142524 :         pr.patch_align = 0;
     200      142524 :         pr.patcher     = patcher;
     201      142524 :         pr.ref         = ref;
     202      142524 :         pr.mcode       = 0;
     203             : 
     204             :         // Store patcher in the list (NOTE: structure is copied).
     205      142524 :         cacao::LegacyPatcher *legacy =  new cacao::LegacyPatcher(jd,pr);
     206      142524 :         PatcherPtrTy ptr(legacy);
     207      142524 :         code->patchers->push_back(ptr);
     208             : 
     209             :         STATISTICS(size_patchref += sizeof(patchref_t));
     210             : 
     211             : #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__SPARC_64__) || defined(__X86_64__))
     212             : 
     213             :         /* XXX We can remove that when we don't use UD2 anymore on i386
     214             :            and x86_64. */
     215             : 
     216             :         /* On some architectures the patcher stub call instruction might
     217             :            be longer than the actual instruction generated.  On this
     218             :            architectures we store the last patcher call position and after
     219             :            the basic block code generation is completed, we check the
     220             :            range and maybe generate some nop's. */
     221             :         /* The nops are generated in codegen_emit in each codegen */
     222             : 
     223      142524 :         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
     224             : #endif
     225             : 
     226             :         //return code->patchers->back()->get();
     227      142524 :         return legacy->get();
     228             : }
     229             : 
     230             : 
     231             : /**
     232             :  * Resolve all patchers in the current JIT run.
     233             :  *
     234             :  * @param jd JIT data-structure
     235             :  */
     236       99456 : void patcher_resolve(codeinfo* code)
     237             : {
     238      341436 :         for (PatcherListTy::iterator i = code->patchers->begin(),
     239       99456 :                         e = code->patchers->end(); i != e; ++i) {
     240      142524 :                 PatcherPtrTy& pr = (*i);
     241             : 
     242      142524 :                 pr->reposition((intptr_t) code->entrypoint);
     243             :                 LOG2("Patcher " << pr->get_name() << " reposition: " << pr->get_mpc() <<  cacao::nl);
     244             :         }
     245       99456 : }
     246             : 
     247             : /**
     248             :  *
     249             :  */
     250           1 : bool patcher_is_patched_at(void* pc)
     251             : {
     252           1 :         codeinfo* code = code_find_codeinfo_for_pc(pc);
     253             : 
     254             :         // Get the patcher for the given PC.
     255           1 :         PatcherPtrTy* pr = patcher_list_find(code, pc);
     256             : 
     257           1 :         if (pr == NULL) {
     258             :                 // The given PC is not a patcher position.
     259           0 :                 return false;
     260             :         }
     261             : 
     262             :         // Validate the instruction.
     263           1 :         return (*pr)->check_is_patched();
     264             : }
     265             : 
     266             : 
     267             : /* patcher_handler *************************************************************
     268             : 
     269             :    Handles the request to patch JIT code at the given patching
     270             :    position. This function is normally called by the signal
     271             :    handler.
     272             : 
     273             :    NOTE: The patcher list lock is used to maintain exclusive
     274             :    access of the patched position (in fact of the whole code).
     275             :    After patching has suceeded, the patcher reference should be
     276             :    removed from the patcher list to avoid double patching.
     277             : 
     278             : *******************************************************************************/
     279             : 
     280             : #if !defined(NDEBUG)
     281             : /* XXX this indent is not thread safe! */
     282             : /* XXX if you want it thread safe, place patcher_depth in threadobject! */
     283             : static int patcher_depth = 0;
     284             : #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
     285             : #endif /* !defined(NDEBUG) */
     286             : 
     287       71146 : bool patcher_handler(u1 *pc)
     288             : {
     289             :         codeinfo      *code;
     290             :         bool           result;
     291             : #if !defined(NDEBUG)
     292             :         int                      i;
     293             : #endif
     294             : 
     295             :         // search the codeinfo for the given PC
     296       71146 :         code = code_find_codeinfo_for_pc(pc);
     297       71146 :         assert(code);
     298             : 
     299             :         // Enter a mutex on the patcher list.
     300       71146 :         code->patchers->lock();
     301             : 
     302             :         /* search the patcher information for the given PC */
     303             : 
     304       71146 :         PatcherPtrTy *pr_p = patcher_list_find(code, pc);
     305             : 
     306       71146 :         if (pr_p == NULL)
     307           0 :                 os::abort("patcher_handler: Unable to find patcher reference.");
     308             : 
     309       71146 :         PatcherPtrTy &pr = *pr_p;
     310             : 
     311       71146 :         if (pr->is_patched()) {
     312             : #if !defined(NDEBUG)
     313           4 :                 if (opt_DebugPatcher) {
     314           0 :                         log_println("patcher_handler: double-patching detected!");
     315             :                 }
     316             : #endif
     317           4 :                 code->patchers->unlock();
     318           4 :                 return true;
     319             :         }
     320             : 
     321             : #if !defined(NDEBUG)
     322       71142 :         if (opt_DebugPatcher) {
     323             : 
     324           0 :                 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->get_mpc());
     325           0 :                 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s\n", pr->get_name());
     326             : 
     327           0 :                 TRACE_PATCHER_INDENT;
     328           0 :                 printf("\tmachine code before = ");
     329             : 
     330             : # if defined(ENABLE_DISASSEMBLER)
     331             :                 disassinstr((u1*) (void*) pr->get_mpc());
     332             : # else
     333           0 :                 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->get_mpc()), (void*) pr->get_mpc());
     334             : # endif
     335             : 
     336           0 :                 patcher_depth++;
     337           0 :                 assert(patcher_depth > 0);
     338             :         }
     339             : #endif
     340             : 
     341             :         /* call the proper patcher function */
     342             : 
     343       71142 :         result = pr->patch();
     344             : 
     345             : #if !defined(NDEBUG)
     346       71142 :         if (opt_DebugPatcher) {
     347           0 :                 assert(patcher_depth > 0);
     348           0 :                 patcher_depth--;
     349             : 
     350           0 :                 TRACE_PATCHER_INDENT;
     351           0 :                 printf("\tmachine code after  = ");
     352             : 
     353             : # if defined(ENABLE_DISASSEMBLER)
     354             :                 disassinstr((u1*) (void*) pr->get_mpc());
     355             : # else
     356           0 :                 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->get_mpc()), (void*) pr->get_mpc());
     357             : # endif
     358             : 
     359           0 :                 if (result == false) {
     360           0 :                         TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
     361             :                 }
     362             :         }
     363             : #endif
     364             : 
     365             :         // Check return value and mangle the pending exception.
     366       71142 :         if (result == false)
     367          13 :                 resolve_handle_pending_exception(true);
     368             : 
     369       71142 :         code->patchers->unlock();
     370             : 
     371       71142 :         return result;
     372             : }
     373             : 
     374             : 
     375             : /* patcher_initialize_class ****************************************************
     376             : 
     377             :    Initalizes a given classinfo pointer.
     378             :    This function does not patch any data.
     379             : 
     380             : *******************************************************************************/
     381             : 
     382         723 : bool patcher_initialize_class(patchref_t *pr)
     383             : {
     384             :         classinfo *c;
     385             : 
     386             :         /* get stuff from the patcher reference */
     387             : 
     388         723 :         c = (classinfo *) pr->ref;
     389             : 
     390             :         /* check if the class is initialized */
     391             : 
     392         723 :         if (!(c->state & CLASS_INITIALIZED))
     393         296 :                 if (!initialize_class(c))
     394           0 :                         return false;
     395             : 
     396             :         /* patch back original code */
     397             : 
     398         723 :         patcher_patch_code(pr);
     399             : 
     400         723 :         return true;
     401             : }
     402             : 
     403             : 
     404             : /* patcher_resolve_class *******************************************************
     405             : 
     406             :    Resolves a given unresolved class reference.
     407             :    This function does not patch any data.
     408             : 
     409             : *******************************************************************************/
     410             : 
     411             : #ifdef ENABLE_VERIFIER
     412        2990 : bool patcher_resolve_class(patchref_t *pr)
     413             : {
     414             :         unresolved_class *uc;
     415             : 
     416             :         /* get stuff from the patcher reference */
     417             : 
     418        2990 :         uc = (unresolved_class *) pr->ref;
     419             : 
     420             :         /* resolve the class and check subtype constraints */
     421             : 
     422        2990 :         if (!resolve_class_eager_no_access_check(uc))
     423           3 :                 return false;
     424             : 
     425             :         /* patch back original code */
     426             : 
     427        2987 :         patcher_patch_code(pr);
     428             : 
     429        2987 :         return true;
     430             : }
     431             : #endif /* ENABLE_VERIFIER */
     432             : 
     433             : 
     434             : /* patcher_resolve_native_function *********************************************
     435             : 
     436             :    Resolves the native function for a given methodinfo.
     437             :    This function patches one data segment word.
     438             : 
     439             : *******************************************************************************/
     440             : 
     441           0 : bool patcher_resolve_native_function(patchref_t *pr)
     442             : {
     443             :         methodinfo  *m;
     444             :         uint8_t     *datap;
     445             : 
     446             :         /* get stuff from the patcher reference */
     447             : 
     448           0 :         m     = (methodinfo *) pr->ref;
     449           0 :         datap = (uint8_t *)    pr->datap;
     450             : 
     451             :         /* resolve native function */
     452             : 
     453           0 :         NativeMethods& nm = VM::get_current()->get_nativemethods();
     454           0 :         void* f = nm.resolve_method(m);
     455             : 
     456           0 :         if (f == NULL)
     457           0 :                 return false;
     458             : 
     459             :         /* patch native function pointer */
     460             : 
     461           0 :         *((intptr_t*) datap) = (intptr_t) f;
     462             : 
     463             :         /* synchronize data cache */
     464             : 
     465           0 :         md_dcacheflush(datap, SIZEOF_VOID_P);
     466             : 
     467             :         /* patch back original code */
     468             : 
     469           0 :         patcher_patch_code(pr);
     470             : 
     471           0 :         return true;
     472             : }
     473             : 
     474             : 
     475             : /**
     476             :  * Deals with breakpoint instructions (ICMD_BREAKPOINT) compiled
     477             :  * into a JIT method. This patcher might never patch back the
     478             :  * original machine code because breakpoints are kept active.
     479             :  */
     480           0 : bool patcher_breakpoint(patchref_t *pr)
     481             : {
     482             :         // Get stuff from the patcher reference.
     483           0 :         Breakpoint* breakp = (Breakpoint*) pr->ref;
     484             : 
     485             :         // Hook point when a breakpoint was triggered.
     486           0 :         Hook::breakpoint(breakp);
     487             : 
     488             :         // In case the breakpoint wants to be kept active, we simply
     489             :         // fail to "patch" at this point.
     490           0 :         if (!breakp->is_oneshot)
     491           0 :                 return false;
     492             : 
     493             :         // Patch back original code.
     494           0 :         patcher_patch_code(pr);
     495             : 
     496           0 :         return true;
     497             : }
     498             : 
     499             : 
     500             : /*
     501             :  * These are local overrides for various environment variables in Emacs.
     502             :  * Please do not remove this and leave it at the end of the file, where
     503             :  * Emacs will automagically detect them.
     504             :  * ---------------------------------------------------------------------
     505             :  * Local variables:
     506             :  * mode: c++
     507             :  * indent-tabs-mode: t
     508             :  * c-basic-offset: 4
     509             :  * tab-width: 4
     510             :  * End:
     511             :  * vim:noexpandtab:sw=4:ts=4:
     512             :  */
     513             : 

Generated by: LCOV version 1.11