Line data Source code
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 142524 : Patcher::Patcher() : done(false) {
38 : LOG2("Patcher ctor" << nl);
39 142524 : }
40 :
41 0 : Patcher::~Patcher() {
42 : LOG2("Patcher dtor" << nl);
43 0 : }
44 :
45 0 : const char* Patcher::get_name() const {
46 0 : return "UnknownPatcher";
47 : }
48 :
49 0 : OStream& Patcher::print(OStream &OS) const {
50 : // Display information about patcher.
51 0 : OS << "\tpatcher";
52 0 : OS << " type:" << get_name();
53 0 : 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 0 : return OS;
62 : }
63 :
64 142524 : void LegacyPatcher::emit() {
65 142524 : 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 142524 : 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 142524 : u1 *savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
76 142524 : cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
77 :
78 142524 : uint32_t mcode = emit_trap(cd);
79 :
80 142524 : 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 142524 : pr.mcode = mcode;
86 142524 : }
87 :
88 1 : bool LegacyPatcher::check_is_patched() const {
89 : // Validate the instruction at the patching position is the same
90 : // instruction as the patcher structure contains.
91 1 : 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 1 : if ((uint16_t) mcode != (uint16_t) pr.mcode) {
97 : #else
98 : #error Unknown PATCHER_CALL_SIZE
99 : #endif
100 : // The code differs.
101 0 : return false;
102 : }
103 :
104 1 : 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 {
118 : functionptr patcher;
119 : const char* name;
120 : } patcher_function_list_t;
121 :
122 : static patcher_function_list_t patcher_function_list[] = {
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 0 : const char* LegacyPatcher::get_name() const {
144 : #if !defined(NDEBUG)
145 : // Lookup name in patcher function list.
146 : patcher_function_list_t* l;
147 0 : for (l = patcher_function_list; l->patcher != NULL; l++)
148 0 : if (l->patcher == pr.patcher)
149 0 : break;
150 0 : return l->name;
151 : #else
152 : return "UnknownLegacyPatcher(NoDebugBuild)";
153 : #endif
154 : }
155 :
156 0 : OStream& LegacyPatcher::print(OStream &OS) const {
157 0 : 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 0 : OS << " mcode:" << (uint16_t) pr.mcode;
163 : #else
164 : # error Unknown PATCHER_CALL_SIZE
165 : #endif
166 0 : OS << " datap:" << (void*) pr.datap;
167 0 : OS << " ref:0x" << (uintptr_t) pr.ref;
168 0 : return OS;
169 : }
170 :
171 0 : bool InitializeClassPatcher::patch_impl() {
172 0 : if (!(c->state & CLASS_INITIALIZED))
173 0 : if (!initialize_class(c))
174 0 : return false;
175 0 : return true;
176 : }
177 :
178 : /**
179 : * @todo implement
180 : */
181 0 : void InitializeClassPatcher::emit() {
182 0 : }
183 : /**
184 : * @todo implement
185 : */
186 0 : bool InitializeClassPatcher::check_is_patched() const {
187 0 : 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 :
|