1 package alt.jiapi.reflect; 2 3 import java.util.List ; 4 import java.util.LinkedList ; 5 6 import alt.jiapi.file.ConstantPool; 7 import alt.jiapi.reflect.instruction.Opcodes; 8 import alt.jiapi.reflect.instruction.Invocation; 9 import alt.jiapi.reflect.instruction.FieldAccess; 10 import alt.jiapi.reflect.instruction.CPInstruction; 11 12 17 class InstructionParser { 18 26 List createInstructionList(byte[] byteCode, ConstantPool cp) { 27 List list = new LinkedList (); 28 boolean branchesFound = false; 29 30 34 for (int i = 0; i < byteCode.length; i++) { 35 byte opcode = byteCode[i]; 36 Instruction ins = null; 37 int iMod = 0; 38 39 switch(opcode) { 41 case Opcodes.NOP: 42 case Opcodes.ACONST_NULL: 43 case Opcodes.ICONST_M1: 44 case Opcodes.ICONST_0: 45 case Opcodes.ICONST_1: 46 case Opcodes.ICONST_2: 47 case Opcodes.ICONST_3: 48 case Opcodes.ICONST_4: 49 case Opcodes.ICONST_5: 50 case Opcodes.LCONST_0: 51 case Opcodes.LCONST_1: 52 case Opcodes.FCONST_0: 53 case Opcodes.FCONST_1: 54 case Opcodes.FCONST_2: 55 case Opcodes.DCONST_0: 56 case Opcodes.DCONST_1: 57 ins = new Instruction(new byte[] { byteCode[i] }); 58 break; 59 case Opcodes.BIPUSH: 60 ins = new Instruction(new byte[] { byteCode[i], 61 byteCode[i+1] }); 62 iMod = 1; break; 64 case Opcodes.SIPUSH: 65 ins = new Instruction(new byte[] { byteCode[i], 66 byteCode[i+1], 67 byteCode[i+2] }); 68 iMod = 2; break; 70 case Opcodes.LDC: 71 ins = new CPInstruction(new byte[] { byteCode[i], 72 byteCode[i+1] }, cp); 73 iMod = 1; break; 75 case Opcodes.LDC_W: 76 case Opcodes.LDC2_W: 77 ins = new CPInstruction(new byte[] { byteCode[i], 78 byteCode[i+1], 79 byteCode[i+2] }, cp); 80 iMod = 2; break; 82 case Opcodes.ILOAD: 83 case Opcodes.LLOAD: 84 case Opcodes.FLOAD: 85 case Opcodes.DLOAD: 86 case Opcodes.ALOAD: 87 ins = new Instruction(new byte[] { byteCode[i], 88 byteCode[i+1] }); 89 iMod = 1; break; 91 case Opcodes.ILOAD_0: 92 case Opcodes.ILOAD_1: 93 case Opcodes.ILOAD_2: 94 case Opcodes.ILOAD_3: 95 case Opcodes.LLOAD_0: 96 case Opcodes.LLOAD_1: 97 case Opcodes.LLOAD_2: 98 case Opcodes.LLOAD_3: 99 case Opcodes.FLOAD_0: 100 case Opcodes.FLOAD_1: 101 case Opcodes.FLOAD_2: 102 case Opcodes.FLOAD_3: 103 case Opcodes.DLOAD_0: 104 case Opcodes.DLOAD_1: 105 case Opcodes.DLOAD_2: 106 case Opcodes.DLOAD_3: 107 case Opcodes.ALOAD_0: 108 case Opcodes.ALOAD_1: 109 case Opcodes.ALOAD_2: 110 case Opcodes.ALOAD_3: 111 ins = new Instruction(new byte[] { byteCode[i] }); 112 break; 113 case Opcodes.IALOAD: 114 case Opcodes.LALOAD: 115 case Opcodes.FALOAD: 116 case Opcodes.DALOAD: 117 case Opcodes.AALOAD: 118 case Opcodes.BALOAD: 119 case Opcodes.CALOAD: 120 case Opcodes.SALOAD: 121 ins = new Instruction(new byte[] { byteCode[i] }); 122 break; 123 case Opcodes.ISTORE: 124 case Opcodes.LSTORE: 125 case Opcodes.FSTORE: 126 case Opcodes.DSTORE: 127 case Opcodes.ASTORE: 128 ins = new Instruction(new byte[] { byteCode[i], 129 byteCode[i+1] }); 130 iMod = 1; break; 132 case Opcodes.ISTORE_0: 133 case Opcodes.ISTORE_1: 134 case Opcodes.ISTORE_2: 135 case Opcodes.ISTORE_3: 136 case Opcodes.LSTORE_0: 137 case Opcodes.LSTORE_1: 138 case Opcodes.LSTORE_2: 139 case Opcodes.LSTORE_3: 140 case Opcodes.FSTORE_0: 141 case Opcodes.FSTORE_1: 142 case Opcodes.FSTORE_2: 143 case Opcodes.FSTORE_3: 144 case Opcodes.DSTORE_0: 145 case Opcodes.DSTORE_1: 146 case Opcodes.DSTORE_2: 147 case Opcodes.DSTORE_3: 148 case Opcodes.ASTORE_0: 149 case Opcodes.ASTORE_1: 150 case Opcodes.ASTORE_2: 151 case Opcodes.ASTORE_3: 152 case Opcodes.IASTORE: 153 case Opcodes.LASTORE: 154 case Opcodes.FASTORE: 155 case Opcodes.DASTORE: 156 case Opcodes.AASTORE: 157 case Opcodes.BASTORE: 158 case Opcodes.CASTORE: 159 case Opcodes.SASTORE: 160 case Opcodes.POP: 161 case Opcodes.POP2: 162 case Opcodes.DUP: 163 case Opcodes.DUP_X1: 164 case Opcodes.DUP_X2: 165 case Opcodes.DUP2: 166 case Opcodes.DUP2_X1: 167 case Opcodes.DUP2_X2: 168 case Opcodes.SWAP: 169 case Opcodes.IADD: 170 case Opcodes.LADD: 171 case Opcodes.FADD: 172 case Opcodes.DADD: 173 case Opcodes.ISUB: 174 case Opcodes.LSUB: 175 case Opcodes.FSUB: 176 case Opcodes.DSUB: 177 case Opcodes.IMUL: 178 case Opcodes.LMUL: 179 case Opcodes.FMUL: 180 case Opcodes.DMUL: 181 case Opcodes.IDIV: 182 case Opcodes.LDIV: 183 case Opcodes.FDIV: 184 case Opcodes.DDIV: 185 case Opcodes.IREM: 186 case Opcodes.LREM: 187 case Opcodes.FREM: 188 case Opcodes.DREM: 189 case Opcodes.INEG: 190 case Opcodes.LNEG: 191 case Opcodes.FNEG: 192 case Opcodes.DNEG: 193 case Opcodes.ISHL: 194 case Opcodes.LSHL: 195 case Opcodes.ISHR: 196 case Opcodes.LSHR: 197 case Opcodes.IUSHR: 198 case Opcodes.LUSHR: 199 case Opcodes.IAND: 200 case Opcodes.LAND: 201 case Opcodes.IOR: 202 case Opcodes.LOR: 203 case Opcodes.IXOR: 204 case Opcodes.LXOR: 205 ins = new Instruction(new byte[] { byteCode[i] }); 206 break; 207 case Opcodes.IINC: 208 ins = new Instruction(new byte[] { byteCode[i], 209 byteCode[i+1], 210 byteCode[i+2] }); 211 iMod = 2; break; 213 case Opcodes.I2L: 214 case Opcodes.I2F: 215 case Opcodes.I2D: 216 case Opcodes.L2I: 217 case Opcodes.L2F: 218 case Opcodes.L2D: 219 case Opcodes.F2I: 220 case Opcodes.F2L: 221 case Opcodes.F2D: 222 case Opcodes.D2I: 223 case Opcodes.D2L: 224 case Opcodes.D2F: 225 case Opcodes.I2B: 226 case Opcodes.I2C: 227 case Opcodes.I2S: 228 case Opcodes.LCMP: 229 case Opcodes.FCMPL: 230 case Opcodes.FCMPG: 231 case Opcodes.DCMPL: 232 case Opcodes.DCMPG: 233 ins = new Instruction(new byte[] { byteCode[i] }); 234 break; 235 case Opcodes.IFEQ: 236 case Opcodes.IFNE: 237 case Opcodes.IFLT: 238 case Opcodes.IFGE: 239 case Opcodes.IFGT: 240 case Opcodes.IFLE: 241 case Opcodes.IF_ICMPEQ: 242 case Opcodes.IF_ICMPNE: 243 case Opcodes.IF_ICMPLT: 244 case Opcodes.IF_ICMPGE: 245 case Opcodes.IF_ICMPGT: 246 case Opcodes.IF_ICMPLE: 247 case Opcodes.IF_ACMPEQ: 248 case Opcodes.IF_ACMPNE: 249 case Opcodes.GOTO: 250 case Opcodes.JSR: 251 branchesFound = true; 252 ins = new BranchInstruction(new byte[] { byteCode[i], 253 byteCode[i+1], 254 byteCode[i+2]}); 255 iMod = 2; break; 257 case Opcodes.RET: 258 ins = new Instruction(new byte[] { byteCode[i], 259 byteCode[i+1]}); 260 iMod = 1; break; 262 case Opcodes.TABLESWITCH: 263 branchesFound = true; 264 int tspCount = 3 - (i % 4); 265 266 byte l1 = byteCode[i + tspCount + 5]; 267 byte l2 = byteCode[i + tspCount + 6]; 268 byte l3 = byteCode[i + tspCount + 7]; 269 byte l4 = byteCode[i + tspCount + 8]; 270 271 int low = (((int)l1) << 24) | (((int)l2) << 16) | 272 (((int)l3) << 8) | l4; 273 274 byte h1 = byteCode[i + tspCount + 9]; 275 byte h2 = byteCode[i + tspCount + 10]; 276 byte h3 = byteCode[i + tspCount + 11]; 277 byte h4 = byteCode[i + tspCount + 12]; 278 279 int high = (((int)h1) << 24) | (((int)h2) << 16) | 280 (((int)h3) << 8) | h4; 281 282 int size = high - low + 1; 283 int bSize = size * 4; 285 byte[] tsBytes = new byte[13 + tspCount + bSize]; 286 for (int k = 0; k < tsBytes.length; k++) { 287 tsBytes[k] = byteCode[i + k]; 288 } 289 290 iMod = tsBytes.length -1; ins = new SwitchInstruction(tsBytes, tspCount, size); 292 293 break; 294 case Opcodes.LOOKUPSWITCH: 295 branchesFound = true; 296 int pCount = 3 - (i % 4); 297 300 byte np1 = byteCode[i + pCount + 5]; 301 byte np2 = byteCode[i + pCount + 6]; 302 byte np3 = byteCode[i + pCount + 7]; 303 byte np4 = byteCode[i + pCount + 8]; 304 305 int nPairs = (np1 << 24) & 0xff000000 | (np2 << 16) & 0xff0000| 306 (np3 << 8) & 0xff00 | (np4 & 0xff); 307 308 int lbSize = nPairs * 4 * 2; 310 byte[] lsBytes = new byte[9 + pCount + lbSize ]; 311 312 for (int k = 0; k < lsBytes.length; k++) { 313 lsBytes[k] = byteCode[i + k]; 314 } 315 316 iMod = lsBytes.length -1; ins = new SwitchInstruction(lsBytes, pCount, nPairs); 318 break; 319 case Opcodes.IRETURN: 320 case Opcodes.LRETURN: 321 case Opcodes.FRETURN: 322 case Opcodes.DRETURN: 323 case Opcodes.ARETURN: 324 case Opcodes.RETURN: 325 ins = new Instruction(new byte[] { byteCode[i] }); 326 break; 327 case Opcodes.GETSTATIC: 328 case Opcodes.PUTSTATIC: 329 case Opcodes.GETFIELD: 330 case Opcodes.PUTFIELD: 331 ins = new FieldAccess(new byte[] { byteCode[i], 332 byteCode[i+1], 333 byteCode[i+2]}, cp); 334 iMod = 2; break; 336 case Opcodes.INVOKEVIRTUAL: 337 case Opcodes.INVOKESPECIAL: 338 case Opcodes.INVOKESTATIC: 339 ins = new Invocation(new byte[] { byteCode[i], 342 byteCode[i+1], 343 byteCode[i+2] }, cp); 344 iMod = 2; break; 346 case Opcodes.INVOKEINTERFACE: 347 byte count = byteCode[i+3]; 348 ins = new Invocation(new byte[] { byteCode[i], 349 byteCode[i+1], 350 byteCode[i+2], 351 count, 352 byteCode[i+4]}, cp); 353 iMod = 4; break; 355 case Opcodes.XXXUNUSEDXXX: 356 new Instruction(new byte[] { byteCode[i]}); 357 break; 358 case Opcodes.NEW: 359 ins = new CPInstruction(new byte[] { byteCode[i], 360 byteCode[i+1], 361 byteCode[i+2] }, cp); 362 iMod = 2; break; 364 case Opcodes.NEWARRAY: 365 ins = new Instruction(new byte[] { byteCode[i], 366 byteCode[i+1] }); 367 iMod = 1; break; 369 case Opcodes.ANEWARRAY: 370 ins = new CPInstruction(new byte[] { byteCode[i], 371 byteCode[i+1], 372 byteCode[i+2] }, cp); 373 iMod = 2; break; 375 case Opcodes.ARRAYLENGTH: 376 ins = new Instruction(new byte[] { byteCode[i] } ); 377 break; 378 case Opcodes.ATHROW: 379 ins = new Instruction(new byte[] { byteCode[i] } ); 380 break; 381 case Opcodes.CHECKCAST: 382 ins = new CPInstruction(new byte[] { byteCode[i], 383 byteCode[i+1], 384 byteCode[i+2] }, cp); 385 iMod = 2; break; 387 case Opcodes.INSTANCEOF: 388 ins = new CPInstruction(new byte[] { byteCode[i], 389 byteCode[i+1], 390 byteCode[i+2] }, cp); 391 iMod = 2; break; 393 case Opcodes.MONITORENTER: 394 case Opcodes.MONITOREXIT: 395 ins = new Instruction(new byte[] { byteCode[i] }); 396 break; 397 case Opcodes.WIDE: 398 if (byteCode[i + 1] == Opcodes.IINC) { 399 ins = new Instruction(new byte[] { byteCode[i], 401 byteCode[i+1], 402 byteCode[i+2], 403 byteCode[i+3], 404 byteCode[i+4], 405 byteCode[i+5] }); 406 iMod = 5; } 408 else { 409 ins = new Instruction(new byte[] { byteCode[i], 411 byteCode[i+1], 412 byteCode[i+2], 413 byteCode[i+3] }); 414 iMod = 3; } 416 break; 417 case Opcodes.MULTIANEWARRAY: 418 byte dim = byteCode[i+4]; 419 ins = new Instruction(new byte[] { byteCode[i], 420 byteCode[i+1], 421 byteCode[i+2], 422 byteCode[i+3], 423 dim }); 424 iMod = 4; break; 426 case Opcodes.IFNULL: 427 case Opcodes.IFNONNULL: 428 branchesFound = true; 429 ins = new BranchInstruction(new byte[] { byteCode[i], 430 byteCode[i+1], 431 byteCode[i+2] }); 432 iMod = 2; break; 434 case Opcodes.GOTO_W: 435 branchesFound = true; 436 ins = new BranchInstruction(new byte[] { byteCode[i], 437 byteCode[i+1], 438 byteCode[i+2], 439 byteCode[i+3], 440 byteCode[i+4] }); 441 iMod = 4; break; 443 case Opcodes.JSR_W: 444 branchesFound = true; 445 ins = new BranchInstruction(new byte[] { byteCode[i], 446 byteCode[i+1], 447 byteCode[i+2], 448 byteCode[i+3], 449 byteCode[i+4] }); 450 iMod = 4; break; 452 case Opcodes.BREAKPOINT: 453 case Opcodes.IMPDEP1: 454 case Opcodes.IMPDEP2: 455 ins = new Instruction(new byte[] { byteCode[i] }); 456 break; 457 } 458 459 ins.setOffset((short)i); 460 i += iMod; 461 462 list.add(ins); 463 } 464 465 if (branchesFound) { 469 for (int i = 0; i < list.size(); i++) { 471 Instruction ins = (Instruction)list.get(i); 472 if (ins instanceof BranchInstruction) { 473 475 BranchInstruction bi = (BranchInstruction)ins; 476 int offset = bi.getTargetOffset(); 477 478 Instruction target = null; 479 target = findTarget(list, (bi.getOffset() + offset)); 482 if (target != null) { 483 bi.setTarget(target); 484 } 485 else { 486 System.out.println("Error locating branch target for instruction at " + i + ": " + bi); 487 } 488 } 489 else if (ins instanceof SwitchInstruction) { 490 492 SwitchInstruction si = (SwitchInstruction)ins; 493 int dOffset = si.getDefaultOffset(); 494 495 Instruction target = null; 497 target = findTarget(list, i, dOffset); 498 si.setDefault(target); 499 500 int[] tOffsets = si.getTargetOffsets(); 502 503 Instruction[] targets = new Instruction[tOffsets.length]; 504 for (int j = 0; j < targets.length; j++) { 505 targets[j] = findTarget(list, i, tOffsets[j]); 506 } 507 si.setTargets(targets); 508 } 509 } 510 } 511 512 513 return list; 514 } 515 516 519 private Instruction findTarget(List list, int offset) { 520 int idx = 0; 521 int currentOffset = 0; 522 while (currentOffset != offset) { 523 if (idx == list.size()) { 524 return null; 525 } 526 527 Instruction ins = (Instruction)list.get(idx); 528 currentOffset += ins.length(); 529 idx++; 530 } 531 532 return (Instruction)list.get(idx); 533 } 534 535 538 private Instruction findTarget(List list, int idx, int offset) { 539 int offs = offset; 540 int dir = 1; 541 if (offset < 0) { 542 offs = -offset; 543 dir = -1; 544 } 545 546 int i = 0; 547 548 while(i < offs) { 549 Instruction ins = (Instruction)list.get(idx); 550 i += ins.length(); 551 idx += dir; 552 } 553 554 Instruction target = (Instruction)list.get(idx); 556 TargetInstruction ti = new TargetInstruction(target); 557 list.set(idx, ti); 558 559 return ti; 560 } 561 } 562 | Popular Tags |