CACAO
patcher.cpp
Go to the documentation of this file.
1 /* src/vm/jit/powerpc64/patcher.cpp - PowerPC64 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/powerpc64/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"
49 #include "vm/jit/methodheader.hpp"
51 
52 
53 /* patcher_patch_code **********************************************************
54 
55  Just patches back the original machine code.
56 
57 *******************************************************************************/
58 
60 {
61  // Patch back original code.
62  *((uint32_t*) pr->mpc) = pr->mcode;
63 
64  // Synchronize instruction cache.
65  md_icacheflush((void*) pr->mpc, 1 * 4);
66 }
67 
68 
69 /* patcher_get_putstatic *******************************************************
70 
71  Machine code:
72 
73  <patched call position>
74  816dffc8 lwz r11,-56(r13)
75  80ab0000 lwz r5,0(r11)
76 
77 *******************************************************************************/
78 
80 {
82  uintptr_t* datap = (uintptr_t*) pr->datap;
83 
84  // Resolve the field.
86 
87  if (fi == NULL)
88  return false;
89 
90  // Check if the field's class is initialized.
91  if (!(fi->clazz->state & CLASS_INITIALIZED))
92  if (!initialize_class(fi->clazz))
93  return false;
94 
95  // Patch the field value's address.
96  *datap = (uintptr_t) fi->value;
97 
98  // Synchronize data cache.
99  md_dcacheflush(datap, SIZEOF_VOID_P);
100 
101  // Patch back the original code.
102  patcher_patch_code(pr);
103 
104  return true;
105 }
106 
107 
108 /* patcher_get_putfield ********************************************************
109 
110  Machine code:
111 
112  <patched call position>
113  811f0014 lwz r8,20(r31)
114 
115 *******************************************************************************/
116 
118 {
120 
121  // Resolve the field.
122  fieldinfo* fi = resolve_field_eager(uf);
123 
124  if (fi == NULL)
125  return false;
126 
127  // Patch the field offset in the patcher. We also need this to
128  // validate patchers.
129  pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
130 
131  // Patch back the original code.
132  patcher_patch_code(pr);
133 
134  return true;
135 }
136 
137 
138 /* patcher_invokestatic_special ************************************************
139 
140  Machine code:
141 
142  <patched call position>
143  81adffd8 lwz r13,-40(r13)
144  7da903a6 mtctr r13
145  4e800421 bctrl
146 
147 ******************************************************************************/
148 
150 {
152  uintptr_t* datap = (uintptr_t*) pr->datap;
153 
154  // Resolve the method.
156 
157  if (m == NULL)
158  return false;
159 
160  // Patch stubroutine.
161  *datap = (uintptr_t) m->stubroutine;
162 
163  // Synchronize data cache.
164  md_dcacheflush(datap, SIZEOF_VOID_P);
165 
166  // Patch back the original code.
167  patcher_patch_code(pr);
168 
169  return true;
170 }
171 
172 
173 /* patcher_invokevirtual *******************************************************
174 
175  Machine code:
176 
177  <patched call position>
178  81830000 lwz r12,0(r3)
179  81ac0088 lwz r13,136(r12)
180  7da903a6 mtctr r13
181  4e800421 bctrl
182 
183 *******************************************************************************/
184 
186 {
187  uint32_t* pc = (uint32_t*) pr->mpc;
189 
190  // Resolve the method.
192 
193  if (m == NULL)
194  return false;
195 
196  // Patch vftbl index.
197  int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
198 
199  pc[1] |= (disp & 0x0000ffff);
200 
201  // Synchronize instruction cache.
202  md_icacheflush(pc + 1, 1 * 4);
203 
204  // Patch back the original code.
205  patcher_patch_code(pr);
206 
207  return true;
208 }
209 
210 
211 /* patcher_invokeinterface *****************************************************
212 
213  Machine code:
214 
215  <patched call position>
216  81830000 lwz r12,0(r3)
217  818cffd0 lwz r12,-48(r12)
218  81ac000c lwz r13,12(r12)
219  7da903a6 mtctr r13
220  4e800421 bctrl
221 
222 *******************************************************************************/
223 
225 {
226  uint32_t* pc = (uint32_t*) pr->mpc;
228 
229  // Resolve the method.
231 
232  if (m == NULL)
233  return false;
234 
235  // Patch interfacetable index.
236  int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
237 
238  // XXX TWISTI: check displacement
239  pc[1] |= (disp & 0x0000ffff);
240 
241  // Patch method offset.
242  disp = sizeof(methodptr) * (m - m->clazz->methods);
243 
244  // XXX TWISTI: check displacement
245  pc[2] |= (disp & 0x0000ffff);
246 
247  // Synchronize instruction cache.
248  md_icacheflush(pc + 1, 2 * 4);
249 
250  // Patch back the original code.
251  patcher_patch_code(pr);
252 
253  return true;
254 }
255 
256 
257 /* patcher_checkcast_interface **************************************
258 
259  Machine code:
260 
261  <patched call position>
262  81870000 lwz r12,0(r7)
263  800c0010 lwz r0,16(r12)
264  34000000 addic. r0,r0,0
265  408101fc bgt- 0x3002e518 FIXME
266  83c00003 lwz r30,3(0) FIXME
267  800c0000 lwz r0,0(r12)
268 
269 *******************************************************************************/
270 
272 {
273  uint32_t* pc = (uint32_t*) pr->mpc;
275 
276  // Resolve the class.
278 
279  if (c == NULL)
280  return false;
281 
282  // Patch super class index.
283  int32_t disp = -(c->index);
284  pc[2] |= (disp & 0x0000ffff);
285 
286  disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
287  pc[5] |= (disp & 0x0000ffff);
288 
289  // Synchronize instruction cache.
290  md_icacheflush(pc + 2, 4 * 4);
291 
292  // Patch back the original code.
293  patcher_patch_code(pr);
294 
295  return true;
296 }
297 
298 
299 /* patcher_instanceof_interface **************************************
300 
301  Machine code:
302 
303  <patched call position>
304  81870000 lwz r12,0(r7)
305  800c0010 lwz r0,16(r12)
306  34000000 addic. r0,r0,0
307  408101fc ble- 0x3002e518
308  800c0000 lwz r0,0(r12)
309 
310 *******************************************************************************/
311 
313 {
314  uint32_t* pc = (uint32_t*) pr->mpc;
316 
317  // Resolve the class.
319 
320  if (c == NULL)
321  return false;
322 
323  // Patch super class index.
324  int32_t disp = -(c->index);
325  pc[2] |= (disp & 0x0000ffff);
326 
327  disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
328  pc[4] |= (disp & 0x0000ffff);
329 
330  // Synchronize instruction cache.
331  md_icacheflush(pc + 2, 3 * 4);
332 
333  // Patch back the original code.
334  patcher_patch_code(pr);
335 
336  return true;
337 }
338 
339 
340 /* patcher_resolve_classref_to_classinfo ***************************************
341 
342  ACONST:
343 
344  <patched call postition>
345  806dffc4 lwz r3,-60(r13)
346  81adffc0 lwz r13,-64(r13)
347  7da903a6 mtctr r13
348  4e800421 bctrl
349 
350 
351  MULTIANEWARRAY:
352 
353  <patched call position>
354  808dffc0 lwz r4,-64(r13)
355  38a10038 addi r5,r1,56
356  81adffbc lwz r13,-68(r13)
357  7da903a6 mtctr r13
358  4e800421 bctrl
359 
360 
361  ARRAYCHECKCAST:
362 
363  <patched call position>
364  808dffd8 lwz r4,-40(r13)
365  81adffd4 lwz r13,-44(r13)
366  7da903a6 mtctr r13
367  4e800421 bctrl
368 
369 *******************************************************************************/
370 
372 {
374  uintptr_t* datap = (uintptr_t*) pr->datap;
375 
376  // Resolve the class.
378 
379  if (c == NULL)
380  return false;
381 
382  // Patch the classinfo pointer.
383  *datap = (uintptr_t) c;
384 
385  // Synchronize data cache.
386  md_dcacheflush(datap, SIZEOF_VOID_P);
387 
388  // Patch back the original code.
389  patcher_patch_code(pr);
390 
391  return true;
392 }
393 
394 
395 /* patcher_resolve_classref_to_vftbl *******************************************
396 
397  CHECKCAST (class):
398 
399  <patched call position>
400  81870000 lwz r12,0(r7)
401  800c0014 lwz r0,20(r12)
402  818dff78 lwz r12,-136(r13)
403 
404 
405  INSTANCEOF (class):
406 
407  <patched call position>
408  817d0000 lwz r11,0(r29)
409  818dff8c lwz r12,-116(r13)
410 
411 *******************************************************************************/
412 
414 {
416  uintptr_t* datap = (uintptr_t*) pr->datap;
417 
418  // Resolve the class.
420 
421  if (c == NULL)
422  return false;
423 
424  // Patch super class' vftbl.
425  *datap = (uintptr_t) c->vftbl;
426 
427  // Synchronize data cache.
428  md_dcacheflush(datap, SIZEOF_VOID_P);
429 
430  // Patch back the original code.
431  patcher_patch_code(pr);
432 
433  return true;
434 }
435 
436 /* patcher_resolve_classref_to_flags *******************************************
437 
438  CHECKCAST/INSTANCEOF:
439 
440  <patched call position>
441  818dff7c lwz r12,-132(r13)
442 
443 *******************************************************************************/
444 
446 {
448  int32_t* datap = (int32_t*) pr->datap;
449 
450  // Resolve the class.
452 
453  if (c == NULL)
454  return false;
455 
456  // Patch class flags.
457  *datap = (int32_t) c->flags;
458 
459  // Synchronize data cache.
460  md_dcacheflush(datap, SIZEOF_VOID_P);
461 
462  // Patch back the original code.
463  patcher_patch_code(pr);
464 
465  return true;
466 }
467 
468 
469 /*
470  * These are local overrides for various environment variables in Emacs.
471  * Please do not remove this and leave it at the end of the file, where
472  * Emacs will automagically detect them.
473  * ---------------------------------------------------------------------
474  * Local variables:
475  * mode: c++
476  * indent-tabs-mode: t
477  * c-basic-offset: 4
478  * tab-width: 4
479  * End:
480  * vim:noexpandtab:sw=4:ts=4:
481  */
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
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
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
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
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