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