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