CACAO
PatcherNew.cpp
Go to the documentation of this file.
1 /* src/vm/jit/Patcher.cpp - Patcher class
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 "vm/jit/PatcherNew.hpp"
27 #include "toolbox/logging.hpp"
28 
29 #include "vm/initialize.hpp"
30 #include "vm/jit/jit.hpp"
31 #include "vm/jit/emit-common.hpp" /* for emit_trap */
32 #include "codegen.hpp" /* for PATCHER_CALL_SIZE */
33 
34 #define DEBUG_NAME "Patcher"
35 namespace cacao{
36 
37 Patcher::Patcher() : done(false) {
38  LOG2("Patcher ctor" << nl);
39 }
40 
42  LOG2("Patcher dtor" << nl);
43 }
44 
45 const char* Patcher::get_name() const {
46  return "UnknownPatcher";
47 }
48 
50  // Display information about patcher.
51  OS << "\tpatcher";
52  OS << " type:" << get_name();
53  OS << " pc:0x" << (void*) get_mpc();
54  // Display machine code of patched position.
55 #if 0 && defined(ENABLE_DISASSEMBLER)
56  printf("\t\tcurrent -> ");
57  disassinstr((uint8_t*) pr.mpc);
58  printf("\t\tapplied -> ");
59  disassinstr((uint8_t*) &(pr.mcode));
60 #endif
61  return OS;
62 }
63 
65  codegendata *cd = jd->cd;
66 
67  /* Calculate the patch position where the original machine
68  code is located and the trap should be placed. */
69 
70  u1 *tmpmcodeptr = (u1 *) (cd->mcodebase + pr.mpc);
71 
72  /* Patch in the trap to call the signal handler (done at
73  compile time). */
74 
75  u1 *savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
76  cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
77 
78  uint32_t mcode = emit_trap(cd);
79 
80  cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
81 
82  /* Remember the original machine code which is patched
83  back in later (done at runtime). */
84 
85  pr.mcode = mcode;
86 }
87 
89  // Validate the instruction at the patching position is the same
90  // instruction as the patcher structure contains.
91  uint32_t mcode = *((uint32_t*) pr.mpc);
92 
93 #if PATCHER_CALL_SIZE == 4
94  if (mcode != pr.mcode) {
95 #elif PATCHER_CALL_SIZE == 2
96  if ((uint16_t) mcode != (uint16_t) pr.mcode) {
97 #else
98 #error Unknown PATCHER_CALL_SIZE
99 #endif
100  // The code differs.
101  return false;
102  }
103 
104  return true;
105 }
106 
107 /**
108  * patcher_function_list
109  *
110  * This is a list which maps patcher function pointers to the according
111  * names of the patcher functions. It is only usefull for debugging
112  * purposes.
113  *
114  */
115 
116 #if !defined(NDEBUG)
117 typedef struct patcher_function_list_t {
119  const char* name;
121 
123  { PATCHER_initialize_class, "initialize_class" },
124 #ifdef ENABLE_VERIFIER
125  { PATCHER_resolve_class, "resolve_class" },
126 #endif /* ENABLE_VERIFIER */
127  { PATCHER_resolve_classref_to_classinfo, "resolve_classref_to_classinfo"},
128  { PATCHER_resolve_classref_to_vftbl, "resolve_classref_to_vftbl"},
129  { PATCHER_resolve_classref_to_flags, "resolve_classref_to_flags"},
130  { PATCHER_resolve_native_function, "resolve_native_function" },
131  { PATCHER_invokestatic_special, "invokestatic_special" },
132  { PATCHER_invokevirtual, "invokevirtual" },
133  { PATCHER_invokeinterface, "invokeinterface" },
134  { PATCHER_breakpoint, "breakpoint" },
135  { PATCHER_checkcast_interface, "checkcast_interface" },
136  { PATCHER_instanceof_interface, "instanceof_interface" },
137  { PATCHER_get_putstatic, "get_putstatic" },
138  { PATCHER_get_putfield, "get_putfield" },
139  { NULL, "-UNKNOWN PATCHER FUNCTION-" }
140 };
141 #endif
142 
143 const char* LegacyPatcher::get_name() const {
144 #if !defined(NDEBUG)
145  // Lookup name in patcher function list.
147  for (l = patcher_function_list; l->patcher != NULL; l++)
148  if (l->patcher == pr.patcher)
149  break;
150  return l->name;
151 #else
152  return "UnknownLegacyPatcher(NoDebugBuild)";
153 #endif
154 }
155 
157  Patcher::print(OS);
158  // Display information about patcher.
159  #if PATCHER_CALL_SIZE == 4
160  OS << " mcode:" << (uint32_t) pr.mcode;
161  #elif PATCHER_CALL_SIZE == 2
162  OS << " mcode:" << (uint16_t) pr.mcode;
163  #else
164  # error Unknown PATCHER_CALL_SIZE
165  #endif
166  OS << " datap:" << (void*) pr.datap;
167  OS << " ref:0x" << (uintptr_t) pr.ref;
168  return OS;
169 }
170 
172  if (!(c->state & CLASS_INITIALIZED))
173  if (!initialize_class(c))
174  return false;
175  return true;
176 }
177 
178 /**
179  * @todo implement
180  */
182 }
183 /**
184  * @todo implement
185  */
187  return is_patched();
188 }
189 } // end namespace cacao
190 
191 /*
192  * These are local overrides for various environment variables in Emacs.
193  * Please do not remove this and leave it at the end of the file, where
194  * Emacs will automagically detect them.
195  * ---------------------------------------------------------------------
196  * Local variables:
197  * mode: c++
198  * indent-tabs-mode: t
199  * c-basic-offset: 4
200  * tab-width: 4
201  * End:
202  * vim:noexpandtab:sw=4:ts=4:
203  */
204 
#define PATCHER_resolve_classref_to_flags
functionptr patcher
#define PATCHER_invokeinterface
u1 * disassinstr(u1 *code)
Definition: disass.cpp:48
patcher_function_list
Definition: PatcherNew.cpp:117
virtual bool patch_impl()
This function performs the patching.
Definition: PatcherNew.cpp:171
#define PATCHER_resolve_classref_to_vftbl
virtual const char * get_name() const
print patcher information
Definition: PatcherNew.cpp:143
virtual OStream & print(OStream &OS) const
print patcher information
Definition: PatcherNew.cpp:156
#define PATCHER_CALL_SIZE
Definition: codegen.hpp:68
#define PATCHER_get_putfield
codegendata * cd
Definition: jit.hpp:129
#define PATCHER_resolve_class
uint8_t u1
Definition: types.hpp:40
#define PATCHER_breakpoint
virtual void emit()
Generates the code for the patcher traps.
Definition: PatcherNew.cpp:64
#define PATCHER_get_putstatic
virtual uintptr_t get_mpc() const =0
get the absolute position in code segment
void(* functionptr)(void)
Definition: global.hpp:39
virtual bool check_is_patched() const
Definition: PatcherNew.cpp:186
struct patcher_function_list_t patcher_function_list_t
patcher_function_list
#define PATCHER_instanceof_interface
virtual ~Patcher()
Definition: PatcherNew.cpp:41
#define PATCHER_resolve_native_function
Simple stream class for formatted output.
Definition: OStream.hpp:141
virtual OStream & print(OStream &OS) const
print patcher information
Definition: PatcherNew.cpp:49
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:563
#define LOG2(STMT)
Definition: logging.hpp:93
virtual const char * get_name() const
print patcher information
Definition: PatcherNew.cpp:45
bool initialize_class(classinfo *c)
Definition: initialize.cpp:110
OStream & OS
#define PATCHER_checkcast_interface
#define PATCHER_invokestatic_special
bool is_patched() const
Check already patched.
Definition: PatcherNew.hpp:93
#define PATCHER_invokevirtual
uintptr_t datap
uint32_t mcode
virtual bool check_is_patched() const
Check if the patcher is already patched.
Definition: PatcherNew.cpp:88
#define PATCHER_initialize_class
#define PATCHER_resolve_classref_to_classinfo
static patcher_function_list_t patcher_function_list[]
Definition: PatcherNew.cpp:122
uintptr_t mpc
Nl nl
Definition: OStream.cpp:56
#define printf(...)
Definition: ssa2.cpp:40