1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2005 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.objectweb.asm.tree.analysis; 31 32 import java.util.List; 33 34 import org.objectweb.asm.Opcodes; 35 import org.objectweb.asm.Type; 36 import org.objectweb.asm.tree.AbstractInsnNode; 37 import org.objectweb.asm.tree.FieldInsnNode; 38 import org.objectweb.asm.tree.IntInsnNode; 39 import org.objectweb.asm.tree.LdcInsnNode; 40 import org.objectweb.asm.tree.MethodInsnNode; 41 import org.objectweb.asm.tree.MultiANewArrayInsnNode; 42 import org.objectweb.asm.tree.TypeInsnNode; 43 44 /** 45 * An {@link Interpreter} for {@link BasicValue} values. 46 * 47 * @author Eric Bruneton 48 * @author Bing Ran 49 */ 50 public class BasicInterpreter implements Opcodes, Interpreter { 51 newValue(final Type type)52 public Value newValue(final Type type) { 53 if (type == null) { 54 return BasicValue.UNINITIALIZED_VALUE; 55 } 56 switch (type.getSort()) { 57 case Type.VOID: 58 return null; 59 case Type.BOOLEAN: 60 case Type.CHAR: 61 case Type.BYTE: 62 case Type.SHORT: 63 case Type.INT: 64 return BasicValue.INT_VALUE; 65 case Type.FLOAT: 66 return BasicValue.FLOAT_VALUE; 67 case Type.LONG: 68 return BasicValue.LONG_VALUE; 69 case Type.DOUBLE: 70 return BasicValue.DOUBLE_VALUE; 71 case Type.ARRAY: 72 case Type.OBJECT: 73 return BasicValue.REFERENCE_VALUE; 74 default: 75 throw new RuntimeException("Internal error."); 76 } 77 } 78 newOperation(final AbstractInsnNode insn)79 public Value newOperation(final AbstractInsnNode insn) { 80 switch (insn.getOpcode()) { 81 case ACONST_NULL: 82 return newValue(Type.getType("Lnull;")); 83 case ICONST_M1: 84 case ICONST_0: 85 case ICONST_1: 86 case ICONST_2: 87 case ICONST_3: 88 case ICONST_4: 89 case ICONST_5: 90 return BasicValue.INT_VALUE; 91 case LCONST_0: 92 case LCONST_1: 93 return BasicValue.LONG_VALUE; 94 case FCONST_0: 95 case FCONST_1: 96 case FCONST_2: 97 return BasicValue.FLOAT_VALUE; 98 case DCONST_0: 99 case DCONST_1: 100 return BasicValue.DOUBLE_VALUE; 101 case BIPUSH: 102 case SIPUSH: 103 return BasicValue.INT_VALUE; 104 case LDC: 105 Object cst = ((LdcInsnNode) insn).cst; 106 if (cst instanceof Integer) { 107 return BasicValue.INT_VALUE; 108 } else if (cst instanceof Float) { 109 return BasicValue.FLOAT_VALUE; 110 } else if (cst instanceof Long) { 111 return BasicValue.LONG_VALUE; 112 } else if (cst instanceof Double) { 113 return BasicValue.DOUBLE_VALUE; 114 } else if (cst instanceof Type) { 115 return newValue(Type.getType("Ljava/lang/Class;")); 116 } else { 117 return newValue(Type.getType(cst.getClass())); 118 } 119 case JSR: 120 return BasicValue.RETURNADDRESS_VALUE; 121 case GETSTATIC: 122 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 123 case NEW: 124 return newValue(Type.getType("L" + ((TypeInsnNode) insn).desc 125 + ";")); 126 default: 127 throw new RuntimeException("Internal error."); 128 } 129 } 130 copyOperation(final AbstractInsnNode insn, final Value value)131 public Value copyOperation(final AbstractInsnNode insn, final Value value) 132 throws AnalyzerException 133 { 134 return value; 135 } 136 unaryOperation(final AbstractInsnNode insn, final Value value)137 public Value unaryOperation(final AbstractInsnNode insn, final Value value) 138 throws AnalyzerException 139 { 140 switch (insn.getOpcode()) { 141 case INEG: 142 case IINC: 143 case L2I: 144 case F2I: 145 case D2I: 146 case I2B: 147 case I2C: 148 case I2S: 149 return BasicValue.INT_VALUE; 150 case FNEG: 151 case I2F: 152 case L2F: 153 case D2F: 154 return BasicValue.FLOAT_VALUE; 155 case LNEG: 156 case I2L: 157 case F2L: 158 case D2L: 159 return BasicValue.LONG_VALUE; 160 case DNEG: 161 case I2D: 162 case L2D: 163 case F2D: 164 return BasicValue.DOUBLE_VALUE; 165 case IFEQ: 166 case IFNE: 167 case IFLT: 168 case IFGE: 169 case IFGT: 170 case IFLE: 171 case TABLESWITCH: 172 case LOOKUPSWITCH: 173 case IRETURN: 174 case LRETURN: 175 case FRETURN: 176 case DRETURN: 177 case ARETURN: 178 case PUTSTATIC: 179 return null; 180 case GETFIELD: 181 return newValue(Type.getType(((FieldInsnNode) insn).desc)); 182 case NEWARRAY: 183 switch (((IntInsnNode) insn).operand) { 184 case T_BOOLEAN: 185 return newValue(Type.getType("[Z")); 186 case T_CHAR: 187 return newValue(Type.getType("[C")); 188 case T_BYTE: 189 return newValue(Type.getType("[B")); 190 case T_SHORT: 191 return newValue(Type.getType("[S")); 192 case T_INT: 193 return newValue(Type.getType("[I")); 194 case T_FLOAT: 195 return newValue(Type.getType("[F")); 196 case T_DOUBLE: 197 return newValue(Type.getType("[D")); 198 case T_LONG: 199 return newValue(Type.getType("[J")); 200 default: 201 throw new AnalyzerException("Invalid array type"); 202 } 203 case ANEWARRAY: 204 String desc = ((TypeInsnNode) insn).desc; 205 if (desc.charAt(0) == '[') { 206 return newValue(Type.getType("[" + desc)); 207 } else { 208 return newValue(Type.getType("[L" + desc + ";")); 209 } 210 case ARRAYLENGTH: 211 return BasicValue.INT_VALUE; 212 case ATHROW: 213 return null; 214 case CHECKCAST: 215 desc = ((TypeInsnNode) insn).desc; 216 if (desc.charAt(0) == '[') { 217 return newValue(Type.getType(desc)); 218 } else { 219 return newValue(Type.getType("L" + desc + ";")); 220 } 221 case INSTANCEOF: 222 return BasicValue.INT_VALUE; 223 case MONITORENTER: 224 case MONITOREXIT: 225 case IFNULL: 226 case IFNONNULL: 227 return null; 228 default: 229 throw new RuntimeException("Internal error."); 230 } 231 } 232 binaryOperation( final AbstractInsnNode insn, final Value value1, final Value value2)233 public Value binaryOperation( 234 final AbstractInsnNode insn, 235 final Value value1, 236 final Value value2) throws AnalyzerException 237 { 238 switch (insn.getOpcode()) { 239 case IALOAD: 240 case BALOAD: 241 case CALOAD: 242 case SALOAD: 243 case IADD: 244 case ISUB: 245 case IMUL: 246 case IDIV: 247 case IREM: 248 case ISHL: 249 case ISHR: 250 case IUSHR: 251 case IAND: 252 case IOR: 253 case IXOR: 254 return BasicValue.INT_VALUE; 255 case FALOAD: 256 case FADD: 257 case FSUB: 258 case FMUL: 259 case FDIV: 260 case FREM: 261 return BasicValue.FLOAT_VALUE; 262 case LALOAD: 263 case LADD: 264 case LSUB: 265 case LMUL: 266 case LDIV: 267 case LREM: 268 case LSHL: 269 case LSHR: 270 case LUSHR: 271 case LAND: 272 case LOR: 273 case LXOR: 274 return BasicValue.LONG_VALUE; 275 case DALOAD: 276 case DADD: 277 case DSUB: 278 case DMUL: 279 case DDIV: 280 case DREM: 281 return BasicValue.DOUBLE_VALUE; 282 case AALOAD: 283 Type t = ((BasicValue) value1).getType(); 284 if (t != null && t.getSort() == Type.ARRAY) { 285 return newValue(t.getElementType()); 286 } else { 287 return BasicValue.REFERENCE_VALUE; 288 } 289 case LCMP: 290 case FCMPL: 291 case FCMPG: 292 case DCMPL: 293 case DCMPG: 294 return BasicValue.INT_VALUE; 295 case IF_ICMPEQ: 296 case IF_ICMPNE: 297 case IF_ICMPLT: 298 case IF_ICMPGE: 299 case IF_ICMPGT: 300 case IF_ICMPLE: 301 case IF_ACMPEQ: 302 case IF_ACMPNE: 303 case PUTFIELD: 304 return null; 305 default: 306 throw new RuntimeException("Internal error."); 307 } 308 } 309 ternaryOperation( final AbstractInsnNode insn, final Value value1, final Value value2, final Value value3)310 public Value ternaryOperation( 311 final AbstractInsnNode insn, 312 final Value value1, 313 final Value value2, 314 final Value value3) throws AnalyzerException 315 { 316 return null; 317 } 318 naryOperation(final AbstractInsnNode insn, final List values)319 public Value naryOperation(final AbstractInsnNode insn, final List values) 320 throws AnalyzerException 321 { 322 if (insn.getOpcode() == MULTIANEWARRAY) { 323 return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); 324 } else { 325 return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); 326 } 327 } 328 merge(final Value v, final Value w)329 public Value merge(final Value v, final Value w) { 330 if (!v.equals(w)) { 331 return BasicValue.UNINITIALIZED_VALUE; 332 } 333 return v; 334 } 335 } 336