CACAO
patcher.cpp
Go to the documentation of this file.
1 /* src/vm/jit/arm/patcher.cpp - ARM code patching functions
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 
32 #include "vm/types.hpp"
33 
34 #include "vm/jit/arm/md.hpp"
35 
36 #include "mm/memory.hpp"
37 
38 #include "native/native.hpp"
39 
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/field.hpp"
43 #include "vm/initialize.hpp"
44 #include "vm/options.hpp"
45 #include "vm/references.hpp"
46 #include "vm/resolve.hpp"
47 
48 #include "vm/jit/asmpart.hpp"
50 
51 
52 /* patcher_patch_code **********************************************************
53 
54  Just patches back the original machine code.
55 
56 *******************************************************************************/
57 
59 {
60  *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
61  md_icacheflush((void*) pr->mpc, 1 * 4);
62 }
63 
64 
65 /**
66  * Check if the trap instruction at the given PC is valid.
67  *
68  * @param pc Program counter.
69  *
70  * @return true if valid, false otherwise.
71  */
73 {
74  uint32_t mcode = *((uint32_t*) pc);
75 
76  // Check for the undefined instruction we use.
77  if ((mcode & 0x0ff000f0) != 0x07f000f0) {
78  return false;
79  }
80 
81  return true;
82 }
83 
84 
85 /* patcher_get_putstatic *******************************************************
86 
87  Machine code:
88 
89  <patched call position>
90  e51c103c ldr r1, [ip, #-60]
91 
92 *******************************************************************************/
93 
95 {
97  uintptr_t* datap = (uintptr_t*) pr->datap;
98 
99  // Resolve the field.
100  fieldinfo* fi = resolve_field_eager(uf);
101 
102  if (fi == NULL)
103  return false;
104 
105  // Check if the field's class is initialized.
106  if (!(fi->clazz->state & CLASS_INITIALIZED))
107  if (!initialize_class(fi->clazz))
108  return false;
109 
110  // Patch the field value's address.
111  *datap = (uintptr_t) fi->value;
112 
113  // Patch back the original code.
114  patcher_patch_code(pr);
115 
116  return true;
117 }
118 
119 
120 /* patcher_get_putfield ********************************************************
121 
122  Machine code:
123 
124  <patched call position>
125  e58a8000 str r8, [sl, #__]
126 
127 *******************************************************************************/
128 
130 {
131  uint32_t* pc = (uint32_t*) pr->mpc;
133 
134  // Resolve the field.
135  fieldinfo* fi = resolve_field_eager(uf);
136 
137  if (fi == NULL)
138  return false;
139 
140  // Patch the field's offset into the instruction.
141 
142  switch(fi->type) {
143  case TYPE_ADR:
144  case TYPE_INT:
145 #if defined(ENABLE_SOFTFLOAT)
146  case TYPE_FLT:
147 #endif
148  assert(fi->offset <= 0x0fff);
149  pr->mcode |= (fi->offset & 0x0fff);
150  break;
151 
152  case TYPE_LNG:
153 #if defined(ENABLE_SOFTFLOAT)
154  case TYPE_DBL:
155 #endif
156  assert((fi->offset + 4) <= 0x0fff);
157  pr->mcode |= ((fi->offset + 0) & 0x0fff);
158  pc[1] &= 0xfffff000;
159  pc[1] |= ((fi->offset + 4) & 0x0fff);
160  break;
161 
162 #if !defined(ENABLE_SOFTFLOAT)
163  case TYPE_FLT:
164  case TYPE_DBL:
165  assert(fi->offset <= 0x03ff);
166  pr->mcode |= ((fi->offset >> 2) & 0x00ff);
167  break;
168 #endif
169  }
170 
171  // Synchronize instruction cache.
172  md_icacheflush(pc, 2 * 4);
173 
174  // Patch back the original code.
175  patcher_patch_code(pr);
176 
177  return true;
178 }
179 
180 
181 /* patcher_resolve_classref_to_classinfo ***************************************
182 
183  ACONST - Machine code:
184 
185  <patched call postition>
186  e51cc030 ldr r0, [ip, #-48]
187 
188  MULTIANEWARRAY - Machine code:
189 
190  <patched call position>
191  e3a00002 mov r0, #2 ; 0x2
192  e51c1064 ldr r1, [ip, #-100]
193  e1a0200d mov r2, sp
194  e1a0e00f mov lr, pc
195  e51cf068 ldr pc, [ip, #-104]
196 
197  ARRAYCHECKCAST - Machine code:
198 
199  <patched call position>
200  e51c1120 ldr r1, [ip, #-288]
201  e1a0e00f mov lr, pc
202  e51cf124 ldr pc, [ip, #-292]
203 
204 *******************************************************************************/
205 
207 {
209  uintptr_t* datap = (uintptr_t*) pr->datap;
210 
211  // Resolve the class.
213 
214  if (c == NULL)
215  return false;
216 
217  // Patch the classinfo pointer.
218  *datap = (uintptr_t) c;
219 
220  // Patch back the original code.
221  patcher_patch_code(pr);
222 
223  return true;
224 }
225 
226 
227 /* patcher_invokestatic_special ************************************************
228 
229  Machine code:
230 
231  <patched call position>
232  e51cc02c ldr ip, [ip, #-44]
233  e1a0e00f mov lr, pc
234  e1a0f00c mov pc, ip
235 
236 ******************************************************************************/
237 
239 {
241  uintptr_t* datap = (uintptr_t*) pr->datap;
242 
243  // Reolve the method.
245 
246  if (m == NULL)
247  return false;
248 
249  // Patch stubroutine.
250  *datap = (uintptr_t) m->stubroutine;
251 
252  // Patch back the original code.
253  patcher_patch_code(pr);
254 
255  return true;
256 }
257 
258 
259 /* patcher_invokevirtual *******************************************************
260 
261  Machine code:
262 
263  <patched call position>
264  e590b000 ldr fp, [r0]
265  e59bc000 ldr ip, [fp, #__]
266  e1a0e00f mov lr, pc
267  e1a0f00c mov pc, ip
268 
269 *******************************************************************************/
270 
272 {
274  int32_t* datap = (int32_t*) pr->datap;
275 
276  // Resolve the method.
278 
279  if (m == NULL)
280  return false;
281 
282  // Patch vftbl index.
283  int32_t disp = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex;
284  *datap = disp;
285 
286  // Patch back the original code.
287  patcher_patch_code(pr);
288 
289  return true;
290 }
291 
292 
293 /* patcher_invokeinterface *****************************************************
294 
295  Machine code:
296 
297  <patched call position>
298  e590b000 ldr fp, [r0]
299  e59bb000 ldr fp, [fp, #__]
300  e59bc000 ldr ip, [fp, #__]
301  e1a0e00f mov lr, pc
302  e1a0f00c mov pc, ip
303 
304 *******************************************************************************/
305 
307 {
309  int32_t* datap = (int32_t*) pr->datap;
310 
311  // Resolve the method.
313 
314  if (m == NULL)
315  return false;
316 
317  // Patch interfacetable index.
318  int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
319  *datap = disp;
320 
321  // HACK The next data segment entry is one below.
322  datap--;
323 
324  // Patch method offset.
325  disp = sizeof(methodptr) * (m - m->clazz->methods);
326  *datap = disp;
327 
328  // Patch back the original code.
329  patcher_patch_code(pr);
330 
331  return true;
332 }
333 
334 
335 /* patcher_checkcast_instanceof_flags ******************************************
336 
337  Machine code:
338 
339  <patched call position>
340 
341 *******************************************************************************/
342 
344 {
346  int32_t* datap = (int32_t*) pr->datap;
347 
348  // Resolve the class.
350 
351  if (c == NULL)
352  return false;
353 
354  // Patch class flags.
355  *datap = (int32_t) c->flags;
356 
357  // Patch back the original code.
358  patcher_patch_code(pr);
359 
360  return true;
361 }
362 
363 
364 /* patcher_resolve_classref_to_index *******************************************
365 
366  Machine code:
367 
368  <patched call position>
369 
370 *******************************************************************************/
371 
373 {
375  int32_t* datap = (int32_t*) pr->datap;
376 
377  // Resolve the class.
379 
380  if (c == NULL)
381  return false;
382 
383  // Patch super class index.
384  *datap = (int32_t) c->index;
385 
386  // Patch back the original code.
387  patcher_patch_code(pr);
388 
389  return true;
390 }
391 
392 
393 /* patcher_resolve_classref_to_vftbl *******************************************
394 
395  Machine code:
396 
397  <patched call position>
398 
399 *******************************************************************************/
400 
402 {
404  uintptr_t* datap = (uintptr_t*) pr->datap;
405 
406  // Resolve the class.
407 
409 
410  if (c == NULL)
411  return false;
412 
413  // Patch super class' vftbl.
414  *datap = (uintptr_t) c->vftbl;
415 
416  // Patch back the original code.
417  patcher_patch_code(pr);
418 
419  return true;
420 }
421 
422 // Dummies, not used
423 
425 {
426  return false;
427 }
428 
430 {
431  return false;
432 }
433 
434 
435 /*
436  * These are local overrides for various environment variables in Emacs.
437  * Please do not remove this and leave it at the end of the file, where
438  * Emacs will automagically detect them.
439  * ---------------------------------------------------------------------
440  * Local variables:
441  * mode: c++
442  * indent-tabs-mode: t
443  * c-basic-offset: 4
444  * tab-width: 4
445  * End:
446  * vim:noexpandtab:sw=4:ts=4:
447  */
bool patcher_invokestatic_special(patchref_t *pr)
Definition: patcher.cpp:392
bool patcher_get_putstatic(patchref_t *pr)
Definition: patcher.cpp:264
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
Definition: patcher.cpp:148
methodinfo * methods
Definition: class.hpp:113
bool patcher_invokeinterface(patchref_t *pr)
Definition: patcher.cpp:477
s4 state
Definition: class.hpp:115
u1 * methodptr
Definition: global.hpp:40
u1 * stubroutine
Definition: method.hpp:102
s4 vftblindex
Definition: method.hpp:81
int32_t offset
Definition: field.hpp:66
classinfo * clazz
Definition: method.hpp:80
void patcher_patch_code(patchref_t *pr)
Definition: patcher.cpp:114
bool patcher_invokevirtual(patchref_t *pr)
Definition: patcher.cpp:433
bool patcher_resolve_classref_to_index(patchref_t *pr)
Definition: patcher.cpp:372
imm_union * value
Definition: field.hpp:67
bool patcher_resolve_classref_to_flags(patchref_t *pr)
Definition: patcher.cpp:225
bool patcher_checkcast_interface(patchref_t *pr)
Definition: patcher.cpp:526
s4 flags
Definition: class.hpp:90
classinfo * clazz
Definition: field.hpp:55
s4 index
Definition: class.hpp:116
bool initialize_class(classinfo *c)
Definition: initialize.cpp:110
bool patcher_get_putfield(patchref_t *pr)
Definition: patcher.cpp:308
vftbl_t * vftbl
Definition: class.hpp:121
fieldinfo * resolve_field_eager(unresolved_field *ref)
Definition: resolve.cpp:1497
#define pc
Definition: md-asm.hpp:56
s4 type
Definition: field.hpp:60
methodinfo * resolve_method_eager(unresolved_method *ref)
Definition: resolve.cpp:2236
uintptr_t datap
uint32_t mcode
classinfo * resolve_classref_eager(constant_classref *ref)
Definition: resolve.cpp:961
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151
uintptr_t mpc
bool patcher_is_valid_trap_instruction_at(void *pc)
Check if the trap instruction at the given PC is valid.
Definition: patcher.cpp:72
#define OFFSET(s, el)
Definition: memory.hpp:90
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
Definition: patcher.cpp:188
bool patcher_instanceof_interface(patchref_t *pr)
Definition: patcher.cpp:572