CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/x86_64/md.cpp - machine dependent x86_64 functions
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5  Copyright (C) 2009 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 <cstdlib>
31 #include <stdint.h>
32 
34 #include "vm/jit/x86_64/md-abi.hpp"
35 
36 #include "vm/vm.hpp"
37 
41 #include "vm/jit/trap.hpp"
42 
43 
44 /* md_init *********************************************************************
45 
46  Do some machine dependent initialization.
47 
48 *******************************************************************************/
49 
50 void md_init(void)
51 {
52  /* nothing to do */
53 }
54 
55 
56 /* md_jit_method_patch_address *************************************************
57 
58  Gets the patch address of the currently compiled method. The offset
59  is extracted from the load instruction(s) before the jump and added
60  to the right base address (PV or REG_METHODPTR).
61 
62  INVOKESTATIC/SPECIAL:
63 
64  4d 8b 15 e2 fe ff ff mov -286(%rip),%r10
65  49 ff d2 rex64Z callq *%r10
66 
67  INVOKEVIRTUAL:
68 
69  4c 8b 17 mov (%rdi),%r10
70  49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
71  48 ff d3 rex64 callq *%rax
72 
73  INVOKEINTERFACE:
74 
75  4c 8b 17 mov (%rdi),%r10
76  4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
77  49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
78  48 ff d3 rex64 callq *%r11
79 
80 *******************************************************************************/
81 
82 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
83 {
84  uint8_t *pc;
85  uint8_t mcode;
86  int32_t offset;
87  void *pa; /* patch address */
88 
89  /* go back to the actual call instruction (3-bytes) */
90 
91  pc = ((uint8_t *) ra) - 3;
92 
93  /* get the last byte of the call */
94 
95  mcode = pc[2];
96 
97  /* check for the different calls */
98 
99  if (mcode == 0xd2) {
100  /* INVOKESTATIC/SPECIAL */
101 
102  /* Get the offset from the instruction (the offset address is
103  4-bytes before the call instruction). */
104 
105  offset = *((int32_t *) (pc - 4));
106 
107  /* add the offset to the return address (IP-relative addressing) */
108 
109  pa = pc + offset;
110  }
111  else if (mcode == 0xd3) {
112  /* INVOKEVIRTUAL/INTERFACE */
113 
114  /* return NULL if no mptr was specified (used for replacement) */
115 
116  if (mptr == NULL)
117  return NULL;
118 
119  /* Get the offset from the instruction (the offset address is
120  4-bytes before the call instruction). */
121 
122  offset = *((int32_t *) (pc - 4));
123 
124  /* add the offset to the method pointer */
125 
126  pa = ((uint8_t *) mptr) + offset;
127  }
128  else {
129  /* catch any problems */
130 
131  vm_abort("md_jit_method_patch_address: unknown instruction %x", mcode);
132 
133  /* keep compiler happy */
134 
135  pa = NULL;
136  }
137 
138  return pa;
139 }
140 
141 
142 /**
143  * Decode the trap instruction at the given PC.
144  *
145  * @param trp information about trap to be filled
146  * @param sig signal number
147  * @param xpc exception PC
148  * @param es execution state of the machine
149  * @return true if trap was decoded successfully, false otherwise.
150  */
151 bool md_trap_decode(trapinfo_t* trp, int sig, void* _xpc, executionstate_t* es)
152 {
153  uint8_t* xpc = (uint8_t*) _xpc;
154 
155 #if 0
156  // Check for StackOverflowException.
157  threads_check_stackoverflow(sp);
158 #endif
159 
160  switch (sig) {
161  case TRAP_SIGFPE:
162  // Check for ArithmeticException.
164  trp->value = 0;
165  return true;
166 
167  case TRAP_SIGILL:
168  // Check for valid trap instruction.
170  trp->type = TRAP_PATCHER;
171  trp->value = 0;
172  return true;
173  }
174  return false;
175 
176  case TRAP_SIGSEGV:
177  {
178  // Get exception-throwing instruction.
179  uint8_t opc = M_ALD_MEM_GET_OPC(xpc);
180  uint8_t mod = M_ALD_MEM_GET_MOD(xpc);
181  uint8_t rm = M_ALD_MEM_GET_RM(xpc);
182 
183  // Check for hardware exception, for values
184  // see emit_mov_mem_reg and emit_mem.
185  if ((opc == 0x8b) && (mod == 0) && (rm == 4)) {
186  int32_t d = M_ALD_MEM_GET_REG(xpc);
187  int32_t disp = M_ALD_MEM_GET_DISP(xpc);
188 
189  // We use the exception type as load displacement.
190  trp->type = disp;
191  trp->value = es->intregs[d];
192  return true;
193  }
194 
195  // Default case is a normal NullPointerException.
196  else {
198  trp->value = 0;
199  return true;
200  }
201  }
202 
203  default:
204  return false;
205  }
206 }
207 
208 
209 /* md_patch_replacement_point **************************************************
210 
211  Patch the given replacement point.
212 
213 *******************************************************************************/
214 
215 #if defined(ENABLE_REPLACEMENT)
216 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
217 {
218  u2 mcode;
219 
220  if (revert) {
221  /* write saved machine code */
222  *(u2*)(pc) = *(u2*)(savedmcode);
223  }
224  else {
225  /* save the current machine code */
226  *(u2*)(savedmcode) = *(u2*)(pc);
227 
228  /* build the machine code for the patch */
229  mcode = 0x0b0f;
230 
231  /* write new machine code */
232  *(u2*)(pc) = (u2) mcode;
233  }
234 
235  /* XXX if required asm_cacheflush(pc,8); */
236 }
237 #endif /* defined(ENABLE_REPLACEMENT) */
238 
239 
240 /*
241  * These are local overrides for various environment variables in Emacs.
242  * Please do not remove this and leave it at the end of the file, where
243  * Emacs will automagically detect them.
244  * ---------------------------------------------------------------------
245  * Local variables:
246  * mode: c++
247  * indent-tabs-mode: t
248  * c-basic-offset: 4
249  * tab-width: 4
250  * End:
251  * vim:noexpandtab:sw=4:ts=4:
252  */
#define pv
Definition: md-asm.hpp:65
intptr_t value
Value (numeric or address) passed with the trap.
Definition: trap.hpp:44
#define mptr
Definition: md-asm.hpp:66
#define M_ALD_MEM_GET_OPC(p)
Definition: codegen.hpp:154
#define ra
Definition: md-asm.hpp:62
#define M_ALD_MEM_GET_REG(p)
Definition: codegen.hpp:156
Contains information about a decoded trap instruction.
Definition: trap.hpp:42
alloc::set< EdgeType >::type mod
uint8_t u1
Definition: types.hpp:40
#define M_ALD_MEM_GET_DISP(p)
Definition: codegen.hpp:158
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
#define xpc
Definition: md-asm.hpp:51
uint16_t u2
Definition: types.hpp:43
int type
Specific trap type (see md-trap.h).
Definition: trap.hpp:43
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
#define sp
Definition: md-asm.hpp:81
#define pc
Definition: md-asm.hpp:56
#define M_ALD_MEM_GET_MOD(p)
Definition: codegen.hpp:155
bool md_trap_decode(trapinfo_t *trp, int sig, void *xpc, executionstate_t *es)
Decode the trap instruction at the given PC.
Definition: md.cpp:192
uintptr_t intregs[INT_REG_CNT]
void md_init(void)
Definition: md.cpp:48
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 M_ALD_MEM_GET_RM(p)
Definition: codegen.hpp:157