CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/i386/md.cpp - machine dependent i386 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 <stdint.h>
31 
32 #include "vm/types.hpp"
33 
34 #include "vm/jit/i386/codegen.hpp"
35 
36 #include "vm/global.hpp"
37 #include "vm/vm.hpp"
38 
39 #include "vm/jit/asmpart.hpp"
40 #include "vm/jit/jit.hpp"
42 #include "vm/jit/trap.hpp"
43 
44 
45 /* md_init *********************************************************************
46 
47  Do some machine dependent initialization.
48 
49 *******************************************************************************/
50 
51 void md_init(void)
52 {
53  (void) asm_md_init();
54 }
55 
56 
57 /* md_jit_method_patch_address *************************************************
58 
59  Gets the patch address of the currently compiled method. The offset
60  is extracted from the load instruction(s) before the jump and added
61  to the right base address (PV or REG_METHODPTR).
62 
63  INVOKESTATIC/SPECIAL:
64 
65  b9 30 00 49 b7 mov $0xb7490030,%ecx
66  ff d1 call *%ecx
67 
68  INVOKEVIRTUAL:
69 
70  8b 08 mov (%eax),%ecx
71  8b 91 00 00 00 00 mov 0x0(%ecx),%edx
72  ff d2 call *%edx
73 
74  INVOKEINTERFACE:
75 
76  8b 08 mov (%eax),%ecx
77  8b 89 00 00 00 00 mov 0x0(%ecx),%ecx
78  8b 91 00 00 00 00 mov 0x0(%ecx),%edx
79  ff d2 call *%edx
80 
81 *******************************************************************************/
82 
83 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
84 {
85  uint8_t *pc;
86  uint16_t opcode;
87  int32_t disp;
88  void *pa; /* patch address */
89 
90  /* go back to the actual call instruction (2-bytes) */
91 
92  pc = ((uint8_t *) ra) - 2;
93 
94  /* Get the opcode of the call. */
95 
96  opcode = *((uint16_t *) pc);
97 
98  /* check for the different calls */
99 
100  switch (opcode) {
101  case 0xd1ff:
102  /* INVOKESTATIC/SPECIAL */
103 
104  /* Patch address is 4-bytes before the call instruction. */
105 
106  pa = pc - 4;
107  break;
108 
109  case 0xd2ff:
110  /* INVOKEVIRTUAL/INTERFACE */
111 
112  /* Return NULL if no mptr was specified (used for
113  replacement). */
114 
115  if (mptr == NULL)
116  return NULL;
117 
118  /* Get the displacement from the instruction (the displacement
119  address is 4-bytes before the call instruction). */
120 
121  disp = *((int32_t *) (pc - 4));
122 
123  /* Add the displacement to the method pointer. */
124 
125  pa = ((uint8_t *) mptr) + disp;
126  break;
127 
128  default:
129  vm_abort_disassemble(pc, 1, "md_jit_method_patch_address: unknown instruction %x", opcode);
130  return NULL;
131  }
132 
133  return pa;
134 }
135 
136 
137 /**
138  * Decode the trap instruction at the given PC.
139  *
140  * @param trp information about trap to be filled
141  * @param sig signal number
142  * @param xpc exception PC
143  * @param es execution state of the machine
144  * @return true if trap was decoded successfully, false otherwise.
145  */
146 bool md_trap_decode(trapinfo_t* trp, int sig, void* _xpc, executionstate_t* es)
147 {
148  uint8_t* xpc = (uint8_t*) _xpc;
149 
150  switch (sig) {
151  case TRAP_SIGFPE:
152  // This is an ArithmeticException.
154  trp->value = 0;
155  return true;
156 
157  case TRAP_SIGILL:
158  // Check for valid trap instruction.
160  trp->type = TRAP_PATCHER;
161  trp->value = 0;
162  return true;
163  }
164  return false;
165 
166  case TRAP_SIGSEGV:
167  {
168  // Get exception-throwing instruction.
169  uint8_t opc = M_ALD_MEM_GET_OPC(xpc);
170  uint8_t mod = M_ALD_MEM_GET_MOD(xpc);
171  uint8_t rm = M_ALD_MEM_GET_RM(xpc);
172 
173  // Check for hardware exception, for values
174  // see emit_mov_mem_reg and emit_mem.
175  if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
176  int32_t d = M_ALD_MEM_GET_REG(xpc);
177  int32_t disp = M_ALD_MEM_GET_DISP(xpc);
178 
179  // We use the exception type as load displacement.
180  trp->type = disp;
181  trp->value = es->intregs[d];
182  return true;
183  }
184 
185  // Default case is a normal NullPointerException.
186  else {
188  trp->value = 0;
189  return true;
190  }
191  }
192 
193  default:
194  return false;
195  }
196 }
197 
198 
199 /* md_patch_replacement_point **************************************************
200 
201  Patch the given replacement point.
202 
203 *******************************************************************************/
204 
205 #if defined(ENABLE_REPLACEMENT)
206 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
207 {
208  u2 mcode;
209 
210  if (revert) {
211  /* write saved machine code */
212  *(u2*)(pc) = *(u2*)(savedmcode);
213  }
214  else {
215  /* save the current machine code */
216  *(u2*)(savedmcode) = *(u2*)(pc);
217 
218  /* build the machine code for the patch */
219  mcode = 0x0b0f;
220 
221  /* write new machine code */
222  *(u2*)(pc) = mcode;
223  }
224 
225  /* XXX if required asm_cacheflush(pc,8); */
226 }
227 #endif /* defined(ENABLE_REPLACEMENT) */
228 
229 /*
230  * These are local overrides for various environment variables in Emacs.
231  * Please do not remove this and leave it at the end of the file, where
232  * Emacs will automagically detect them.
233  * ---------------------------------------------------------------------
234  * Local variables:
235  * mode: c++
236  * indent-tabs-mode: t
237  * c-basic-offset: 4
238  * tab-width: 4
239  * End:
240  * vim:noexpandtab:sw=4:ts=4:
241  */
#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
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
uint8_t u1
Definition: types.hpp:40
#define M_ALD_MEM_GET_DISP(p)
Definition: codegen.hpp:158
#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 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 vm_abort_disassemble(void *pc, int count, const char *text,...)
Definition: vm.cpp:2001
void md_init(void)
Definition: md.cpp:48
s4 asm_md_init(void)
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