1 package org.hansel; 2 3 import java.util.Iterator ; 4 import java.util.List ; 5 6 import org.hansel.stack.BinaryOperatorEntry; 7 import org.hansel.stack.HanselValue; 8 import org.hansel.stack.PrefixOpEntry; 9 import org.objectweb.asm.Opcodes; 10 import org.objectweb.asm.Type; 11 import org.objectweb.asm.tree.AbstractInsnNode; 12 import org.objectweb.asm.tree.FieldInsnNode; 13 import org.objectweb.asm.tree.IntInsnNode; 14 import org.objectweb.asm.tree.LdcInsnNode; 15 import org.objectweb.asm.tree.LocalVariableNode; 16 import org.objectweb.asm.tree.MethodInsnNode; 17 import org.objectweb.asm.tree.MultiANewArrayInsnNode; 18 import org.objectweb.asm.tree.TypeInsnNode; 19 import org.objectweb.asm.tree.VarInsnNode; 20 import org.objectweb.asm.tree.analysis.SourceInterpreter; 21 import org.objectweb.asm.tree.analysis.Value; 22 23 public final class HanselInterpreter extends SourceInterpreter { 24 private static final int PRECEDENCE_CAST = 1; 25 private static final int PRECEDENCE_UNARY_MINUS = 1; 26 private static final int PRECEDENCE_MUL = 2; 27 private static final int PRECEDENCE_ADD = 3; 28 private static final int PRECEDENCE_SHIFT = 4; 29 private static final int PRECEDENCE_INSTANCEOF = 5; 30 private static final int PRECEDENCE_COMPARE = 5; 31 private static final int PRECEDENCE_AND = 7; 32 private static final int PRECEDENCE_XOR = 8; 33 private static final int PRECEDENCE_OR = 9; 34 private List localVariables; 36 37 38 public HanselInterpreter(List localVariables) { 39 this.localVariables = localVariables; 41 } 43 44 public Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2) { 45 switch (insn.getOpcode()) { 46 case Opcodes.PUTFIELD: 47 case Opcodes.IF_ICMPEQ: 48 case Opcodes.IF_ICMPNE: 49 case Opcodes.IF_ICMPLT: 50 case Opcodes.IF_ICMPGE: 51 case Opcodes.IF_ICMPGT: 52 case Opcodes.IF_ICMPLE: 53 case Opcodes.IF_ACMPEQ: 54 case Opcodes.IF_ACMPNE: 55 return null; 56 case Opcodes.LALOAD: 57 case Opcodes.DALOAD: 58 return new HanselValue(value1 + "[" + value2 + "]", false, 2); 59 60 case Opcodes.IALOAD: 61 case Opcodes.FALOAD: 62 case Opcodes.AALOAD: 63 case Opcodes.CALOAD: 64 case Opcodes.SALOAD: 65 return new HanselValue(value1 + "[" + value2 + "]", false, 1); 66 case Opcodes.BALOAD: 67 return new HanselValue(value1 + "[" + value2 + "]", true, 1); 68 case Opcodes.IADD: 69 case Opcodes.LADD: 70 case Opcodes.FADD: 71 case Opcodes.DADD: 72 return new BinaryOperatorEntry("+", PRECEDENCE_ADD, value1, value2); 73 case Opcodes.ISUB: 74 case Opcodes.LSUB: 75 case Opcodes.FSUB: 76 case Opcodes.DSUB: 77 return new BinaryOperatorEntry("-", PRECEDENCE_ADD, value1, value2); 78 case Opcodes.IMUL: 79 case Opcodes.LMUL: 80 case Opcodes.FMUL: 81 case Opcodes.DMUL: 82 return new BinaryOperatorEntry("*", PRECEDENCE_MUL, value1, value2); 83 case Opcodes.IDIV: 84 case Opcodes.LDIV: 85 case Opcodes.FDIV: 86 case Opcodes.DDIV: 87 return new BinaryOperatorEntry("/", PRECEDENCE_MUL, value1, value2); 88 case Opcodes.IREM: 89 case Opcodes.LREM: 90 case Opcodes.FREM: 91 case Opcodes.DREM: 92 return new BinaryOperatorEntry("%", PRECEDENCE_MUL, value1, value2); 93 case Opcodes.ISHL: 94 case Opcodes.LSHL: 95 return new BinaryOperatorEntry("<<", PRECEDENCE_SHIFT, value1, value2); 96 case Opcodes.ISHR: 97 case Opcodes.LSHR: 98 case Opcodes.IUSHR: 99 case Opcodes.LUSHR: 100 return new BinaryOperatorEntry(">>", PRECEDENCE_SHIFT, value1, value2); 101 case Opcodes.IAND: 102 case Opcodes.LAND: 103 return new BinaryOperatorEntry("&", PRECEDENCE_AND, value1, value2); 104 case Opcodes.IOR: 105 case Opcodes.LOR: 106 return new BinaryOperatorEntry("|", PRECEDENCE_OR, value1, value2); 107 case Opcodes.IXOR: 108 case Opcodes.LXOR: 109 return new BinaryOperatorEntry("^", PRECEDENCE_XOR, value1, value2); 110 case Opcodes.LCMP: 111 case Opcodes.FCMPL: 112 case Opcodes.FCMPG: 113 case Opcodes.DCMPL: 114 case Opcodes.DCMPG: 115 return new BinaryOperatorEntry("<", PRECEDENCE_COMPARE, value1, value2, 1); 116 117 default: 118 throw failure(insn); 119 } 120 } 121 122 private HanselValue findLocalVar(int index, AbstractInsnNode insn) { 123 Iterator it = localVariables.iterator(); 124 126 while (it.hasNext()) { 127 LocalVariableNode lvn = (LocalVariableNode) it.next(); 128 129 if ((lvn.index == index) ) { 133 return new HanselValue(lvn.name, isBool(lvn.desc), getSize(lvn.desc)); 135 } 136 } 137 138 return new HanselValue("Unknown local: " + index, false, 1); 139 } 140 141 142 143 private int getSize(String desc) { 144 return Type.getType(desc).getSize(); 145 } 146 147 private boolean isBool(String desc) { 148 return isBool(Type.getType(desc)); 149 } 150 151 private boolean isBool(Type type) { 152 return type.equals(Type.BOOLEAN_TYPE); 153 } 154 155 public Value copyOperation(AbstractInsnNode insn, Value value) { 156 if (insn instanceof VarInsnNode) { 157 return findLocalVar(((VarInsnNode) insn).var, insn); 158 } 159 160 switch (insn.getOpcode()) { 161 case Opcodes.DUP: 162 case Opcodes.DUP_X1: 163 case Opcodes.DUP_X2: 164 case Opcodes.DUP2: 165 case Opcodes.DUP2_X1: 166 case Opcodes.DUP2_X2: 167 case Opcodes.SWAP: 168 return value; 169 170 case Opcodes.ISTORE: 171 case Opcodes.LSTORE: 172 case Opcodes.FSTORE: 173 case Opcodes.DSTORE: 174 case Opcodes.ASTORE: 175 return HanselValue.DONT_CARE; 176 default: throw failure(insn); 177 } 178 } 179 180 181 public Value merge(Value v, Value w) { 182 return v; 183 } 184 185 private HanselValue multiANewArray(MultiANewArrayInsnNode node, List values) { 186 String result = node.desc; 187 188 for (int i=0;i<values.size(); i++) { 189 result += "[" + values.get(i) + "]"; 190 } 191 192 return new HanselValue(result, false, 1); 193 } 194 195 private HanselValue invokeMethod(MethodInsnNode node, List values) { 196 String result = ""; 197 int start = 0; 198 199 if (node.getOpcode() != Opcodes.INVOKESTATIC) { 200 start = 1; 201 result = values.get(0) + "."; 202 } 203 204 result += node.name + "("; 205 for (int i=start; i<values.size(); i++) { 206 result += values.get(i); 207 if (i != values.size() - 1) { 208 result += ", "; 209 } 210 } 211 212 return new HanselValue(result + ")", isBool(Type.getReturnType(node.desc)), 213 Type.getReturnType(node.desc).getSize()); 214 } 215 216 217 public Value naryOperation(AbstractInsnNode insn, List values) { 218 219 switch (insn.getOpcode()) { 220 case Opcodes.INVOKESPECIAL: 221 case Opcodes.INVOKEVIRTUAL: 222 case Opcodes.INVOKEINTERFACE: 223 case Opcodes.INVOKESTATIC: 224 return invokeMethod((MethodInsnNode) insn, values); 225 case Opcodes.MULTIANEWARRAY: 226 return multiANewArray((MultiANewArrayInsnNode) insn, values); 227 228 229 default: 230 throw failure(insn); 231 } 232 } 233 234 private IllegalStateException failure(AbstractInsnNode insn) { 235 Thread.dumpStack(); 236 return new IllegalStateException ("Unknown instruction: " + insn.getOpcode() + " " + insn + " (Class: " + insn.getClass() + ")"); 237 } 238 239 public Value newOperation(AbstractInsnNode insn) { 240 switch (insn.getOpcode()) { 241 case Opcodes.ACONST_NULL: 242 return HanselValue.NULL; 243 case Opcodes.LCONST_0: return HanselValue.ZERO_2; 244 case Opcodes.LCONST_1: return HanselValue.ONE_2; 245 case Opcodes.FCONST_0: return HanselValue.ZERO_1; 246 case Opcodes.FCONST_1: return HanselValue.ONE_1; 247 case Opcodes.FCONST_2: return new HanselValue("2", false, 1); 248 case Opcodes.DCONST_0: return HanselValue.ZERO_2; 249 case Opcodes.DCONST_1: return HanselValue.ONE_1; 250 case Opcodes.ICONST_M1: return new HanselValue("-1", false,1); 251 case Opcodes.ICONST_0: return HanselValue.ZERO_1; 252 case Opcodes.ICONST_1: return HanselValue.ONE_1; 253 case Opcodes.ICONST_2: return new HanselValue("2", false, 1); 254 case Opcodes.ICONST_3: return new HanselValue("3", false, 1); 255 case Opcodes.ICONST_4: return new HanselValue("4", false, 1); 256 case Opcodes.ICONST_5: return new HanselValue("5", false, 1); 257 case Opcodes.BIPUSH: 258 case Opcodes.SIPUSH: 259 return new HanselValue(String.valueOf(((IntInsnNode) insn).operand), false, 1); 260 case Opcodes.LDC: 261 return formatLDC(((LdcInsnNode) insn).cst); 262 case Opcodes.GETSTATIC: 263 return new HanselValue(((FieldInsnNode) insn).name, isBool(((FieldInsnNode) insn).desc), 264 getSize((((FieldInsnNode) insn).desc))); 265 case Opcodes.JSR: 266 return HanselValue.DONT_CARE; 267 case Opcodes.NEW: 268 return new HanselValue("new " + ((TypeInsnNode) insn).desc + "()", false, 1); 269 default: 270 throw failure(insn); 271 } 272 } 273 274 private HanselValue formatLDC(Object cst) { 275 if (cst instanceof Type) { 276 Type t = (Type) cst; 277 if (t.getSort() == Type.OBJECT) { 278 String result = t.getClassName(); 279 if (result.indexOf('.') > -1) { 280 return new HanselValue(result.substring(result.lastIndexOf('.') + 1) + ".class", 281 false, 1); 282 } 283 } 284 } 285 286 if ((cst instanceof Double ) || (cst instanceof Long )) { 287 return new HanselValue(cst.toString(), false, 2); 288 } else if (cst instanceof String ) { 289 return new HanselValue("\"" + cst.toString() + "\"", false, 1); 290 } else { 291 return new HanselValue(cst.toString(), false, 1); 292 } 293 } 294 295 public Value newValue(Type type) { 296 return HanselValue.DONT_CARE; 297 } 298 299 public Value ternaryOperation(AbstractInsnNode insn, Value value1, Value value2, Value value3) { 300 switch (insn.getOpcode()) { 301 case Opcodes.AASTORE: 302 case Opcodes.IASTORE: 303 case Opcodes.LASTORE: 304 case Opcodes.FASTORE: 305 case Opcodes.DASTORE: 306 case Opcodes.BASTORE: 307 case Opcodes.CASTORE: 308 case Opcodes.SASTORE: 309 return HanselValue.DONT_CARE; 310 default: throw failure(insn); 311 } 312 } 313 314 public Value unaryOperation(AbstractInsnNode insn, Value value) { 315 switch (insn.getOpcode()) { 316 case Opcodes.ATHROW: 317 case Opcodes.MONITORENTER: 318 case Opcodes.MONITOREXIT: 319 case Opcodes.IFNULL: 320 case Opcodes.IFNONNULL: 321 case Opcodes.IFEQ: 322 case Opcodes.IFNE: 323 case Opcodes.IFLT: 324 case Opcodes.IFGE: 325 case Opcodes.IFGT: 326 case Opcodes.IFLE: 327 case Opcodes.TABLESWITCH: 328 case Opcodes.LOOKUPSWITCH: 329 case Opcodes.IRETURN: 330 case Opcodes.LRETURN: 331 case Opcodes.FRETURN: 332 case Opcodes.DRETURN: 333 case Opcodes.ARETURN: 334 case Opcodes.PUTSTATIC: 335 return null; 337 case Opcodes.IINC: 338 return HanselValue.DONT_CARE; 339 case Opcodes.INEG: 340 case Opcodes.LNEG: 341 case Opcodes.FNEG: 342 case Opcodes.DNEG: 343 return new PrefixOpEntry("-", PRECEDENCE_UNARY_MINUS, (HanselValue) value); 344 case Opcodes.I2L: 345 case Opcodes.F2L: 346 case Opcodes.D2L: 347 return new PrefixOpEntry("(long)", PRECEDENCE_CAST, (HanselValue) value, 2); 348 case Opcodes.I2F: 349 case Opcodes.L2F: 350 case Opcodes.D2F: 351 return new PrefixOpEntry("(float)", PRECEDENCE_CAST, (HanselValue) value, 1); 352 case Opcodes.I2D: 353 case Opcodes.L2D: 354 case Opcodes.F2D: 355 return new PrefixOpEntry("(double)", PRECEDENCE_CAST, (HanselValue) value, 2); 356 case Opcodes.L2I: 357 case Opcodes.F2I: 358 case Opcodes.D2I: 359 return new PrefixOpEntry("(int)", PRECEDENCE_CAST, (HanselValue) value, 1); 360 case Opcodes.I2B: 361 return new PrefixOpEntry("(boolean)", PRECEDENCE_CAST, (HanselValue) value, 1); 362 case Opcodes.I2C: 363 return new PrefixOpEntry("(char)", PRECEDENCE_CAST, (HanselValue) value, 1); 364 case Opcodes.I2S: 365 return new PrefixOpEntry("(short)", PRECEDENCE_CAST, (HanselValue) value, 1); 366 case Opcodes.INSTANCEOF: 367 return new BinaryOperatorEntry("instanceof", PRECEDENCE_INSTANCEOF, 368 (HanselValue) value, 369 new HanselValue(((TypeInsnNode) insn).desc, false, 1), 1); 370 case Opcodes.NEWARRAY: 371 return new HanselValue("new " + getType(((IntInsnNode) insn).operand) + "[" + value + "]", false, 1); 372 case Opcodes.ANEWARRAY: 373 return new HanselValue("new " + ((TypeInsnNode) insn).desc + "[" + value + "]", false, 1); 374 case Opcodes.ARRAYLENGTH: 375 return new HanselValue(value + ".length", false, 1); 376 case Opcodes.CHECKCAST: 377 return new PrefixOpEntry("("+ ((TypeInsnNode) insn).desc + ")", 378 PRECEDENCE_CAST, (HanselValue) value, 379 1); 380 case Opcodes.GETFIELD: 381 return new HanselValue("this." + ((FieldInsnNode) insn).name, isBool(((FieldInsnNode) insn).desc), 382 getSize(((FieldInsnNode) insn).desc)); 383 384 default: 385 throw failure(insn); 386 } 387 } 388 389 392 private String getType(int operand) { 393 switch (operand) { 394 case 4: return "boolean"; 395 case 5: return "char"; 396 case 6: return "float"; 397 case 7: return "double"; 398 case 8: return "byte"; 399 case 9: return "short"; 400 case 10: return "int"; 401 case 11: return "long"; 402 default: throw new IllegalArgumentException ("Unknown type of newarray: " + operand); 403 } 404 } 405 406 } 407 | Popular Tags |