1
2
3
4 package joeq.Class;
5
6 import java.util.Iterator;
7 import java.util.List;
8 import joeq.Main.jq;
9 import joeq.Memory.CodeAddress;
10 import joeq.Memory.StackAddress;
11 import joeq.Runtime.Debug;
12 import jwutil.util.Assert;
13
14 /***
15 * @author John Whaley <jwhaley@alum.mit.edu>
16 * @version $Id: jq_CompiledCode.java 1931 2004-09-22 22:17:47Z joewhaley $
17 */
18 public class jq_CompiledCode implements Comparable {
19
20 public static
21 public static
22
23 protected final CodeAddress entrypoint;
24 protected final jq_Method method;
25 protected final CodeAddress start;
26 protected final int length;
27 protected final jq_TryCatch[] handlers;
28 protected final jq_BytecodeMap bcm;
29 protected final Object
30 protected final int stackframesize;
31 protected final List code_reloc, data_reloc;
32
33 public jq_CompiledCode(jq_Method method,
34 CodeAddress start,
35 int length,
36 CodeAddress entrypoint,
37 jq_TryCatch[] handlers,
38 jq_BytecodeMap bcm,
39 Object
40 int stackframesize,
41 List code_reloc,
42 List data_reloc) {
43 this.method = method;
44 this.entrypoint = entrypoint;
45 this.start = start;
46 this.length = length;
47 this.handlers = handlers;
48 this.bcm = bcm;
49 this.ed = ed;
50 this.stackframesize = stackframesize;
51 this.code_reloc = code_reloc;
52 this.data_reloc = data_reloc;
53 }
54
55 public jq_Method getMethod() {
56 return method;
57 }
58
59 public CodeAddress getStart() {
60 return start;
61 }
62
63 public int getLength() {
64 return length;
65 }
66
67 public CodeAddress getEntrypoint() {
68 return entrypoint;
69 }
70
71 public int getStackFrameSize() {
72 return stackframesize;
73 }
74
75 public jq_TryCatch findCatchBlock(CodeAddress ip, jq_Class extype) {
76 int offset = ip.difference(start);
77 if (handlers == null) {
78 if (TRACE) Debug.writeln("no handlers in " + this);
79 return null;
80 }
81 for (int i = 0; i < handlers.length; ++i) {
82 jq_TryCatch tc = handlers[i];
83 if (TRACE) Debug.writeln("checking handler: " + tc);
84 if (tc.catches(offset, extype))
85 return tc;
86 if (TRACE) Debug.writeln("does not catch");
87 }
88 if (TRACE) Debug.writeln("no appropriate handler found in " + this);
89 return null;
90 }
91
92 public void deliverException(jq_TryCatch tc, StackAddress fp, Throwable x) {
93 Assert._assert(ed != null);
94 CodeAddress entry = (CodeAddress) start.offset(tc.getHandlerEntry());
95 _delegate.deliverToStackFrame(ed, this, x, tc, entry, fp);
96 }
97
98 public Object getThisPointer(CodeAddress ip, StackAddress fp) {
99 Assert._assert(ed != null);
100 return _delegate.getThisPointer(ed, this, ip, fp);
101 }
102
103 public int getBytecodeIndex(CodeAddress ip) {
104 if (bcm == null) return -1;
105 return bcm.getBytecodeIndex(ip.difference(start));
106 }
107
108 /*** Rewrite the entrypoint to branch to the given compiled code. */
109 public void redirect(jq_CompiledCode that) {
110 CodeAddress newEntrypoint = that.getEntrypoint();
111 if (TRACE_REDIRECT) Debug.writeln("redirecting " + this + " to point to " + that);
112 if (entrypoint.difference(start.offset(5)) >= 0) {
113 if (TRACE_REDIRECT) Debug.writeln("redirecting via trampoline");
114
115 Assert._assert(entrypoint.peek1() == newEntrypoint.peek1());
116
117 entrypoint.offset(-4).poke4(newEntrypoint.difference(entrypoint) + 1);
118
119 entrypoint.offset(-5).poke1((byte) 0xE9);
120
121 entrypoint.offset(1).poke2((short) 0xF8EB);
122 } else {
123 if (TRACE_REDIRECT) Debug.writeln("redirecting by rewriting targets");
124 Iterator it = _delegate.getCompiledMethods();
125 while (it.hasNext()) {
126 jq_CompiledCode cc = (jq_CompiledCode) it.next();
127 cc.patchDirectBindCalls(this.method, that);
128 }
129 }
130 }
131
132 public String toString() {
133 return method + " address: (" + start.stringRep() + "-" + start.offset(length).stringRep() + ")";
134 }
135
136 public boolean contains(CodeAddress address) {
137 return address.difference(start) >= 0 && address.difference(start.offset(length)) < 0;
138 }
139
140 static interface Delegate {
141 void patchDirectBindCalls(Iterator i);
142 void patchDirectBindCalls(Iterator i, jq_Method method, jq_CompiledCode cc);
143 Iterator getCompiledMethods();
144 void deliverToStackFrame(Object ed, jq_CompiledCode t, Throwable x, jq_TryCatch tc, CodeAddress entry, StackAddress fp);
145 Object getThisPointer(Object ed, jq_CompiledCode t, CodeAddress ip, StackAddress fp);
146 }
147
148 private static Delegate _delegate;
149
150 public void patchDirectBindCalls() {
151 Assert._assert(jq.RunningNative);
152 if (code_reloc != null) {
153 Iterator i = code_reloc.iterator();
154 _delegate.patchDirectBindCalls(i);
155 }
156 }
157
158 public void patchDirectBindCalls(jq_Method method, jq_CompiledCode cc) {
159 Assert._assert(jq.RunningNative);
160 if (code_reloc != null) {
161 Iterator i = code_reloc.iterator();
162 _delegate.patchDirectBindCalls(i, method, cc);
163 }
164 }
165
166 public int compareTo(jq_CompiledCode that) {
167 if (this == that) return 0;
168 if (this.start.difference(that.start) < 0) return -1;
169 if (this.start.difference(that.start.offset(that.length)) < 0) {
170 Assert.UNREACHABLE(this + " overlaps " + that);
171 }
172 return 1;
173 }
174
175 public int compareTo(java.lang.Object o) {
176 if (o instanceof jq_CompiledCode)
177 return compareTo((jq_CompiledCode) o);
178 else
179 return -((Comparable)o).compareTo(this);
180 }
181
182 public boolean equals(Object o) {
183 if (o instanceof jq_CompiledCode)
184 return this == o;
185 else
186 return o.equals(this);
187 }
188
189 /***
190 * NOTE that this violates the contract of hashCode when comparing against InstructionPointer objects!
191 */
192 public int hashCode() {
193 return super.hashCode();
194 }
195
196 public static final jq_InstanceField _entrypoint;
197
198 static {
199 jq_Class k = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Class/jq_CompiledCode;");
200 _entrypoint = k.getOrCreateInstanceField("entrypoint", "Ljoeq/Memory/CodeAddress;");
201
202 _delegate = null;
203 boolean nullVM = jq.nullVM;
204 if (!nullVM) {
205 _delegate = attemptDelegate("joeq.Class.Delegates$CompiledCode");
206 }
207 if (_delegate == null) {
208 _delegate = new NullDelegates.CompiledCode();
209 }
210 }
211
212 private static Delegate attemptDelegate(String s) {
213 String type = "compiled code delegate";
214 try {
215 Class c = Class.forName(s);
216 return (Delegate)c.newInstance();
217 } catch (java.lang.ClassNotFoundException x) {
218 System.err.println("Cannot find "+type+" "+s+": "+x);
219 } catch (java.lang.InstantiationException x) {
220 System.err.println("Cannot instantiate "+type+" "+s+": "+x);
221 } catch (java.lang.IllegalAccessException x) {
222 System.err.println("Cannot access "+type+" "+s+": "+x);
223 }
224 return null;
225 }
226 }