1
2
3
4 package joeq.Compiler.Reference.x86;
5
6 import joeq.Class.PrimordialClassLoader;
7 import joeq.Class.jq_Class;
8 import joeq.Class.jq_InstanceField;
9 import joeq.Class.jq_InstanceMethod;
10 import joeq.Class.jq_Method;
11 import joeq.Class.jq_Reference;
12 import joeq.Class.jq_StaticField;
13 import joeq.Class.jq_StaticMethod;
14 import joeq.Memory.Address;
15 import joeq.Memory.CodeAddress;
16 import joeq.Memory.HeapAddress;
17 import joeq.Memory.StackAddress;
18 import joeq.Runtime.SystemInterface;
19 import joeq.Runtime.Unsafe;
20 import jwutil.util.Assert;
21
22 /***
23 * @author John Whaley <jwhaley@alum.mit.edu>
24 * @version $Id: x86ReferenceLinker.java 1941 2004-09-30 03:37:06Z joewhaley $
25 */
26 public abstract class x86ReferenceLinker {
27
28 public static
29
30 static void patchCaller(jq_Method m, CodeAddress retloc) {
31 if (retloc.offset(-6).peek2() == (short)0xE890) {
32
33 retloc.offset(-4).poke4(m.getDefaultCompiledVersion().getEntrypoint().difference(retloc));
34 }
35 if (!m.isStatic() && ((jq_InstanceMethod)m).isVirtual()) {
36 ((Address[])m.getDeclaringClass().getVTable())[((jq_InstanceMethod)m).getOffset()>>2] = m.getDefaultCompiledVersion().getEntrypoint();
37 }
38 }
39
40 static void getstatic4(jq_StaticField f) {
41 f = f.resolve1();
42 jq_Class k = f.getDeclaringClass();
43 k.cls_initialize();
44 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
45 if (TRACE) SystemInterface.debugwriteln("backpatching getstatic4 "+f+" ip: "+retloc.stringRep());
46 int patchsize = x86ReferenceCompiler.patch_getstatic4(retloc, f);
47
48 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
49 }
50 static void getstatic8(jq_StaticField f) {
51 f = f.resolve1();
52 jq_Class k = f.getDeclaringClass();
53 k.cls_initialize();
54 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
55 if (TRACE) SystemInterface.debugwriteln("backpatching getstatic8 "+f+" ip: "+retloc.stringRep());
56 int patchsize = x86ReferenceCompiler.patch_getstatic8(retloc, f);
57
58 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
59 }
60 static void putstatic4(jq_StaticField f) {
61 f = f.resolve1();
62 jq_Class k = f.getDeclaringClass();
63 k.cls_initialize();
64 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
65 if (TRACE) SystemInterface.debugwriteln("backpatching putstatic4 "+f+" ip: "+retloc.stringRep());
66 int patchsize = x86ReferenceCompiler.patch_putstatic4(retloc, f);
67
68 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
69 }
70 static void putstatic8(jq_StaticField f) {
71 f = f.resolve1();
72 jq_Class k = f.getDeclaringClass();
73 k.cls_initialize();
74 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
75 if (TRACE) SystemInterface.debugwriteln("backpatching putstatic8 "+f+" ip: "+retloc.stringRep());
76 int patchsize = x86ReferenceCompiler.patch_putstatic8(retloc, f);
77
78 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
79 }
80 static void getfield1(jq_InstanceField f) {
81 f = f.resolve1();
82 jq_Class k = f.getDeclaringClass();
83 Assert._assert(k.isClsInitialized());
84 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
85 if (TRACE) SystemInterface.debugwriteln("backpatching getfield1 "+f+" ip: "+retloc.stringRep());
86 int patchsize = x86ReferenceCompiler.patch_getfield1(retloc, f);
87
88 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
89 }
90 static void cgetfield(jq_InstanceField f) {
91 f = f.resolve1();
92 jq_Class k = f.getDeclaringClass();
93 Assert._assert(k.isClsInitialized());
94 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
95 if (TRACE) SystemInterface.debugwriteln("backpatching cgetfield "+f+" ip: "+retloc.stringRep());
96 int patchsize = x86ReferenceCompiler.patch_cgetfield(retloc, f);
97
98 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
99 }
100 static void sgetfield(jq_InstanceField f) {
101 f = f.resolve1();
102 jq_Class k = f.getDeclaringClass();
103 Assert._assert(k.isClsInitialized());
104 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
105 if (TRACE) SystemInterface.debugwriteln("backpatching sgetfield "+f+" ip: "+retloc.stringRep());
106 int patchsize = x86ReferenceCompiler.patch_sgetfield(retloc, f);
107
108 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
109 }
110 static void getfield4(jq_InstanceField f) {
111 f = f.resolve1();
112 jq_Class k = f.getDeclaringClass();
113 Assert._assert(k.isClsInitialized());
114 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
115 if (TRACE) SystemInterface.debugwriteln("backpatching getfield4 "+f+" ip: "+retloc.stringRep());
116 int patchsize = x86ReferenceCompiler.patch_getfield4(retloc, f);
117
118 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
119 }
120 static void getfield8(jq_InstanceField f) {
121 f = f.resolve1();
122 jq_Class k = f.getDeclaringClass();
123 Assert._assert(k.isClsInitialized());
124 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
125 if (TRACE) SystemInterface.debugwriteln("backpatching getfield8 "+f+" ip: "+retloc.stringRep());
126 int patchsize = x86ReferenceCompiler.patch_getfield8(retloc, f);
127
128 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
129 }
130 static void putfield1(jq_InstanceField f) {
131 f = f.resolve1();
132 jq_Class k = f.getDeclaringClass();
133 Assert._assert(k.isClsInitialized());
134 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
135 if (TRACE) SystemInterface.debugwriteln("backpatching putfield1 "+f+" ip: "+retloc.stringRep());
136 int patchsize = x86ReferenceCompiler.patch_putfield1(retloc, f);
137
138 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
139 }
140 static void putfield2(jq_InstanceField f) {
141 f = f.resolve1();
142 jq_Class k = f.getDeclaringClass();
143 Assert._assert(k.isClsInitialized());
144 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
145 if (TRACE) SystemInterface.debugwriteln("backpatching putfield2 "+f+" ip: "+retloc.stringRep());
146 int patchsize = x86ReferenceCompiler.patch_putfield2(retloc, f);
147
148 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
149 }
150 static void putfield4(jq_InstanceField f) {
151 f = f.resolve1();
152 jq_Class k = f.getDeclaringClass();
153 Assert._assert(k.isClsInitialized());
154 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
155 if (TRACE) SystemInterface.debugwriteln("backpatching putfield4 "+f+" ip: "+retloc.stringRep());
156 int patchsize = x86ReferenceCompiler.patch_putfield4(retloc, f);
157
158 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
159 }
160 static void putfield8(jq_InstanceField f) {
161 f = f.resolve1();
162 jq_Class k = f.getDeclaringClass();
163 Assert._assert(k.isClsInitialized());
164 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
165 if (TRACE) SystemInterface.debugwriteln("backpatching putfield8 "+f+" ip: "+retloc.stringRep());
166 int patchsize = x86ReferenceCompiler.patch_putfield8(retloc, f);
167
168 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
169 }
170 static void invokevirtual(jq_InstanceMethod f) {
171 f = f.resolve1();
172 jq_Class k = f.getDeclaringClass();
173 Assert._assert(k.isClsInitialized());
174 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
175 if (TRACE) SystemInterface.debugwriteln("backpatching invokevirtual "+f+" ip: "+retloc.stringRep());
176 int patchsize = x86ReferenceCompiler.patch_invokevirtual(retloc, f);
177
178 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
179 }
180 static void invokestatic(jq_Method f) {
181 f = (jq_Method)f.resolve();
182 jq_Class k = f.getDeclaringClass();
183 k.cls_initialize();
184 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
185 if (TRACE) SystemInterface.debugwriteln("backpatching invokestatic "+f+" ip: "+retloc.stringRep());
186 int patchsize = x86ReferenceCompiler.patch_invokestatic(retloc, f);
187
188 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
189 }
190 static void invokespecial(jq_InstanceMethod f) {
191 f = f.resolve1();
192 jq_Class k = f.getDeclaringClass();
193 k.cls_initialize();
194 f = jq_Class.getInvokespecialTarget(k, f);
195 CodeAddress retloc = (CodeAddress) StackAddress.getBasePointer().offset(4).peek();
196 if (TRACE) SystemInterface.debugwriteln("backpatching invokespecial "+f+" ip: "+retloc.stringRep());
197
198 int patchsize = x86ReferenceCompiler.patch_invokestatic(retloc, f);
199
200 StackAddress.getBasePointer().offset(4).poke(retloc.offset(-patchsize));
201 }
202 static long invokeinterface(jq_InstanceMethod f) throws Throwable {
203 f = f.resolve1();
204 int n_paramwords = f.getParamWords();
205 StackAddress obj_location = (StackAddress) StackAddress.getBasePointer().offset((n_paramwords+2)<<2);
206 Object o = ((HeapAddress) obj_location.peek()).asObject();
207 jq_Reference t = jq_Reference.getTypeOf(o);
208 if (!t.implementsInterface(f.getDeclaringClass()))
209 throw new IncompatibleClassChangeError(t+" does not implement interface "+f.getDeclaringClass());
210 jq_InstanceMethod m = t.getVirtualMethod(f.getNameAndDesc());
211 if (m == null)
212 throw new AbstractMethodError();
213
214 jq_Class k = m.getDeclaringClass();
215 k.cls_initialize();
216 for (int i=0; i<n_paramwords; ++i) {
217 int v = StackAddress.getBasePointer().offset((n_paramwords-i+2)<<2).peek4();
218 Unsafe.pushArg(v);
219 }
220 return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
221 }
222
223 public static final jq_Class _class;
224 public static final jq_StaticMethod _getstatic4;
225 public static final jq_StaticMethod _getstatic8;
226 public static final jq_StaticMethod _putstatic4;
227 public static final jq_StaticMethod _putstatic8;
228 public static final jq_StaticMethod _getfield1;
229 public static final jq_StaticMethod _cgetfield;
230 public static final jq_StaticMethod _sgetfield;
231 public static final jq_StaticMethod _getfield4;
232 public static final jq_StaticMethod _getfield8;
233 public static final jq_StaticMethod _putfield1;
234 public static final jq_StaticMethod _putfield2;
235 public static final jq_StaticMethod _putfield4;
236 public static final jq_StaticMethod _putfield8;
237 public static final jq_StaticMethod _invokevirtual;
238 public static final jq_StaticMethod _invokestatic;
239 public static final jq_StaticMethod _invokespecial;
240 public static final jq_StaticMethod _invokeinterface;
241 static {
242 _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Compiler/Reference/x86/x86ReferenceLinker;");
243 _getstatic4 = _class.getOrCreateStaticMethod("getstatic4", "(Ljoeq/Class/jq_StaticField;)V");
244 _getstatic8 = _class.getOrCreateStaticMethod("getstatic8", "(Ljoeq/Class/jq_StaticField;)V");
245 _putstatic4 = _class.getOrCreateStaticMethod("putstatic4", "(Ljoeq/Class/jq_StaticField;)V");
246 _putstatic8 = _class.getOrCreateStaticMethod("putstatic8", "(Ljoeq/Class/jq_StaticField;)V");
247 _getfield1 = _class.getOrCreateStaticMethod("getfield1", "(Ljoeq/Class/jq_InstanceField;)V");
248 _sgetfield = _class.getOrCreateStaticMethod("sgetfield", "(Ljoeq/Class/jq_InstanceField;)V");
249 _cgetfield = _class.getOrCreateStaticMethod("cgetfield", "(Ljoeq/Class/jq_InstanceField;)V");
250 _getfield4 = _class.getOrCreateStaticMethod("getfield4", "(Ljoeq/Class/jq_InstanceField;)V");
251 _getfield8 = _class.getOrCreateStaticMethod("getfield8", "(Ljoeq/Class/jq_InstanceField;)V");
252 _putfield1 = _class.getOrCreateStaticMethod("putfield1", "(Ljoeq/Class/jq_InstanceField;)V");
253 _putfield2 = _class.getOrCreateStaticMethod("putfield2", "(Ljoeq/Class/jq_InstanceField;)V");
254 _putfield4 = _class.getOrCreateStaticMethod("putfield4", "(Ljoeq/Class/jq_InstanceField;)V");
255 _putfield8 = _class.getOrCreateStaticMethod("putfield8", "(Ljoeq/Class/jq_InstanceField;)V");
256 _invokevirtual = _class.getOrCreateStaticMethod("invokevirtual", "(Ljoeq/Class/jq_InstanceMethod;)V");
257 _invokestatic = _class.getOrCreateStaticMethod("invokestatic", "(Ljoeq/Class/jq_Method;)V");
258 _invokespecial = _class.getOrCreateStaticMethod("invokespecial", "(Ljoeq/Class/jq_InstanceMethod;)V");
259 _invokeinterface = _class.getOrCreateStaticMethod("invokeinterface", "(Ljoeq/Class/jq_InstanceMethod;)J");
260 }
261 }