1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.microemu.app.classloader;
23
24 import java.util.HashMap;
25
26 import org.microemu.Injected;
27 import org.microemu.app.util.MIDletThread;
28 import org.microemu.app.util.MIDletTimer;
29 import org.objectweb.asm.Label;
30 import org.objectweb.asm.MethodAdapter;
31 import org.objectweb.asm.MethodVisitor;
32 import org.objectweb.asm.Opcodes;
33
34
35
36
37
38 public class ChangeCallsMethodVisitor extends MethodAdapter implements Opcodes {
39
40 private static final String INJECTED_CLASS = codeName(Injected.class);
41
42 static String NEW_SYSTEM_OUT_CLASS = INJECTED_CLASS;
43
44 static String NEW_SYSTEM_PROPERTIES_CLASS = INJECTED_CLASS;
45
46 static String NEW_RESOURCE_LOADER_CLASS = INJECTED_CLASS;
47
48 private HashMap catchInfo;
49
50 private InstrumentationConfig config;
51
52 private static class CatchInformation {
53
54 Label label;
55
56 String type;
57
58 public CatchInformation(String type) {
59 this.label = new Label();
60 this.type = type;
61 }
62 }
63
64 public ChangeCallsMethodVisitor(MethodVisitor mv, InstrumentationConfig config) {
65 super(mv);
66 this.config = config;
67 }
68
69 public static String codeName(Class klass) {
70 return klass.getName().replace('.', '/');
71 }
72
73 public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
74 switch (opcode) {
75 case GETSTATIC:
76 if ((name.equals("out")) && (owner.equals("java/lang/System"))) {
77
78
79 mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
80 return;
81 }
82 if ((name.equals("err")) && (owner.equals("java/lang/System"))) {
83
84
85 mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
86 return;
87 }
88 break;
89
90 }
91 mv.visitFieldInsn(opcode, owner, name, desc);
92 }
93
94 public void visitMethodInsn(int opcode, String owner, String name, String desc) {
95 switch (opcode) {
96 case INVOKESTATIC:
97
98 if ((name.equals("getProperty")) && (owner.equals("java/lang/System"))) {
99
100
101 mv.visitMethodInsn(opcode, NEW_SYSTEM_PROPERTIES_CLASS, name, desc);
102 return;
103 }
104 break;
105 case INVOKEVIRTUAL:
106 if ((name.equals("getResourceAsStream")) && (owner.equals("java/lang/Class"))) {
107
108
109
110 mv.visitMethodInsn(INVOKESTATIC, NEW_RESOURCE_LOADER_CLASS, name, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/io/InputStream;");
111 return;
112 } else if ((name.equals("printStackTrace")) && (owner.equals("java/lang/Throwable"))) {
113
114 mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, name, "(Ljava/lang/Throwable;)V");
115 return;
116 }
117 break;
118 case INVOKESPECIAL:
119 if ((config.isEnhanceThreadCreation()) && (name.equals("<init>"))) {
120 if (owner.equals("java/util/Timer")) {
121 owner = codeName(MIDletTimer.class);
122 } else if (owner.equals("java/lang/Thread")) {
123 owner = codeName(MIDletThread.class);
124 }
125 }
126 break;
127 }
128
129 mv.visitMethodInsn(opcode, owner, name, desc);
130 }
131
132 public void visitTypeInsn(final int opcode, String desc) {
133 if ((opcode == NEW) && (config.isEnhanceThreadCreation())) {
134 if ("java/util/Timer".equals(desc)) {
135 desc = codeName(MIDletTimer.class);
136 } else if ("java/lang/Thread".equals(desc)) {
137 desc = codeName(MIDletThread.class);
138 }
139 }
140 mv.visitTypeInsn(opcode, desc);
141 }
142
143 public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
144 if (config.isEnhanceCatchBlock() && type != null) {
145 if (catchInfo == null) {
146 catchInfo = new HashMap();
147 }
148 CatchInformation newHandler = (CatchInformation)catchInfo.get(handler);
149 if (newHandler == null) {
150 newHandler = new CatchInformation(type);
151 catchInfo.put(handler, newHandler);
152 }
153 mv.visitTryCatchBlock(start, end, newHandler.label, type);
154 } else {
155 mv.visitTryCatchBlock(start, end, handler, type);
156 }
157 }
158
159
160 public void visitLabel(Label label) {
161 if (config.isEnhanceCatchBlock() && catchInfo != null) {
162 CatchInformation newHandler = (CatchInformation)catchInfo.get(label);
163 if (newHandler != null) {
164 mv.visitLabel(newHandler.label);
165
166 mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, "handleCatchThrowable", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
167
168 mv.visitTypeInsn(CHECKCAST, newHandler.type);
169 }
170 }
171 mv.visitLabel(label);
172 }
173
174 }