CACAO
patcher.cpp
Go to the documentation of this file.
1 /* src/vm/jit/mips/patcher.cpp - MIPS code patching functions
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <cassert>
29 #include <stdint.h>
30 
31 #include "vm/jit/mips/codegen.hpp"
32 #include "vm/jit/mips/md.hpp"
33 
34 #include "mm/memory.hpp"
35 
36 #include "native/native.hpp"
37 
38 #include "vm/jit/builtin.hpp"
39 #include "vm/class.hpp"
40 #include "vm/field.hpp"
41 #include "vm/initialize.hpp"
42 #include "vm/options.hpp"
43 #include "vm/references.hpp"
44 #include "vm/resolve.hpp"
45 
46 #include "vm/jit/asmpart.hpp"
48 
49 
50 /* patcher_patch_code **********************************************************
51 
52  Just patches back the original machine code.
53 
54 *******************************************************************************/
55 
57 {
58  *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
59  md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
60 }
61 
62 
63 /* patcher_get_putstatic *******************************************************
64 
65  Machine code:
66 
67  <patched call position>
68  dfc1ffb8 ld at,-72(s8)
69  fc250000 sd a1,0(at)
70 
71 *******************************************************************************/
72 
74 {
76  uintptr_t* datap = (uintptr_t*) pr->datap;
77 
78  // Resolve the field.
80 
81  if (fi == NULL)
82  return false;
83 
84  // Check if the field's class is initialized.
85  if (!(fi->clazz->state & CLASS_INITIALIZED))
86  if (!initialize_class(fi->clazz))
87  return false;
88 
89  // Patch the field value's address.
90  *datap = (uintptr_t) fi->value;
91 
92  // Synchronize data cache.
93  md_dcacheflush(datap, SIZEOF_VOID_P);
94 
95  // Patch back the original code.
97 
98  return true;
99 }
100 
101 
102 /* patcher_get_putfield ********************************************************
103 
104  Machine code:
105 
106  <patched call position>
107  8ee90020 lw a5,32(s7)
108 
109 *******************************************************************************/
110 
112 {
113  uint32_t* pc = (uint32_t*) pr->mpc;
115 
116  // Resolve the field.
117  fieldinfo* fi = resolve_field_eager(uf);
118 
119  if (fi == NULL)
120  return false;
121 
122 #if SIZEOF_VOID_P == 4
123  if (IS_LNG_TYPE(fi->type)) {
124 # if WORDS_BIGENDIAN == 1
125  // ATTENTION: order of these instructions depend on M_LLD_INTERN.
126  // The first instruction is patched back later.
127  pr->mcode |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
128  pc[1] |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
129 # else
130  // ATTENTION: order of these instructions depend on M_LLD_INTERN.
131  // The first instruction is patched back later.
132  pr->mcode |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
133  pc[1] |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
134 # endif
135  }
136  else
137 #endif
138  {
139  // The instruction is patched back later.
140  pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
141  }
142 
143  // Synchronize instruction cache.
144  md_icacheflush(pc, 2 * 4);
145 
146  // Patch back the original code.
147  patcher_patch_code(pr);
148 
149  return true;
150 }
151 
152 
153 /* patcher_resolve_classref_to_classinfo ***************************************
154 
155  ACONST:
156 
157  <patched call postition>
158  dfc4ff98 ld a0,-104(s8)
159 
160  MULTIANEWARRAY:
161 
162  <patched call position>
163  dfc5ff90 ld a1,-112(s8)
164  03a03025 move a2,sp
165  dfd9ff88 ld t9,-120(s8)
166  0320f809 jalr t9
167  00000000 nop
168 
169  ARRAYCHECKCAST:
170 
171  <patched call position>
172  dfc5ffc0 ld a1,-64(s8)
173  dfd9ffb8 ld t9,-72(s8)
174  0320f809 jalr t9
175  00000000 nop
176 
177 *******************************************************************************/
178 
180 {
182  uintptr_t* datap = (uintptr_t*) pr->datap;
183 
184  // Resolve the class.
186 
187  if (c == NULL)
188  return false;
189 
190  // Patch the class.
191  *datap = (uintptr_t) c;
192 
193  // Synchronize data cache.
194  md_dcacheflush(datap, SIZEOF_VOID_P);
195 
196  // Patch back the original code.
197  patcher_patch_code(pr);
198 
199  return true;
200 }
201 
202 
203 /* patcher_resolve_classref_to_vftbl *******************************************
204 
205  CHECKCAST (class):
206  INSTANCEOF (class):
207 
208  <patched call position>
209  dd030000 ld v1,0(a4)
210  dfd9ff18 ld t9,-232(s8)
211 
212 *******************************************************************************/
213 
215 {
217  uintptr_t* datap = (uintptr_t*) pr->datap;
218 
219  // Resolve the field.
221 
222  if (c == NULL)
223  return false;
224 
225  // Patch super class' vftbl.
226  *datap = (uintptr_t) c->vftbl;
227 
228  // Synchronize data cache.
229  md_dcacheflush(datap, SIZEOF_VOID_P);
230 
231  // Patch back the original code.
232  patcher_patch_code(pr);
233 
234  return true;
235 }
236 
237 
238 /* patcher_resolve_classref_to_flags *******************************************
239 
240  CHECKCAST/INSTANCEOF:
241 
242  <patched call position>
243  8fc3ff24 lw v1,-220(s8)
244  30630200 andi v1,v1,512
245  1060000d beq v1,zero,0x000000001051824c
246  00000000 nop
247 
248 *******************************************************************************/
249 
251 {
253  int32_t* datap = (int32_t*) pr->datap;
254 
255  // Resolve the class.
257 
258  if (c == NULL)
259  return false;
260 
261  // Patch class flags.
262  *datap = (int32_t) c->flags;
263 
264  // Synchronize data cache.
265  md_dcacheflush(datap, sizeof(int32_t));
266 
267  // Patch back the original code.
268  patcher_patch_code(pr);
269 
270  return true;
271 }
272 
273 
274 /* patcher_invokestatic_special ************************************************
275 
276  Machine code:
277 
278  <patched call position>
279  dfdeffc0 ld s8,-64(s8)
280  03c0f809 jalr s8
281  00000000 nop
282 
283 ******************************************************************************/
284 
286 {
288  void** datap = (void**) pr->datap;
289 
290  // Resolve the method.
292 
293  if (m == NULL)
294  return false;
295 
296  // Patch stubroutine.
297  *datap = (void*) m->stubroutine;
298 
299  // Synchronize data cache.
300  md_dcacheflush(datap, SIZEOF_VOID_P);
301 
302  // Patch back the original code.
303  patcher_patch_code(pr);
304 
305  return true;
306 }
307 
308 
309 /* patcher_invokevirtual *******************************************************
310 
311  Machine code:
312 
313  <patched call position>
314  dc990000 ld t9,0(a0)
315  df3e0040 ld s8,64(t9)
316  03c0f809 jalr s8
317  00000000 nop
318 
319 *******************************************************************************/
320 
322 {
323  uint32_t* pc = (uint32_t*) pr->mpc;
325 
326  // Resolve the method.
328 
329  if (m == NULL)
330  return false;
331 
332  // Patch vftbl index.
333  pc[1] |= (int32_t) ((OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
334 
335  // Synchronize instruction cache.
336  md_icacheflush(pc + 1, 1 * 4);
337 
338  // Patch back the original code.
339  patcher_patch_code(pr);
340 
341  return true;
342 }
343 
344 
345 /* patcher_invokeinterface *****************************************************
346 
347  Machine code:
348 
349  <patched call position>
350  dc990000 ld t9,0(a0)
351  df39ffa0 ld t9,-96(t9)
352  df3e0018 ld s8,24(t9)
353  03c0f809 jalr s8
354  00000000 nop
355 
356 *******************************************************************************/
357 
359 {
360  uint32_t* pc = (uint32_t*) pr->mpc;
362 
363  // Resovlve the method.
365 
366  if (m == NULL)
367  return false;
368 
369  // Patch interfacetable index.
370  pc[1] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
371 
372  // Patch method offset.
373  pc[2] |= (int32_t) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
374 
375  // Synchronize instruction cache.
376  md_icacheflush(pc + 1, 2 * 4);
377 
378  // Patch back the original code.
379  patcher_patch_code(pr);
380 
381  return true;
382 }
383 
384 
385 /* patcher_checkcast_interface *************************************************
386 
387  Machine code:
388 
389  <patched call position>
390  dd030000 ld v1,0(a4)
391  8c79001c lw t9,28(v1)
392  27390000 addiu t9,t9,0
393  1b200082 blez t9,zero,0x000000001051843c
394  00000000 nop
395  dc790000 ld t9,0(v1)
396 
397 *******************************************************************************/
398 
400 {
401  uint32_t* pc = (uint32_t*) pr->mpc;
403 
404  // Resolve the class.
406 
407  if (c == NULL)
408  return false;
409 
410  // Patch super class index.
411  pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
412  pc[6] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
413 
414  // Synchronize instruction cache.
415  md_icacheflush(pc + 2, 5 * 4);
416 
417  // Patch back the original code.
418  patcher_patch_code(pr);
419 
420  return true;
421 }
422 
423 
424 /* patcher_instanceof_interface ************************************************
425 
426  Machine code:
427 
428  <patched call position>
429  dd030000 ld v1,0(a4)
430  8c79001c lw t9,28(v1)
431  27390000 addiu t9,t9,0
432  1b200082 blez t9,zero,0x000000001051843c
433  00000000 nop
434  dc790000 ld t9,0(v1)
435 
436 *******************************************************************************/
437 
439 {
440  uint32_t* pc = (uint32_t*) pr->mpc;
442 
443  // Resolve the method.
445 
446  if (c == NULL)
447  return false;
448 
449  // Patch super class index.
450  pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
451  pc[5] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
452 
453  // Synchronize instruction cache.
454  md_icacheflush(pc + 2, 4 * 4);
455 
456  // Patch back the original code.
457  patcher_patch_code(pr);
458 
459  return true;
460 }
461 
462 
463 /*
464  * These are local overrides for various environment variables in Emacs.
465  * Please do not remove this and leave it at the end of the file, where
466  * Emacs will automagically detect them.
467  * ---------------------------------------------------------------------
468  * Local variables:
469  * mode: c++
470  * indent-tabs-mode: t
471  * c-basic-offset: 4
472  * tab-width: 4
473  * End:
474  * vim:noexpandtab:sw=4:ts=4:
475  */
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
#define PATCHER_CALL_SIZE
Definition: codegen.hpp:68
s4 state
Definition: class.hpp:115
static void md_dcacheflush(void *addr, int nbytes)
Definition: md.hpp:163
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
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
#define IS_LNG_TYPE(a)
Definition: global.hpp:135
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
#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