1 #!/usr/bin/env python 2 3 """ 4 Java bytecode conversion. Specification found at the following URL: 5 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html 6 7 NOTE: Synchronized constructs are not actually supported. 8 """ 9 10 import dis # for access to Python bytecode values 11 from UserDict import UserDict 12 13 # Bytecode production classes. 14 15 class BytecodeWriter: 16 def __init__(self): 17 self.loops = [] 18 self.jumps = {} 19 self.output = [] 20 self.position = 0 21 22 # Mapping from values to indexes. 23 self.constants = {} 24 25 # Mapping from names to indexes. 26 # NOTE: This may be acquired from elsewhere. 27 self.globals = {} 28 29 def get_output(self): 30 output = [] 31 for element in self.output: 32 if isinstance(element, LazyValue): 33 output.append(chr(element.value)) 34 else: 35 output.append(chr(element)) 36 return "".join(output) 37 38 # Special methods. 39 40 def end_loop(self): 41 current_loop_start = self.loops.pop() 42 self.jump_absolute(current_loop_start) 43 self.output[current_loop_start + 1] = self.position 44 self.pop_block() 45 46 def jump_to_label(self, status, name): 47 # Record the instruction using the jump. 48 if not self.jumps.has_key(name): 49 self.jumps[name] = [] 50 self.jumps[name].append(self.position) 51 if status is None: 52 self.jump_forward() 53 elif status: 54 self.jump_if_true() 55 else: 56 self.jump_if_false() 57 58 def start_label(self, name): 59 # Fill in all jump instructions. 60 for jump_instruction in self.jumps[name]: 61 self.output[jump_instruction + 1] = self.position 62 63 # Complicated methods. 64 65 def load_const(self, value): 66 self.output.append(opmap["LOAD_CONST"]) 67 if not self.constants.has_key(value): 68 self.constants[value] = len(self.constants.keys()) 69 self.output.append(self.constants[value]) 70 71 def load_global(self, name): 72 self.output.append(opmap["LOAD_GLOBAL"]) 73 if not self.globals.has_key(value): 74 self.globals[name] = len(self.globals.keys()) 75 self.output.append(self.globals[name]) 76 77 def load_fast(self, index): 78 self.output.append(opmap["LOAD_FAST"]) 79 self.output.append(index) 80 81 # Normal bytecode generators. 82 83 def for_iter(self): 84 self.loops.push(self.position) 85 self.output.append(opmap["FOR_ITER"]) 86 self.output.append(None) # To be filled in later 87 self.position += 2 88 89 def jump_if_false(self, offset=None): 90 self.output.append(opmap["JUMP_IF_FALSE"]) 91 self.output.append(offset) # May be filled in later 92 self.position += 2 93 94 def jump_if_true(self, offset=None): 95 self.output.append(opmap["JUMP_IF_TRUE"]) 96 self.output.append(offset) # May be filled in later 97 self.position += 2 98 99 def jump_forward(self, offset=None): 100 self.output.append(opmap["JUMP_FORWARD"]) 101 self.output.append(offset) # May be filled in later 102 self.position += 2 103 104 # Utility classes and functions. 105 106 class LazyDict(UserDict): 107 def __getitem__(self, key): 108 if not self.data.has_key(key): 109 self.data[key] = LazyValue() 110 return self.data[key] 111 def __setitem__(self, key, value): 112 if self.data.has_key(key): 113 existing_value = self.data[key] 114 if isinstance(existing_value, LazyValue): 115 existing_value.value = value 116 return 117 self.data[key] = value 118 119 class LazyValue: 120 def __init__(self, value=None): 121 self.value = value 122 123 def signed(value, limit): 124 125 """ 126 Return the signed integer from the unsigned 'value', where 'limit' (a value 127 one greater than the highest possible positive integer) is used to determine 128 whether a negative or positive result is produced. 129 """ 130 131 d, r = divmod(value, limit) 132 if d == 1: 133 mask = limit * 2 - 1 134 return -1 - (value ^ mask) 135 else: 136 return value 137 138 def signed2(value): 139 return signed(value, 0x8000) 140 141 def signed4(value): 142 return signed(value, 0x80000000) 143 144 # Bytecode conversion. 145 146 class BytecodeReader: 147 def __init__(self, class_file): 148 self.class_file = class_file 149 self.position_mapping = LazyDict() 150 151 def process(self, code, program): 152 self.java_position = 0 153 while self.java_position < len(code): 154 self.position_mapping[self.java_position] = program.position 155 bytecode = ord(code[self.java_position]) 156 mnemonic, number_of_arguments = self.java_bytecodes[bytecode] 157 self.process_bytecode(mnemonic, number_of_arguments) 158 159 def process_bytecode(self, mnemonic, number_of_arguments): 160 if number_of_arguments is not None: 161 arguments = [] 162 for j in range(0, number_of_arguments): 163 arguments.append(ord(code[self.java_position + 1 + j])) 164 165 # Call the handler. 166 getattr(self, mnemonic)(arguments, program) 167 else: 168 # Call the handler. 169 number_of_arguments = getattr(self, mnemonic)(code[self.java_position+1:], program) 170 171 self.java_position = self.java_position + 1 + number_of_arguments 172 173 def nop(self, arguments, program): 174 pass 175 176 def aaload(self, arguments, program): 177 # NOTE: No type checking performed. 178 program.binary_subscr() 179 180 def aastore(self, arguments, program): 181 # NOTE: No type checking performed. 182 # Stack: arrayref, index, value 183 program.rot_three() # Stack: value, arrayref, index 184 program.store_subscr() 185 186 def aconst_null(self, arguments, program): 187 program.load_global(None) 188 189 def aload(self, arguments, program): 190 program.load_fast(arguments[0]) 191 192 def aload_0(self, arguments, program): 193 program.load_fast(0) 194 195 def aload_1(self, arguments, program): 196 program.load_fast(1) 197 198 def aload_2(self, arguments, program): 199 program.load_fast(2) 200 201 def aload_3(self, arguments, program): 202 program.load_fast(3) 203 204 def anewarray(self, arguments, program): 205 # NOTE: Does not raise NegativeArraySizeException. 206 # NOTE: Not using the index to type the list/array. 207 index = arguments[0] << 8 + arguments[1] 208 209 program.build_list() # Stack: count, list 210 program.rot_two() # Stack: list, count 211 program.setup_loop() 212 program.load_global("range") 213 program.load_const(0) # Stack: list, count, range, 0 214 program.rot_three() # Stack: list, 0, count, range 215 program.rot_three() # Stack: list, range, 0, count 216 program.call_function(2) # Stack: list, range_list 217 program.get_iter() # Stack: list, iter 218 program.for_iter() # Stack: list, iter, value 219 program.pop_top() # Stack: list, iter 220 program.rot_two() # Stack: iter, list 221 program.dup_top() # Stack: iter, list, list 222 program.load_attr("append") # Stack: iter, list, append 223 program.load_global(None) # Stack: iter, list, append, None 224 program.call_function(1) # Stack: iter, list, None 225 program.pop_top() # Stack: iter, list 226 program.rot_two() # Stack: list, iter 227 program.end_loop() # Back to for_iter above 228 229 def areturn(self, arguments, program): 230 program.return_value() 231 232 def arraylength(self, arguments, program): 233 program.load_global("len") # Stack: arrayref, len 234 program.rot_two() # Stack: len, arrayref 235 program.call_function(1) 236 237 def astore(self, arguments, program): 238 program.store_fast(arguments[0]) 239 240 def astore_0(self, arguments, program): 241 program.store_fast(0) 242 243 def astore_1(self, arguments, program): 244 program.store_fast(1) 245 246 def astore_2(self, arguments, program): 247 program.store_fast(2) 248 249 def astore_3(self, arguments, program): 250 program.store_fast(3) 251 252 def athrow(self, arguments, program): 253 # NOTE: NullPointerException not raised where null/None is found on the stack. 254 program.raise_varargs(1) 255 256 baload = aaload 257 bastore = aastore 258 259 def bipush(self, arguments, program): 260 program.load_const(arguments[0]) 261 262 caload = aaload 263 castore = aastore 264 265 def checkcast(self, arguments, program): 266 index = arguments[0] << 8 + arguments[1] 267 target_name = self.class_file.constants[index - 1].get_name() 268 target_components = target_name.split("/") 269 270 program.dup_top() # Stack: objectref, objectref 271 program.load_global("isinstance") # Stack: objectref, objectref, isinstance 272 program.rot_two() # Stack: objectref, isinstance, objectref 273 program.load_global(target_components[0]) 274 for target_component in target_components[1:]: 275 program.load_attr(target_component) 276 program.call_function(2) # Stack: objectref 277 278 def d2f(self, arguments, program): 279 pass 280 281 def d2i(self, arguments, program): 282 program.load_global("int") # Stack: value, int 283 program.rot_two() # Stack: int, value 284 program.call_function(1) # Stack: result 285 286 d2l = d2i # Preserving Java semantics 287 288 def dadd(self, arguments, program): 289 # NOTE: No type checking performed. 290 program.binary_add() 291 292 daload = aaload 293 dastore = aastore 294 295 def dcmpg(self, arguments, program): 296 # NOTE: No type checking performed. 297 program.compare_op(">") 298 299 def dcmpl(self, arguments, program): 300 # NOTE: No type checking performed. 301 program.compare_op("<") 302 303 def dconst_0(self, arguments, program): 304 program.load_const(0.0) 305 306 def dconst_1(self, arguments, program): 307 program.load_const(1.0) 308 309 def ddiv(self, arguments, program): 310 # NOTE: No type checking performed. 311 program.binary_divide() 312 313 dload = aload 314 dload_0 = aload_0 315 dload_1 = aload_1 316 dload_2 = aload_2 317 dload_3 = aload_3 318 319 def dmul(self, arguments, program): 320 # NOTE: No type checking performed. 321 program.binary_multiply() 322 323 def dneg(self, arguments, program): 324 # NOTE: No type checking performed. 325 program.unary_negative() 326 327 def drem(self, arguments, program): 328 # NOTE: No type checking performed. 329 program.binary_modulo() 330 331 dreturn = areturn 332 dstore = astore 333 dstore_0 = astore_0 334 dstore_1 = astore_1 335 dstore_2 = astore_2 336 dstore_3 = astore_3 337 338 def dsub(self, arguments, program): 339 # NOTE: No type checking performed. 340 program.binary_subtract() 341 342 def dup(self, arguments, program): 343 program.dup_top() 344 345 def dup_x1(self, arguments, program): 346 # Ignoring computational type categories. 347 program.dup_top() 348 program.rot_three() 349 350 def dup_x2(self, arguments, program): 351 # Ignoring computational type categories. 352 program.dup_top() 353 program.rot_four() 354 355 dup2 = dup # Ignoring computational type categories 356 dup2_x1 = dup_x1 # Ignoring computational type categories 357 dup2_x2 = dup_x2 # Ignoring computational type categories 358 359 def f2d(self, arguments, program): 360 pass # Preserving Java semantics 361 362 def f2i(self, arguments, program): 363 program.load_global("int") # Stack: value, int 364 program.rot_two() # Stack: int, value 365 program.call_function(1) # Stack: result 366 367 f2l = f2i # Preserving Java semantics 368 fadd = dadd 369 faload = daload 370 fastore = dastore 371 fcmpg = dcmpg 372 fcmpl = dcmpl 373 fconst_0 = dconst_0 374 fconst_1 = dconst_1 375 376 def fconst_2(self, arguments, program): 377 program.load_const(2.0) 378 379 fdiv = ddiv 380 fload = dload 381 fload_0 = dload_0 382 fload_1 = dload_1 383 fload_2 = dload_2 384 fload_3 = dload_3 385 fmul = dmul 386 fneg = dneg 387 frem = drem 388 freturn = dreturn 389 fstore = dstore 390 fstore_0 = dstore_0 391 fstore_1 = dstore_1 392 fstore_2 = dstore_2 393 fstore_3 = dstore_3 394 fsub = dsub 395 396 def getfield(self, arguments, program): 397 index = arguments[0] << 8 + arguments[1] 398 target_name = self.class_file.constants[index - 1].get_name() 399 # NOTE: Using the string version of the name which may contain incompatible characters. 400 program.load_attr(str(target_name)) 401 402 getstatic = getfield # Ignoring Java restrictions 403 404 def goto(self, arguments, program): 405 offset = signed2(arguments[0] << 8 + arguments[1]) 406 java_absolute = self.java_position + offset 407 program.jump_absolute(self.position_mapping[java_absolute]) 408 409 def goto_w(self, arguments, program): 410 offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]) 411 java_absolute = self.java_position + offset 412 program.jump_absolute(self.position_mapping[java_absolute]) 413 414 def i2b(self, arguments, program): 415 pass 416 417 def i2c(self, arguments, program): 418 program.load_global("chr") # Stack: value, chr 419 program.rot_two() # Stack: chr, value 420 program.call_function(1) # Stack: result 421 422 def i2d(self, arguments, program): 423 program.load_global("float") # Stack: value, float 424 program.rot_two() # Stack: float, value 425 program.call_function(1) # Stack: result 426 427 i2f = i2d # Not distinguishing between float and double 428 429 def i2l(self, arguments, program): 430 pass # Preserving Java semantics 431 432 def i2s(self, arguments, program): 433 pass # Not distinguishing between int and short 434 435 iadd = fadd 436 iaload = faload 437 438 def iand(self, arguments, program): 439 # NOTE: No type checking performed. 440 program.binary_and() 441 442 iastore = fastore 443 444 def iconst_m1(self, arguments, program): 445 program.load_const(-1) 446 447 def iconst_0(self, arguments, program): 448 program.load_const(0) 449 450 def iconst_1(self, arguments, program): 451 program.load_const(1) 452 453 def iconst_2(self, arguments, program): 454 program.load_const(2) 455 456 def iconst_3(self, arguments, program): 457 program.load_const(3) 458 459 def iconst_4(self, arguments, program): 460 program.load_const(4) 461 462 def iconst_5(self, arguments, program): 463 program.load_const(5) 464 465 idiv = fdiv 466 467 def _if_xcmpx(self, arguments, program, op): 468 offset = signed2(arguments[0] << 8 + arguments[1]) 469 java_absolute = self.java_position + offset 470 program.compare_op(op) 471 program.jump_to_label(0, "next") # skip if false 472 program.goto(offset) 473 program.start_label("next") 474 475 def if_acmpeq(self, arguments, program): 476 # NOTE: No type checking performed. 477 self._if_xcmpx(arguments, program, "is") 478 479 def if_acmpne(self, arguments, program): 480 # NOTE: No type checking performed. 481 self._if_xcmpx(arguments, program, "is not") 482 483 def if_icmpeq(self, arguments, program): 484 # NOTE: No type checking performed. 485 self._if_xcmpx(arguments, program, "==") 486 487 def if_icmpne(self, arguments, program): 488 # NOTE: No type checking performed. 489 self._if_xcmpx(arguments, program, "!=") 490 491 def if_icmplt(self, arguments, program): 492 # NOTE: No type checking performed. 493 self._if_xcmpx(arguments, program, "<") 494 495 def if_icmpge(self, arguments, program): 496 # NOTE: No type checking performed. 497 self._if_xcmpx(arguments, program, ">=") 498 499 def if_icmpgt(self, arguments, program): 500 # NOTE: No type checking performed. 501 self._if_xcmpx(arguments, program, ">") 502 503 def if_icmple(self, arguments, program): 504 # NOTE: No type checking performed. 505 self._if_xcmpx(arguments, program, "<=") 506 507 def ifeq(self, arguments, program): 508 # NOTE: No type checking performed. 509 program.load_const(0) 510 self._if_xcmpx(arguments, program, "==") 511 512 def ifne(self, arguments, program): 513 # NOTE: No type checking performed. 514 program.load_const(0) 515 self._if_xcmpx(arguments, program, "!=") 516 517 def iflt(self, arguments, program): 518 # NOTE: No type checking performed. 519 program.load_const(0) 520 self._if_xcmpx(arguments, program, "<") 521 522 def ifge(self, arguments, program): 523 # NOTE: No type checking performed. 524 program.load_const(0) 525 self._if_xcmpx(arguments, program, ">=") 526 527 def ifgt(self, arguments, program): 528 # NOTE: No type checking performed. 529 program.load_const(0) 530 self._if_xcmpx(arguments, program, ">") 531 532 def ifle(self, arguments, program): 533 # NOTE: No type checking performed. 534 program.load_const(0) 535 self._if_xcmpx(arguments, program, "<=") 536 537 def ifnonnull(self, arguments, program): 538 # NOTE: No type checking performed. 539 program.load_const(None) 540 self._if_xcmpx(arguments, program, "is not") 541 542 def ifnull(self, arguments, program): 543 # NOTE: No type checking performed. 544 program.load_const(None) 545 self._if_xcmpx(arguments, program, "is") 546 547 def iinc(self, arguments, program): 548 # NOTE: No type checking performed. 549 program.load_fast(arguments[0]) 550 program.load_const(arguments[1]) 551 program.binary_add() 552 553 iload = fload 554 iload_0 = fload_0 555 iload_1 = fload_1 556 iload_2 = fload_2 557 iload_3 = fload_3 558 imul = fmul 559 ineg = fneg 560 561 def instanceof(self, arguments, program): 562 index = arguments[0] << 8 + arguments[1] 563 target_name = self.class_file.constants[index - 1].get_name() 564 target_components = target_name.split("/") 565 566 program.load_global("isinstance") # Stack: objectref, isinstance 567 program.rot_two() # Stack: isinstance, objectref 568 program.load_global(target_components[0]) 569 for target_component in target_components[1:]: 570 program.load_attr(target_component) 571 program.call_function(2) # Stack: result 572 573 def _invoke(self, target_name, program): 574 program.rot_two() # Stack: tuple, objectref 575 # NOTE: Using the string version of the name which may contain incompatible characters. 576 program.load_attr(str(target_name)) # Stack: tuple, method 577 program.rot_two() # Stack: method, tuple 578 program.load_global("apply") # Stack: method, tuple, apply 579 program.rot_three() # Stack: apply, method, tuple 580 program.call_function(2) 581 582 def invokeinterface(self, arguments, program): 583 # NOTE: This implementation does not perform the necessary checks for 584 # NOTE: signature-based polymorphism. 585 # NOTE: Java rules not specifically obeyed. 586 index = arguments[0] << 8 + arguments[1] 587 count = arguments[2] 588 target_name = self.class_file.constants[index - 1].get_name() 589 # Stack: objectref, arg1, arg2, ... 590 program.build_tuple(count) # Stack: objectref, tuple 591 self._invoke(target_name, program) 592 593 def invokespecial(self, arguments, program): 594 # NOTE: This implementation does not perform the necessary checks for 595 # NOTE: signature-based polymorphism. 596 # NOTE: Java rules not specifically obeyed. 597 index = arguments[0] << 8 + arguments[1] 598 target = self.class_file.constants[index - 1] 599 target_name = target.get_name() 600 # Get the number of parameters from the descriptor. 601 count = len(target.get_descriptor()[0]) 602 # Stack: objectref, arg1, arg2, ... 603 program.build_tuple(count) # Stack: objectref, tuple 604 self._invoke(target_name, program) 605 606 def invokestatic(self, arguments, program): 607 # NOTE: This implementation does not perform the necessary checks for 608 # NOTE: signature-based polymorphism. 609 # NOTE: Java rules not specifically obeyed. 610 index = arguments[0] << 8 + arguments[1] 611 target = self.class_file.constants[index - 1] 612 target_name = target.get_name() 613 # Get the number of parameters from the descriptor. 614 count = len(target.get_descriptor()[0]) 615 # Stack: arg1, arg2, ... 616 program.build_tuple(count) # Stack: tuple 617 # NOTE: Should probably use Python static methods. 618 program.load_name("self") # Stack: tuple, self 619 self._invoke(target_name, program) 620 621 invokevirtual = invokeinterface # Ignoring Java rules 622 623 def ior(self, arguments, program): 624 # NOTE: No type checking performed. 625 program.binary_or() 626 627 irem = frem 628 ireturn = freturn 629 630 def ishl(self, arguments, program): 631 # NOTE: No type checking performed. 632 # NOTE: Not verified. 633 program.binary_lshift() 634 635 def ishr(self, arguments, program): 636 # NOTE: No type checking performed. 637 # NOTE: Not verified. 638 program.binary_rshift() 639 640 istore = fstore 641 istore_0 = fstore_0 642 istore_1 = fstore_1 643 istore_2 = fstore_2 644 istore_3 = fstore_3 645 isub = fsub 646 iushr = ishr # Ignoring distinctions between arithmetic and logical shifts 647 648 def ixor(self, arguments, program): 649 # NOTE: No type checking performed. 650 program.binary_xor() 651 652 def jsr(self, arguments, program): 653 offset = signed2(arguments[0] << 8 + arguments[1]) 654 java_absolute = self.java_position + offset 655 # Store the address of the next instruction. 656 program.load_const(self.position_mapping[self.java_position + 3]) 657 program.jump_absolute(self.position_mapping[java_absolute]) 658 659 def jsr_w(self, arguments, program): 660 offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]) 661 java_absolute = self.java_position + offset 662 # Store the address of the next instruction. 663 program.load_const(self.position_mapping[self.java_position + 5]) 664 program.jump_absolute(self.position_mapping[java_absolute]) 665 666 l2d = i2d 667 l2f = i2f 668 669 def l2i(self, arguments, program): 670 pass # Preserving Java semantics 671 672 ladd = iadd 673 laload = iaload 674 land = iand 675 lastore = iastore 676 677 def lcmp(self, arguments, program): 678 # NOTE: No type checking performed. 679 program.dup_topx(2) # Stack: value1, value2, value1, value2 680 program.compare_op(">") # Stack: value1, value2, result 681 program.jump_to_label(0, "equals") 682 # True - produce result and branch. 683 program.pop_top() # Stack: value1, value2 684 program.pop_top() # Stack: value1 685 program.pop_top() # Stack: 686 program.load_const(1) # Stack: 1 687 program.jump_to_label(None, "next") 688 # False - test equality. 689 program.start_label("equals") 690 program.pop_top() # Stack: value1, value2 691 program.dup_topx(2) # Stack: value1, value2, value1, value2 692 program.compare_op("==") # Stack: value1, value2, result 693 program.jump_to_label(0, "less") 694 # True - produce result and branch. 695 program.pop_top() # Stack: value1, value2 696 program.pop_top() # Stack: value1 697 program.pop_top() # Stack: 698 program.load_const(0) # Stack: 0 699 program.jump_to_label(None, "next") 700 # False - produce result. 701 program.start_label("less") 702 program.pop_top() # Stack: value1, value2 703 program.pop_top() # Stack: value1 704 program.pop_top() # Stack: 705 program.load_const(-1) # Stack: -1 706 program.start_label("next") 707 708 lconst_0 = iconst_0 709 lconst_1 = iconst_1 710 711 def ldc(self, arguments, program): 712 program.load_const(self.class_file.constants[arguments[0] - 1]) 713 714 def ldc_w(self, arguments, program): 715 program.load_const(self.class_file.constants[arguments[0] << 8 + arguments[1] - 1]) 716 717 ldc2_w = ldc_w 718 ldiv = idiv 719 lload = iload 720 lload_0 = iload_0 721 lload_1 = iload_1 722 lload_2 = iload_2 723 lload_3 = iload_3 724 lmul = imul 725 lneg = ineg 726 727 def lookupswitch(self, arguments, program): 728 # Find the offset to the next 4 byte boundary in the code. 729 d, r = divmod(self.java_position, 4) 730 to_boundary = (4 - r) % 4 731 # Get the pertinent arguments. 732 arguments = arguments[to_boundary:] 733 default = arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3] 734 npairs = arguments[4] << 24 + arguments[5] << 16 + arguments[6] << 8 + arguments[7] 735 # Process the pairs. 736 # NOTE: This is not the most optimal implementation. 737 pair_index = 8 738 for pair in range(0, npairs): 739 match = (arguments[pair_index] << 24 + arguments[pair_index + 1] << 16 + 740 arguments[pair_index + 2] << 8 + arguments[pair_index + 3]) 741 offset = signed4(arguments[pair_index + 4] << 24 + arguments[pair_index + 5] << 16 + 742 arguments[pair_index + 6] << 8 + arguments[pair_index + 7]) 743 # Calculate the branch target. 744 java_absolute = self.java_position + offset 745 # Generate branching code. 746 program.dup_top() # Stack: key, key 747 program.load_const(match) # Stack: key, key, match 748 program.compare_op("==") # Stack: key, result 749 program.jump_to_label(0, "end" + str(pair)) 750 program.pop_top() # Stack: key 751 program.pop_top() # Stack: 752 program.jump_absolute(self.position_mapping[java_absolute]) 753 # Generate the label for the end of the branching code. 754 program.start_label("end" + str(pair)) 755 program.pop_top() # Stack: key 756 # Update the index. 757 pair_index += 8 758 # Generate the default. 759 java_absolute = self.java_position + default 760 program.jump_absolute(self.position_mapping[java_absolute]) 761 762 lor = ior 763 lrem = irem 764 lreturn = ireturn 765 lshl = ishl 766 lshr = ishr 767 lstore = istore 768 lstore_0 = istore_0 769 lstore_1 = istore_1 770 lstore_2 = istore_2 771 lstore_3 = istore_3 772 lsub = isub 773 lushr = iushr 774 lxor = ixor 775 776 def monitorenter(self, arguments, program): 777 # NOTE: To be implemented. 778 pass 779 780 def monitorexit(self, arguments, program): 781 # NOTE: To be implemented. 782 pass 783 784 def multianewarray(self, arguments, program): 785 program.build_list() # Stack: count1, count2, ..., countN, list 786 program.rot_two() # Stack: count1, count2, ..., list, countN 787 program.setup_loop() 788 program.load_global("range") 789 program.load_const(0) # Stack: list, count, range, 0 790 program.rot_three() # Stack: list, 0, count, range 791 program.rot_three() # Stack: list, range, 0, count 792 program.call_function(2) # Stack: list, range_list 793 program.get_iter() # Stack: list, iter 794 program.for_iter() # Stack: list, iter, value 795 for i in range(0, arguments[2]): 796 # Stack: 797 self.anewarray(arguments, program) # Stack: list, iter 798 799 def wide(self, code, program): 800 # NOTE: To be implemented. 801 return number_of_arguments 802 803 java_bytecodes = { 804 # code : (mnemonic, number of following bytes, change in stack) 805 0 : ("nop", 0), 806 1 : ("aconst_null", 0), 807 2 : ("iconst_m1", 0), 808 3 : ("iconst_0", 0), 809 4 : ("iconst_1", 0), 810 5 : ("iconst_2", 0), 811 6 : ("iconst_3", 0), 812 7 : ("iconst_4", 0), 813 8 : ("iconst_5", 0), 814 9 : ("lconst_0", 0), 815 10 : ("lconst_1", 0), 816 11 : ("fconst_0", 0), 817 12 : ("fconst_1", 0), 818 13 : ("fconst_2", 0), 819 14 : ("dconst_0", 0), 820 15 : ("dconst_1", 0), 821 16 : ("bipush", 1), 822 17 : ("sipush", 2), 823 18 : ("ldc", 1), 824 19 : ("ldc_w", 2), 825 20 : ("ldc2_w", 2), 826 21 : ("iload", 1), 827 22 : ("lload", 1), 828 23 : ("fload", 1), 829 24 : ("dload", 1), 830 25 : ("aload", 1), 831 26 : ("iload_0", 0), 832 27 : ("iload_1", 0), 833 28 : ("iload_2", 0), 834 29 : ("iload_3", 0), 835 30 : ("lload_0", 0), 836 31 : ("lload_1", 0), 837 32 : ("lload_2", 0), 838 33 : ("lload_3", 0), 839 34 : ("fload_0", 0), 840 35 : ("fload_1", 0), 841 36 : ("fload_2", 0), 842 37 : ("fload_3", 0), 843 38 : ("dload_0", 0), 844 39 : ("dload_1", 0), 845 40 : ("dload_2", 0), 846 41 : ("dload_3", 0), 847 42 : ("aload_0", 0), 848 43 : ("aload_1", 0), 849 44 : ("aload_2", 0), 850 45 : ("aload_3", 0), 851 46 : ("iaload", 0), 852 47 : ("laload", 0), 853 48 : ("faload", 0), 854 49 : ("daload", 0), 855 50 : ("aaload", 0), 856 51 : ("baload", 0), 857 52 : ("caload", 0), 858 53 : ("saload", 0), 859 54 : ("istore", 1), 860 55 : ("lstore", 1), 861 56 : ("fstore", 1), 862 57 : ("dstore", 1), 863 58 : ("astore", 1), 864 59 : ("istore_0", 0), 865 60 : ("istore_1", 0), 866 61 : ("istore_2", 0), 867 62 : ("istore_3", 0), 868 63 : ("lstore_0", 0), 869 64 : ("lstore_1", 0), 870 65 : ("lstore_2", 0), 871 66 : ("lstore_3", 0), 872 67 : ("fstore_0", 0), 873 68 : ("fstore_1", 0), 874 69 : ("fstore_2", 0), 875 70 : ("fstore_3", 0), 876 71 : ("dstore_0", 0), 877 72 : ("dstore_1", 0), 878 73 : ("dstore_2", 0), 879 74 : ("dstore_3", 0), 880 75 : ("astore_0", 0), 881 76 : ("astore_1", 0), 882 77 : ("astore_2", 0), 883 78 : ("astore_3", 0), 884 79 : ("iastore", 0), 885 80 : ("lastore", 0), 886 81 : ("fastore", 0), 887 82 : ("dastore", 0), 888 83 : ("aastore", 0), 889 84 : ("bastore", 0), 890 85 : ("castore", 0), 891 86 : ("sastore", 0), 892 87 : ("pop", 0), 893 88 : ("pop2", 0), 894 89 : ("dup", 0), 895 90 : ("dup_x1", 0), 896 91 : ("dup_x2", 0), 897 92 : ("dup2", 0), 898 93 : ("dup2_x1", 0), 899 94 : ("dup2_x2", 0), 900 95 : ("swap", 0), 901 96 : ("iadd", 0), 902 97 : ("ladd", 0), 903 98 : ("fadd", 0), 904 99 : ("dadd", 0), 905 100 : ("isub", 0), 906 101 : ("lsub", 0), 907 102 : ("fsub", 0), 908 103 : ("dsub", 0), 909 104 : ("imul", 0), 910 105 : ("lmul", 0), 911 106 : ("fmul", 0), 912 107 : ("dmul", 0), 913 108 : ("idiv", 0), 914 109 : ("ldiv", 0), 915 110 : ("fdiv", 0), 916 111 : ("ddiv", 0), 917 112 : ("irem", 0), 918 113 : ("lrem", 0), 919 114 : ("frem", 0), 920 115 : ("drem", 0), 921 116 : ("ineg", 0), 922 117 : ("lneg", 0), 923 118 : ("fneg", 0), 924 119 : ("dneg", 0), 925 120 : ("ishl", 0), 926 121 : ("lshl", 0), 927 122 : ("ishr", 0), 928 123 : ("lshr", 0), 929 124 : ("iushr", 0), 930 125 : ("lushr", 0), 931 126 : ("iand", 0), 932 127 : ("land", 0), 933 128 : ("ior", 0), 934 129 : ("lor", 0), 935 130 : ("ixor", 0), 936 131 : ("lxor", 0), 937 132 : ("iinc", 2), 938 133 : ("i2l", 0), 939 134 : ("i2f", 0), 940 135 : ("i2d", 0), 941 136 : ("l2i", 0), 942 137 : ("l2f", 0), 943 138 : ("l2d", 0), 944 139 : ("f2i", 0), 945 140 : ("f2l", 0), 946 141 : ("f2d", 0), 947 142 : ("d2i", 0), 948 143 : ("d2l", 0), 949 144 : ("d2f", 0), 950 145 : ("i2b", 0), 951 146 : ("i2c", 0), 952 147 : ("i2s", 0), 953 148 : ("lcmp", 0), 954 149 : ("fcmpl", 0), 955 150 : ("fcmpg", 0), 956 151 : ("dcmpl", 0), 957 152 : ("dcmpg", 0), 958 153 : ("ifeq", 2), 959 154 : ("ifne", 2), 960 155 : ("iflt", 2), 961 156 : ("ifge", 2), 962 157 : ("ifgt", 2), 963 158 : ("ifle", 2), 964 159 : ("if_icmpeq", 2), 965 160 : ("if_icmpne", 2), 966 161 : ("if_icmplt", 2), 967 162 : ("if_icmpge", 2), 968 163 : ("if_icmpgt", 2), 969 164 : ("if_icmple", 2), 970 165 : ("if_acmpeq", 2), 971 166 : ("if_acmpne", 2), 972 167 : ("goto", 2), 973 168 : ("jsr", 2), 974 169 : ("ret", 1), 975 170 : ("tableswitch", None), # variable number of arguments 976 171 : ("lookupswitch", None), # variable number of arguments 977 172 : ("ireturn", 0), 978 173 : ("lreturn", 0), 979 174 : ("freturn", 0), 980 175 : ("dreturn", 0), 981 176 : ("areturn", 0), 982 177 : ("return", 0), 983 178 : ("getstatic", 2), 984 179 : ("putstatic", 2), 985 180 : ("getfield", 2), 986 181 : ("putfield", 2), 987 182 : ("invokevirtual", 2), 988 183 : ("invokespecial", 2), 989 184 : ("invokestatic", 2), 990 185 : ("invokeinterface", 4), 991 187 : ("new", 2), 992 188 : ("newarray", 1), 993 189 : ("anewarray", 2), 994 190 : ("arraylength", 0), 995 191 : ("athrow", 0), 996 192 : ("checkcast", 2), 997 193 : ("instanceof", 2), 998 194 : ("monitorenter", 0), 999 195 : ("monitorexit", 0), 1000 196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element 1001 197 : ("multianewarray", 3), 1002 198 : ("ifnull", 2), 1003 199 : ("ifnonnull", 2), 1004 200 : ("goto_w", 4), 1005 201 : ("jsr_w", 4), 1006 } 1007 1008 if __name__ == "__main__": 1009 import sys 1010 from classfile import ClassFile 1011 f = open(sys.argv[1]) 1012 c = ClassFile(f.read()) 1013 1014 # vim: tabstop=4 expandtab shiftwidth=4