1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2011
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
32 #include "vm/jit/x86_64/codegen.h"
33 #include "vm/jit/x86_64/md.h"
35 #include "mm/memory.hpp"
37 #include "native/native.hpp"
39 #include "vm/jit/builtin.hpp"
40 #include "vm/class.hpp"
41 #include "vm/field.hpp"
42 #include "vm/initialize.hpp"
43 #include "vm/options.h"
44 #include "vm/references.h"
45 #include "vm/resolve.hpp"
47 #include "vm/jit/patcher-common.hpp"
50 /* patcher_patch_code **********************************************************
52 Just patches back the original machine code.
54 *******************************************************************************/
56 void patcher_patch_code(patchref_t *pr)
58 *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;
59 md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
62 static int32_t *patch_checked_location(int32_t *p, int32_t val)
65 // verify that it's aligned
66 assert((((uintptr_t) p) & (4-1)) == 0);
71 static void checked_icache_flush(int32_t *addr, int nbytes, int32_t *check_loc)
73 assert((int8_t*) addr + nbytes - sizeof(int32_t) >= (int8_t*) check_loc);
74 md_icacheflush(addr, nbytes);
78 * Check if the trap instruction at the given PC is valid.
80 * @param pc Program counter.
82 * @return true if valid, false otherwise.
84 bool patcher_is_valid_trap_instruction_at(void* pc)
86 uint16_t mcode = *((uint16_t*) pc);
88 // Check for the undefined instruction we use.
89 return (mcode == 0x0b0f);
93 * Overwrites the MFENCE instruction at the indicated address with a 3-byte
94 * NOP. The MFENCE instruction is not allowed to cross a (4-byte) word
97 * @param pc Program counter.
99 static void patch_out_mfence(void *pc)
101 uint32_t *p = (uint32_t*) (((uintptr_t) pc) & ~3);
103 assert((((uintptr_t) pc) & 3) < 2);
104 if (((uintptr_t) pc) & 1)
105 *p = (*p & 0x000000ff) | 0x001f0f00;
107 *p = (*p & 0xff000000) | 0x00001f0f;
109 md_icacheflush(p, 4);
112 /* patcher_resolve_classref_to_classinfo ***************************************
116 <patched call position>
117 48 bf a0 f0 92 00 00 00 00 00 mov $0x92f0a0,%rdi
121 <patched call position>
122 48 be 30 40 b2 00 00 00 00 00 mov $0xb24030,%rsi
123 48 89 e2 mov %rsp,%rdx
124 48 b8 7c 96 4b 00 00 00 00 00 mov $0x4b967c,%rax
129 <patched call position>
130 48 be b8 3f b2 00 00 00 00 00 mov $0xb23fb8,%rsi
131 48 b8 00 00 00 00 00 00 00 00 mov $0x0,%rax
134 *******************************************************************************/
136 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
138 constant_classref* cr = (constant_classref*) pr->ref;
139 uintptr_t* datap = (uintptr_t*) pr->datap;
141 // Resolve the class.
142 classinfo* c = resolve_classref_eager(cr);
148 *datap = (uintptr_t) c;
150 // Synchronize data cache.
151 md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
153 // Patch back the original code.
154 patcher_patch_code(pr);
160 /* patcher_resolve_classref_to_vftbl *******************************************
165 <patched call position>
167 *******************************************************************************/
169 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
171 constant_classref* cr = (constant_classref*) pr->ref;
172 uintptr_t* datap = (uintptr_t*) pr->datap;
174 // Resolve the field.
175 classinfo* c = resolve_classref_eager(cr);
180 // Patch super class' vftbl.
181 *datap = (uintptr_t) c->vftbl;
183 // Synchronize data cache.
184 md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
186 // Patch back the original code.
187 patcher_patch_code(pr);
193 /* patcher_resolve_classref_to_flags *******************************************
195 CHECKCAST/INSTANCEOF:
197 <patched call position>
199 *******************************************************************************/
201 bool patcher_resolve_classref_to_flags(patchref_t *pr)
203 constant_classref* cr = (constant_classref*) pr->ref;
204 /* int32_t* datap = (int32_t*) pr->datap; */
205 uint8_t* ra = (uint8_t*) pr->mpc;
207 // Resolve the field.
208 classinfo* c = resolve_classref_eager(cr);
213 ra += PATCHER_CALL_SIZE;
214 ra += PATCH_ALIGNMENT((uintptr_t) ra, 2, sizeof(int32_t));
216 // Patch class flags.
217 /* *datap = c->flags; */
218 patch_checked_location((int32_t*) (ra + 2), c->flags);
220 // Synchronize data cache.
221 /* md_dcacheflush(datap, sizeof(int32_t)); */
222 md_icacheflush(ra + 2, sizeof(int32_t));
224 // Patch back the original code.
225 patcher_patch_code(pr);
231 /* patcher_get_putstatic *******************************************************
235 <patched call position>
236 4d 8b 15 86 fe ff ff mov -378(%rip),%r10
237 49 8b 32 mov (%r10),%rsi
239 *******************************************************************************/
241 bool patcher_get_putstatic(patchref_t *pr)
243 unresolved_field* uf = (unresolved_field*) pr->ref;
244 uintptr_t* datap = (uintptr_t*) pr->datap;
245 uint8_t* ra = (uint8_t*) pr->mpc;
247 // Resolve the field.
248 fieldinfo* fi = resolve_field_eager(uf);
253 ra += PATCHER_CALL_SIZE;
255 // Check if the field's class is initialized/
256 if (!(fi->clazz->state & CLASS_INITIALIZED))
257 if (!initialize_class(fi->clazz))
260 // Patch the field value's address.
261 *datap = (uintptr_t) fi->value;
263 if (pr->disp_mb && !(fi->flags & ACC_VOLATILE))
264 patch_out_mfence(ra + pr->disp_mb - 2);
266 // Synchronize data cache.
267 md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
269 // Patch back the original code.
270 patcher_patch_code(pr);
276 /* patcher_get_putfield ********************************************************
280 <patched call position>
281 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d
283 *******************************************************************************/
285 bool patcher_get_putfield(patchref_t *pr)
287 uint8_t* pc = (uint8_t*) pr->mpc;
288 unresolved_field* uf = (unresolved_field*) pr->ref;
290 // Resolve the field.
291 fieldinfo* fi = resolve_field_eager(uf);
296 pc += PATCHER_CALL_SIZE;
298 int disp = -sizeof(int32_t) + pr->patch_align;
299 patch_checked_location((int32_t*) (pc + disp), fi->offset);
301 if (pr->disp_mb && !(fi->flags & ACC_VOLATILE))
302 patch_out_mfence(pc + pr->disp_mb - 2);
304 // Synchronize instruction cache.
305 md_icacheflush(pc, disp + sizeof(int32_t));
307 // Patch back the original code.
308 patcher_patch_code(pr);
314 /* patcher_putfieldconst *******************************************************
318 <patched call position>
319 41 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%r13)
321 *******************************************************************************/
323 bool patcher_putfieldconst(patchref_t *pr)
325 uint8_t* pc = (uint8_t*) pr->mpc;
326 unresolved_field* uf = (unresolved_field*) pr->ref;
328 // Resolve the field.
329 fieldinfo* fi = resolve_field_eager(uf);
334 pc += PATCHER_CALL_SIZE;
336 int disp = -2*sizeof(int32_t) + pr->patch_align;
337 patch_checked_location((int32_t*) (pc + disp), fi->offset);
339 if (pr->disp_mb && !(fi->flags & ACC_VOLATILE))
340 patch_out_mfence(pc + pr->disp_mb - 2);
342 // Synchronize instruction cache.
343 md_icacheflush(pc, disp + sizeof(int32_t));
345 // Patch back the original code.
346 patcher_patch_code(pr);
352 /* patcher_invokestatic_special ************************************************
356 <patched call position>
357 49 ba 00 00 00 00 00 00 00 00 mov $0x0,%r10
360 *******************************************************************************/
362 bool patcher_invokestatic_special(patchref_t *pr)
364 unresolved_method* um = (unresolved_method*) pr->ref;
365 uintptr_t* datap = (uintptr_t*) pr->datap;
367 // Resolve the method.
368 methodinfo* m = resolve_method_eager(um);
373 // Patch stubroutine.
374 *datap = (uintptr_t) m->stubroutine;
376 // Synchronize data cache.
377 md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
379 // Patch back the original code.
380 patcher_patch_code(pr);
386 /* patcher_invokevirtual *******************************************************
390 <patched call position>
391 4c 8b 17 mov (%rdi),%r10
392 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
395 *******************************************************************************/
397 bool patcher_invokevirtual(patchref_t *pr)
399 uint8_t* pc = (uint8_t*) pr->mpc;
400 unresolved_method* um = (unresolved_method*) pr->ref;
402 // Resovlve the method.
403 methodinfo* m = resolve_method_eager(um);
408 pc += PATCHER_CALL_SIZE;
409 pc += PATCH_ALIGNMENT((uintptr_t) pc, 6, sizeof(int32_t));
411 // Patch vftbl index.
412 patch_checked_location((int32_t*) (pc + 6), (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
414 // Synchronize instruction cache.
415 md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P);
417 // Patch back the original code.
418 patcher_patch_code(pr);
424 /* patcher_invokeinterface *****************************************************
428 <patched call position>
429 4c 8b 17 mov (%rdi),%r10
430 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
431 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
434 *******************************************************************************/
436 bool patcher_invokeinterface(patchref_t *pr)
438 uint8_t* pc = (uint8_t*) pr->mpc;
439 unresolved_method* um = (unresolved_method*) pr->ref;
441 // Resolve the method.
442 methodinfo* m = resolve_method_eager(um);
447 pc += PATCHER_CALL_SIZE;
448 pc += PATCH_ALIGNMENT((uintptr_t) pc, 6, sizeof(int32_t));
450 // Patch interfacetable index.
451 patch_checked_location((int32_t*) (pc + 6), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index));
453 int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 3 + 7), 3, sizeof(int32_t));
455 // Patch method offset.
456 int32_t *loc = patch_checked_location((int32_t*) (pc + 3 + 7 + 3), (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)));
458 // Synchronize instruction cache.
459 checked_icache_flush(pc + 6, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P + disp, loc);
461 // Patch back the original code.
462 patcher_patch_code(pr);
468 /* patcher_checkcast_interface *************************************************
472 <patched call position>
473 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
474 41 81 fb 00 00 00 00 cmp $0x0,%r11d
475 0f 8f 08 00 00 00 jg 0x00002aaaaae511d5
476 48 8b 0c 25 03 00 00 00 mov 0x3,%rcx
477 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
479 *******************************************************************************/
481 bool patcher_checkcast_interface(patchref_t *pr)
483 uint8_t* pc = (uint8_t*) pr->mpc;
484 constant_classref* cr = (constant_classref*) pr->ref;
486 // Resolve the class.
487 classinfo* c = resolve_classref_eager(cr);
492 pc += PATCHER_CALL_SIZE;
493 pc += PATCH_ALIGNMENT((uintptr_t) pc, 10, sizeof(int32_t));
495 // Patch super class index.
496 patch_checked_location((int32_t*) (pc + 10), c->index);
498 int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 7 + 7 + 6 + 8), 3, sizeof(int32_t));
500 int32_t *loc = patch_checked_location((int32_t*) (pc + 7 + 7 + 6 + 8 + 3), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)));
502 // Synchronize instruction cache.
503 checked_icache_flush(pc + 10, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t) + disp, loc);
505 // Patch back the original code.
506 patcher_patch_code(pr);
512 /* patcher_instanceof_interface ************************************************
516 <patched call position>
517 45 8b 9a 1c 00 00 00 mov 0x1c(%r10),%r11d
518 41 81 fb 00 00 00 00 cmp $0x0,%r11d
519 0f 8e 94 04 00 00 jle 0x00002aaaaab018f8
520 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11
522 *******************************************************************************/
524 bool patcher_instanceof_interface(patchref_t *pr)
526 uint8_t* pc = (uint8_t*) pr->mpc;
527 constant_classref* cr = (constant_classref*) pr->ref;
529 // Resolve the class.
530 classinfo* c = resolve_classref_eager(cr);
535 pc += PATCHER_CALL_SIZE;
536 pc += PATCH_ALIGNMENT((uintptr_t) pc, 10, sizeof(int32_t));
538 // Patch super class index.
539 patch_checked_location((int32_t*) (pc + 10), c->index);
541 int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 7 + 7 + 6), 3, sizeof(int32_t));
543 int32_t *loc = patch_checked_location((int32_t*) (pc + 7 + 7 + 6 + 3), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)));
545 // Synchronize instruction cache.
546 checked_icache_flush(pc + 10, sizeof(int32_t) + 6 + 3 + sizeof(int32_t) + disp, loc);
548 // Patch back the original code.
549 patcher_patch_code(pr);
556 * These are local overrides for various environment variables in Emacs.
557 * Please do not remove this and leave it at the end of the file, where
558 * Emacs will automagically detect them.
559 * ---------------------------------------------------------------------
562 * indent-tabs-mode: t
566 * vim:noexpandtab:sw=4:ts=4: