1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import edu.umd.cs.findbugs.SystemProperties; 23 24 31 public class BytecodeScanner implements org.apache.bcel.Constants { 32 private static final boolean DEBUG = SystemProperties.getBoolean("bs.debug"); 33 34 37 public interface Callback { 38 44 public void handleInstruction(int opcode, int index); 45 } 46 47 53 private static short unsignedValueOf(byte value) { 54 short result; 55 if ((value & 0x80) != 0) { 56 result = (short) (value & 0x7F); 57 result |= 0x80; 58 } else { 59 result = (short) value; 60 } 61 return result; 62 } 63 64 70 private static int extractInt(byte[] arr, int offset) { 71 return ((arr[offset] & 0xFF) << 24) | 72 ((arr[offset + 1] & 0xFF) << 16) | 73 ((arr[offset + 2] & 0xFF) << 8) | 74 (arr[offset + 3] & 0xFF); 75 } 76 77 private static final int PAD[] = {0, 3, 2, 1}; 78 79 85 public void scan(byte[] instructionList, Callback callback) { 86 87 boolean wide = false; 88 89 for (int index = 0; index < instructionList.length;) { 90 short opcode = unsignedValueOf(instructionList[index]); 91 callback.handleInstruction(opcode, index); 92 93 if (DEBUG) System.out.println(index + ": " + OPCODE_NAMES[opcode]); 94 95 switch (opcode) { 96 97 case NOP: 99 case ACONST_NULL: 100 case ICONST_M1: 101 case ICONST_0: 102 case ICONST_1: 103 case ICONST_2: 104 case ICONST_3: 105 case ICONST_4: 106 case ICONST_5: 107 case LCONST_0: 108 case LCONST_1: 109 case FCONST_0: 110 case FCONST_1: 111 case FCONST_2: 112 case DCONST_0: 113 case DCONST_1: 114 case ILOAD_0: 115 case ILOAD_1: 116 case ILOAD_2: 117 case ILOAD_3: 118 case LLOAD_0: 119 case LLOAD_1: 120 case LLOAD_2: 121 case LLOAD_3: 122 case FLOAD_0: 123 case FLOAD_1: 124 case FLOAD_2: 125 case FLOAD_3: 126 case DLOAD_0: 127 case DLOAD_1: 128 case DLOAD_2: 129 case DLOAD_3: 130 case ALOAD_0: 131 case ALOAD_1: 132 case ALOAD_2: 133 case ALOAD_3: 134 case IALOAD: 135 case LALOAD: 136 case FALOAD: 137 case DALOAD: 138 case AALOAD: 139 case BALOAD: 140 case CALOAD: 141 case SALOAD: 142 case ISTORE_0: 143 case ISTORE_1: 144 case ISTORE_2: 145 case ISTORE_3: 146 case LSTORE_0: 147 case LSTORE_1: 148 case LSTORE_2: 149 case LSTORE_3: 150 case FSTORE_0: 151 case FSTORE_1: 152 case FSTORE_2: 153 case FSTORE_3: 154 case DSTORE_0: 155 case DSTORE_1: 156 case DSTORE_2: 157 case DSTORE_3: 158 case ASTORE_0: 159 case ASTORE_1: 160 case ASTORE_2: 161 case ASTORE_3: 162 case IASTORE: 163 case LASTORE: 164 case FASTORE: 165 case DASTORE: 166 case AASTORE: 167 case BASTORE: 168 case CASTORE: 169 case SASTORE: 170 case POP: 171 case POP2: 172 case DUP: 173 case DUP_X1: 174 case DUP_X2: 175 case DUP2: 176 case DUP2_X1: 177 case DUP2_X2: 178 case SWAP: 179 case IADD: 180 case LADD: 181 case FADD: 182 case DADD: 183 case ISUB: 184 case LSUB: 185 case FSUB: 186 case DSUB: 187 case IMUL: 188 case LMUL: 189 case FMUL: 190 case DMUL: 191 case IDIV: 192 case LDIV: 193 case FDIV: 194 case DDIV: 195 case IREM: 196 case LREM: 197 case FREM: 198 case DREM: 199 case INEG: 200 case LNEG: 201 case FNEG: 202 case DNEG: 203 case ISHL: 204 case LSHL: 205 case ISHR: 206 case LSHR: 207 case IUSHR: 208 case LUSHR: 209 case IAND: 210 case LAND: 211 case IOR: 212 case LOR: 213 case IXOR: 214 case LXOR: 215 case I2L: 216 case I2F: 217 case I2D: 218 case L2I: 219 case L2F: 220 case L2D: 221 case F2I: 222 case F2L: 223 case F2D: 224 case D2I: 225 case D2L: 226 case D2F: 227 case I2B: 228 case I2C: 229 case I2S: 230 case LCMP: 231 case FCMPL: 232 case FCMPG: 233 case DCMPL: 234 case DCMPG: 235 case IRETURN: 236 case LRETURN: 237 case FRETURN: 238 case DRETURN: 239 case ARETURN: 240 case RETURN: 241 case ARRAYLENGTH: 242 case ATHROW: 243 case MONITORENTER: 244 case MONITOREXIT: 245 ++index; 246 break; 247 248 case BIPUSH: 250 case LDC: 251 case NEWARRAY: 252 index += 2; 253 break; 254 255 case ILOAD: 257 case LLOAD: 258 case FLOAD: 259 case DLOAD: 260 case ALOAD: 261 case ISTORE: 262 case LSTORE: 263 case FSTORE: 264 case DSTORE: 265 case ASTORE: 266 case RET: 267 if (wide) { 268 index += 3; 270 wide = false; 271 } else { 272 index += 2; 274 } 275 break; 276 277 case IINC: 279 if (wide) { 280 index += 5; 282 wide = false; 283 } else { 284 index += 3; 286 } 287 break; 288 289 case SIPUSH: 291 case LDC_W: 292 case LDC2_W: 293 case IFEQ: 294 case IFNE: 295 case IFLT: 296 case IFGE: 297 case IFGT: 298 case IFLE: 299 case IF_ICMPEQ: 300 case IF_ICMPNE: 301 case IF_ICMPLT: 302 case IF_ICMPGE: 303 case IF_ICMPGT: 304 case IF_ICMPLE: 305 case IF_ACMPEQ: 306 case IF_ACMPNE: 307 case GOTO: 308 case JSR: 309 case GETSTATIC: 310 case PUTSTATIC: 311 case GETFIELD: 312 case PUTFIELD: 313 case INVOKEVIRTUAL: 314 case INVOKESPECIAL: 315 case INVOKESTATIC: 316 case NEW: 317 case ANEWARRAY: 318 case CHECKCAST: 319 case INSTANCEOF: 320 case IFNULL: 321 case IFNONNULL: 322 index += 3; 323 break; 324 325 case MULTIANEWARRAY: 327 index += 4; 328 break; 329 330 case INVOKEINTERFACE: 332 case GOTO_W: 333 case JSR_W: 334 index += 5; 335 break; 336 337 case TABLESWITCH: 339 { 340 int offset = index + 1; offset += PAD[offset & 3]; 343 assert (offset & 3) == 0; 344 345 347 int low = extractInt(instructionList, offset + 4); 349 int high = extractInt(instructionList, offset + 8); 350 int tableSize = (high - low) + 1; 351 if (DEBUG) System.out.println("tableswitch: low=" + low + ", high=" + high + ", tableSize=" + tableSize); 352 353 index = offset + 12 + (tableSize * 4); 355 } 356 break; 357 358 case LOOKUPSWITCH: 360 { 361 int offset = index + 1; offset += PAD[offset & 3]; 364 assert (offset & 3) == 0; 365 366 368 int numPairs = extractInt(instructionList, offset + 4); 370 if (DEBUG) System.out.println("lookupswitch: numPairs=" + numPairs); 371 372 index = offset + 8 + (numPairs * 8); 374 } 375 break; 376 377 case WIDE: 379 wide = true; 380 ++index; 381 break; 382 383 default: 384 throw new IllegalArgumentException ("Bad opcode " + opcode + " at offset " + index); 385 } 386 387 if (index < 0) 388 throw new IllegalStateException ("index=" + index + ", opcode=" + opcode); 389 390 } 391 } 392 } 393 394 | Popular Tags |