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 from dis import opmap, cmp_op # for access to Python bytecode values and operators 11 from UserDict import UserDict 12 13 # Bytecode production classes. 14 15 class BytecodeWriter: 16 17 "A Python bytecode writer." 18 19 def __init__(self): 20 # A stack of loop block or exception block start positions. 21 self.blocks = [] 22 23 # A stack of exception block handler pointers. 24 self.exception_handlers = [] 25 26 # A dictionary mapping labels to jump instructions referencing such labels. 27 self.jumps = {} 28 29 # The output values, including "lazy" subvalues which will need evaluating. 30 self.output = [] 31 32 # The current Python bytecode instruction position. 33 self.position = 0 34 35 # Stack depth estimation. 36 self.stack_depth = 0 37 self.max_stack_depth = 0 38 39 # Mapping from values to indexes. 40 self.constants = {} 41 42 # Mapping from names to indexes. 43 # NOTE: This may be acquired from elsewhere. 44 #self.globals = {} 45 46 # Mapping from names to indexes. 47 self.names = {} 48 49 # A list of constants used as exception handler return addresses. 50 self.constants_for_exceptions = [] 51 52 def get_output(self): 53 output = [] 54 for element in self.output: 55 if isinstance(element, LazySubValue): 56 value = element.value 57 else: 58 value = element 59 output.append(chr(value)) 60 return "".join(output) 61 62 def get_constants(self): 63 l = self._get_list(self._invert(self.constants)) 64 result = [] 65 for i in l: 66 if isinstance(i, LazyValue): 67 result.append(i.get_value()) 68 else: 69 result.append(i) 70 return result 71 72 #def get_globals(self): 73 # return self._get_list(self._invert(self.globals)) 74 75 def get_names(self): 76 return self._get_list(self._invert(self.names)) 77 78 def _invert(self, d): 79 inverted = {} 80 for k, v in d.items(): 81 inverted[v] = k 82 return inverted 83 84 def _get_list(self, d): 85 l = [] 86 for i in range(0, len(d.keys())): 87 l.append(d[i]) 88 return l 89 90 # Administrative methods. 91 92 def update_stack_depth(self, change): 93 self.stack_depth += change 94 if self.stack_depth > self.max_stack_depth: 95 self.max_stack_depth = self.stack_depth 96 97 # Special methods. 98 99 def _write_value(self, value): 100 if isinstance(value, LazyValue): 101 # NOTE: Assume a 16-bit value. 102 self.output.append(value.values[0]) 103 self.output.append(value.values[1]) 104 self.position += 2 105 elif value <= 0xffff: 106 self.output.append(value & 0xff) 107 self.output.append((value & 0xff00) >> 8) 108 self.position += 2 109 else: 110 # NOTE: EXTENDED_ARG not yet supported. 111 raise ValueError, value 112 113 def setup_loop(self): 114 self.blocks.append(self.position) 115 self.output.append(opmap["SETUP_LOOP"]) 116 self.position += 1 117 self._write_value(0) # To be filled in later 118 119 def end_loop(self): 120 current_loop_start = self.blocks.pop() 121 self.jump_absolute(current_loop_start) 122 # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction. 123 # NOTE: 8-bit limit. 124 self.output[current_loop_start + 1] = self.position - current_loop_start - 3 125 self.output[current_loop_start + 2] = 0 126 self.pop_block() 127 128 def jump_to_label(self, status, name): 129 # Record the instruction using the jump. 130 jump_instruction = self.position 131 if status is None: 132 self.jump_forward() 133 elif status: 134 self.jump_if_true() 135 else: 136 self.jump_if_false() 137 # Record the following instruction, too. 138 if not self.jumps.has_key(name): 139 self.jumps[name] = [] 140 self.jumps[name].append((jump_instruction, self.position)) 141 142 def start_label(self, name): 143 # Fill in all jump instructions. 144 for jump_instruction, following_instruction in self.jumps[name]: 145 # NOTE: 8-bit limit. 146 self.output[jump_instruction + 1] = self.position - following_instruction 147 self.output[jump_instruction + 2] = 0 148 del self.jumps[name] 149 150 def load_const_ret(self, value): 151 self.constants_for_exceptions.append(value) 152 self.load_const(value) 153 154 def ret(self, index): 155 self.end_finally() 156 157 def setup_except(self, target): 158 self.blocks.append(self.position) 159 self.exception_handlers.append(target) 160 self.output.append(opmap["SETUP_EXCEPT"]) 161 self.position += 1 162 self._write_value(0) # To be filled in later 163 164 def setup_finally(self, target): 165 self.blocks.append(self.position) 166 self.exception_handlers.append(target) 167 self.output.append(opmap["SETUP_FINALLY"]) 168 self.position += 1 169 self._write_value(0) # To be filled in later 170 171 def end_exception(self): 172 current_exception_start = self.blocks.pop() 173 # Convert the "lazy" absolute value. 174 current_exception_target = self.exception_handlers.pop() 175 target = current_exception_target.get_value() 176 # NOTE: Using 3 as the assumed length of the SETUP_* instruction. 177 # NOTE: 8-bit limit. 178 self.output[current_exception_start + 1] = target - current_exception_start - 3 179 self.output[current_exception_start + 2] = 0 180 # NOTE: The POP_BLOCK instruction gets slipped in before this method is called. 181 182 # Complicated methods. 183 184 def load_const(self, value): 185 self.output.append(opmap["LOAD_CONST"]) 186 if not self.constants.has_key(value): 187 self.constants[value] = len(self.constants.keys()) 188 self.position += 1 189 self._write_value(self.constants[value]) 190 self.update_stack_depth(1) 191 192 def load_global(self, name): 193 self.output.append(opmap["LOAD_GLOBAL"]) 194 if not self.names.has_key(name): 195 self.names[name] = len(self.names.keys()) 196 self.position += 1 197 self._write_value(self.names[name]) 198 self.update_stack_depth(1) 199 200 def load_attr(self, name): 201 self.output.append(opmap["LOAD_ATTR"]) 202 if not self.names.has_key(name): 203 self.names[name] = len(self.names.keys()) 204 self.position += 1 205 self._write_value(self.names[name]) 206 207 def load_name(self, name): 208 self.output.append(opmap["LOAD_NAME"]) 209 if not self.names.has_key(name): 210 self.names[name] = len(self.names.keys()) 211 self.position += 1 212 self._write_value(self.names[name]) 213 self.update_stack_depth(1) 214 215 def load_fast(self, index): 216 self.output.append(opmap["LOAD_FAST"]) 217 self.position += 1 218 self._write_value(index) 219 self.update_stack_depth(1) 220 221 def store_attr(self, name): 222 self.output.append(opmap["STORE_ATTR"]) 223 if not self.names.has_key(name): 224 self.names[name] = len(self.names.keys()) 225 self.position += 1 226 self._write_value(self.names[name]) 227 self.update_stack_depth(-1) 228 229 def store_fast(self, index): 230 self.output.append(opmap["STORE_FAST"]) 231 self.position += 1 232 self._write_value(index) 233 self.update_stack_depth(-1) 234 235 # Normal bytecode generators. 236 237 def for_iter(self): 238 self.blocks.append(self.position) 239 self.output.append(opmap["FOR_ITER"]) 240 self.position += 1 241 self._write_value(0) # To be filled in later 242 self.update_stack_depth(1) 243 244 def jump_if_false(self, offset=0): 245 self.output.append(opmap["JUMP_IF_FALSE"]) 246 self.position += 1 247 self._write_value(offset) # May be filled in later 248 249 def jump_if_true(self, offset=0): 250 self.output.append(opmap["JUMP_IF_TRUE"]) 251 self.position += 1 252 self._write_value(offset) # May be filled in later 253 254 def jump_forward(self, offset=0): 255 self.output.append(opmap["JUMP_FORWARD"]) 256 self.position += 1 257 self._write_value(offset) # May be filled in later 258 259 def jump_absolute(self, address=0): 260 self.output.append(opmap["JUMP_ABSOLUTE"]) 261 self.position += 1 262 self._write_value(address) # May be filled in later 263 264 def build_tuple(self, count): 265 self.output.append(opmap["BUILD_TUPLE"]) 266 self.position += 1 267 self._write_value(count) 268 self.update_stack_depth(-(count - 1)) 269 270 def build_list(self, count): 271 self.output.append(opmap["BUILD_LIST"]) 272 self.position += 1 273 self._write_value(count) 274 self.update_stack_depth(-(count - 1)) 275 276 def pop_top(self): 277 self.output.append(opmap["POP_TOP"]) 278 self.position += 1 279 self.update_stack_depth(-1) 280 281 def dup_top(self): 282 self.output.append(opmap["DUP_TOP"]) 283 self.position += 1 284 self.update_stack_depth(1) 285 286 def rot_two(self): 287 self.output.append(opmap["ROT_TWO"]) 288 self.position += 1 289 290 def rot_three(self): 291 self.output.append(opmap["ROT_THREE"]) 292 self.position += 1 293 294 def rot_four(self): 295 self.output.append(opmap["ROT_FOUR"]) 296 self.position += 1 297 298 def call_function(self, count): 299 self.output.append(opmap["CALL_FUNCTION"]) 300 self.position += 1 301 self._write_value(count) 302 self.update_stack_depth(-count) 303 304 def binary_subscr(self): 305 self.output.append(opmap["BINARY_SUBSCR"]) 306 self.position += 1 307 self.update_stack_depth(-1) 308 309 def binary_add(self): 310 self.output.append(opmap["BINARY_ADD"]) 311 self.position += 1 312 self.update_stack_depth(-1) 313 314 def binary_divide(self): 315 self.output.append(opmap["BINARY_DIVIDE"]) 316 self.position += 1 317 self.update_stack_depth(-1) 318 319 def binary_multiply(self): 320 self.output.append(opmap["BINARY_MULTIPLY"]) 321 self.position += 1 322 self.update_stack_depth(-1) 323 324 def binary_modulo(self): 325 self.output.append(opmap["BINARY_MODULO"]) 326 self.position += 1 327 self.update_stack_depth(-1) 328 329 def binary_subtract(self): 330 self.output.append(opmap["BINARY_SUBTRACT"]) 331 self.position += 1 332 self.update_stack_depth(-1) 333 334 def binary_and(self): 335 self.output.append(opmap["BINARY_AND"]) 336 self.position += 1 337 self.update_stack_depth(-1) 338 339 def binary_or(self): 340 self.output.append(opmap["BINARY_XOR"]) 341 self.position += 1 342 self.update_stack_depth(-1) 343 344 def binary_lshift(self): 345 self.output.append(opmap["BINARY_LSHIFT"]) 346 self.position += 1 347 self.update_stack_depth(-1) 348 349 def binary_rshift(self): 350 self.output.append(opmap["BINARY_RSHIFT"]) 351 self.position += 1 352 self.update_stack_depth(-1) 353 354 def binary_xor(self): 355 self.output.append(opmap["BINARY_XOR"]) 356 self.position += 1 357 self.update_stack_depth(-1) 358 359 def compare_op(self, op): 360 self.output.append(opmap["COMPARE_OP"]) 361 self.position += 1 362 self._write_value(list(cmp_op).index(op)) 363 self.update_stack_depth(-1) 364 365 def return_value(self): 366 self.output.append(opmap["RETURN_VALUE"]) 367 self.position += 1 368 self.update_stack_depth(-1) 369 370 def raise_varargs(self, count): 371 self.output.append(opmap["RAISE_VARARGS"]) 372 self.position += 1 373 self._write_value(count) 374 375 def pop_block(self): 376 self.output.append(opmap["POP_BLOCK"]) 377 self.position += 1 378 379 def end_finally(self): 380 self.output.append(opmap["END_FINALLY"]) 381 self.position += 1 382 383 # Utility classes and functions. 384 385 class LazyDict(UserDict): 386 def __getitem__(self, key): 387 if not self.data.has_key(key): 388 # NOTE: Assume 16-bit value. 389 self.data[key] = LazyValue(2) 390 return self.data[key] 391 def __setitem__(self, key, value): 392 if self.data.has_key(key): 393 existing_value = self.data[key] 394 if isinstance(existing_value, LazyValue): 395 existing_value.set_value(value) 396 return 397 self.data[key] = value 398 399 class LazyValue: 400 def __init__(self, nvalues): 401 self.values = [] 402 for i in range(0, nvalues): 403 self.values.append(LazySubValue()) 404 def set_value(self, value): 405 # NOTE: Assume at least 16-bit value. No "filling" performed. 406 if value <= 0xffff: 407 self.values[0].set_value(value & 0xff) 408 self.values[1].set_value((value & 0xff00) >> 8) 409 else: 410 # NOTE: EXTENDED_ARG not yet supported. 411 raise ValueError, value 412 def get_value(self): 413 value = 0 414 values = self.values[:] 415 for i in range(0, len(values)): 416 value = (value << 8) + values.pop().value 417 return value 418 419 class LazySubValue: 420 def __init__(self): 421 self.value = 0 422 def set_value(self, value): 423 self.value = value 424 425 def signed(value, limit): 426 427 """ 428 Return the signed integer from the unsigned 'value', where 'limit' (a value 429 one greater than the highest possible positive integer) is used to determine 430 whether a negative or positive result is produced. 431 """ 432 433 d, r = divmod(value, limit) 434 if d == 1: 435 mask = limit * 2 - 1 436 return -1 - (value ^ mask) 437 else: 438 return value 439 440 def signed2(value): 441 return signed(value, 0x8000) 442 443 def signed4(value): 444 return signed(value, 0x80000000) 445 446 # Bytecode conversion. 447 448 class BytecodeReader: 449 450 "A generic Java bytecode reader." 451 452 def __init__(self, class_file): 453 self.class_file = class_file 454 self.position_mapping = LazyDict() 455 456 def process(self, code, exception_table, program): 457 self.java_position = 0 458 459 # Produce a structure which permits fast access to exception details. 460 exception_block_start = {} 461 exception_block_end = {} 462 exception_block_handler = {} 463 reversed_exception_table = exception_table[:] 464 reversed_exception_table.reverse() 465 466 # Later entries have wider coverage than earlier entries. 467 for exception in reversed_exception_table: 468 # Index start positions. 469 if not exception_block_start.has_key(exception.start_pc): 470 exception_block_start[exception.start_pc] = [] 471 exception_block_start[exception.start_pc].append(exception) 472 # Index end positions. 473 if not exception_block_end.has_key(exception.end_pc): 474 exception_block_end[exception.end_pc] = [] 475 exception_block_end[exception.end_pc].append(exception) 476 # Index handler positions. 477 if not exception_block_handler.has_key(exception.handler_pc): 478 exception_block_handler[exception.handler_pc] = [] 479 exception_block_handler[exception.handler_pc].append(exception) 480 481 # Process each instruction in the code. 482 while self.java_position < len(code): 483 self.position_mapping[self.java_position] = program.position 484 485 # Insert exception handling constructs. 486 for exception in exception_block_start.get(self.java_position, []): 487 # Note that the absolute position is used. 488 if exception.catch_type == 0: 489 program.setup_finally(self.position_mapping[exception.handler_pc]) 490 else: 491 program.setup_except(self.position_mapping[exception.handler_pc]) 492 493 # Insert exception handler end details. 494 for exception in exception_block_end.get(self.java_position, []): 495 program.end_exception() 496 497 # Where handlers are begun, do not produce equivalent bytecode since 498 # the first handler instruction typically involves saving a local 499 # variable that is not applicable to the Python VM. 500 #if not exception_block_handler.get(self.java_position, []): 501 502 # Process the bytecode at the current position. 503 bytecode = ord(code[self.java_position]) 504 mnemonic, number_of_arguments = self.java_bytecodes[bytecode] 505 number_of_arguments = self.process_bytecode(mnemonic, number_of_arguments, code, program) 506 next_java_position = self.java_position + 1 + number_of_arguments 507 508 # Insert exception handler end instructions. 509 for exception in exception_block_end.get(next_java_position, []): 510 program.pop_block() 511 512 # Only advance the JVM position after sneaking in extra Python 513 # instructions. 514 self.java_position = next_java_position 515 516 def process_bytecode(self, mnemonic, number_of_arguments, code, program): 517 if number_of_arguments is not None: 518 arguments = [] 519 for j in range(0, number_of_arguments): 520 arguments.append(ord(code[self.java_position + 1 + j])) 521 522 # Call the handler. 523 getattr(self, mnemonic)(arguments, program) 524 return number_of_arguments 525 else: 526 # Call the handler. 527 return getattr(self, mnemonic)(code[self.java_position+1:], program) 528 529 java_bytecodes = { 530 # code : (mnemonic, number of following bytes, change in stack) 531 0 : ("nop", 0), 532 1 : ("aconst_null", 0), 533 2 : ("iconst_m1", 0), 534 3 : ("iconst_0", 0), 535 4 : ("iconst_1", 0), 536 5 : ("iconst_2", 0), 537 6 : ("iconst_3", 0), 538 7 : ("iconst_4", 0), 539 8 : ("iconst_5", 0), 540 9 : ("lconst_0", 0), 541 10 : ("lconst_1", 0), 542 11 : ("fconst_0", 0), 543 12 : ("fconst_1", 0), 544 13 : ("fconst_2", 0), 545 14 : ("dconst_0", 0), 546 15 : ("dconst_1", 0), 547 16 : ("bipush", 1), 548 17 : ("sipush", 2), 549 18 : ("ldc", 1), 550 19 : ("ldc_w", 2), 551 20 : ("ldc2_w", 2), 552 21 : ("iload", 1), 553 22 : ("lload", 1), 554 23 : ("fload", 1), 555 24 : ("dload", 1), 556 25 : ("aload", 1), 557 26 : ("iload_0", 0), 558 27 : ("iload_1", 0), 559 28 : ("iload_2", 0), 560 29 : ("iload_3", 0), 561 30 : ("lload_0", 0), 562 31 : ("lload_1", 0), 563 32 : ("lload_2", 0), 564 33 : ("lload_3", 0), 565 34 : ("fload_0", 0), 566 35 : ("fload_1", 0), 567 36 : ("fload_2", 0), 568 37 : ("fload_3", 0), 569 38 : ("dload_0", 0), 570 39 : ("dload_1", 0), 571 40 : ("dload_2", 0), 572 41 : ("dload_3", 0), 573 42 : ("aload_0", 0), 574 43 : ("aload_1", 0), 575 44 : ("aload_2", 0), 576 45 : ("aload_3", 0), 577 46 : ("iaload", 0), 578 47 : ("laload", 0), 579 48 : ("faload", 0), 580 49 : ("daload", 0), 581 50 : ("aaload", 0), 582 51 : ("baload", 0), 583 52 : ("caload", 0), 584 53 : ("saload", 0), 585 54 : ("istore", 1), 586 55 : ("lstore", 1), 587 56 : ("fstore", 1), 588 57 : ("dstore", 1), 589 58 : ("astore", 1), 590 59 : ("istore_0", 0), 591 60 : ("istore_1", 0), 592 61 : ("istore_2", 0), 593 62 : ("istore_3", 0), 594 63 : ("lstore_0", 0), 595 64 : ("lstore_1", 0), 596 65 : ("lstore_2", 0), 597 66 : ("lstore_3", 0), 598 67 : ("fstore_0", 0), 599 68 : ("fstore_1", 0), 600 69 : ("fstore_2", 0), 601 70 : ("fstore_3", 0), 602 71 : ("dstore_0", 0), 603 72 : ("dstore_1", 0), 604 73 : ("dstore_2", 0), 605 74 : ("dstore_3", 0), 606 75 : ("astore_0", 0), 607 76 : ("astore_1", 0), 608 77 : ("astore_2", 0), 609 78 : ("astore_3", 0), 610 79 : ("iastore", 0), 611 80 : ("lastore", 0), 612 81 : ("fastore", 0), 613 82 : ("dastore", 0), 614 83 : ("aastore", 0), 615 84 : ("bastore", 0), 616 85 : ("castore", 0), 617 86 : ("sastore", 0), 618 87 : ("pop", 0), 619 88 : ("pop2", 0), 620 89 : ("dup", 0), 621 90 : ("dup_x1", 0), 622 91 : ("dup_x2", 0), 623 92 : ("dup2", 0), 624 93 : ("dup2_x1", 0), 625 94 : ("dup2_x2", 0), 626 95 : ("swap", 0), 627 96 : ("iadd", 0), 628 97 : ("ladd", 0), 629 98 : ("fadd", 0), 630 99 : ("dadd", 0), 631 100 : ("isub", 0), 632 101 : ("lsub", 0), 633 102 : ("fsub", 0), 634 103 : ("dsub", 0), 635 104 : ("imul", 0), 636 105 : ("lmul", 0), 637 106 : ("fmul", 0), 638 107 : ("dmul", 0), 639 108 : ("idiv", 0), 640 109 : ("ldiv", 0), 641 110 : ("fdiv", 0), 642 111 : ("ddiv", 0), 643 112 : ("irem", 0), 644 113 : ("lrem", 0), 645 114 : ("frem", 0), 646 115 : ("drem", 0), 647 116 : ("ineg", 0), 648 117 : ("lneg", 0), 649 118 : ("fneg", 0), 650 119 : ("dneg", 0), 651 120 : ("ishl", 0), 652 121 : ("lshl", 0), 653 122 : ("ishr", 0), 654 123 : ("lshr", 0), 655 124 : ("iushr", 0), 656 125 : ("lushr", 0), 657 126 : ("iand", 0), 658 127 : ("land", 0), 659 128 : ("ior", 0), 660 129 : ("lor", 0), 661 130 : ("ixor", 0), 662 131 : ("lxor", 0), 663 132 : ("iinc", 2), 664 133 : ("i2l", 0), 665 134 : ("i2f", 0), 666 135 : ("i2d", 0), 667 136 : ("l2i", 0), 668 137 : ("l2f", 0), 669 138 : ("l2d", 0), 670 139 : ("f2i", 0), 671 140 : ("f2l", 0), 672 141 : ("f2d", 0), 673 142 : ("d2i", 0), 674 143 : ("d2l", 0), 675 144 : ("d2f", 0), 676 145 : ("i2b", 0), 677 146 : ("i2c", 0), 678 147 : ("i2s", 0), 679 148 : ("lcmp", 0), 680 149 : ("fcmpl", 0), 681 150 : ("fcmpg", 0), 682 151 : ("dcmpl", 0), 683 152 : ("dcmpg", 0), 684 153 : ("ifeq", 2), 685 154 : ("ifne", 2), 686 155 : ("iflt", 2), 687 156 : ("ifge", 2), 688 157 : ("ifgt", 2), 689 158 : ("ifle", 2), 690 159 : ("if_icmpeq", 2), 691 160 : ("if_icmpne", 2), 692 161 : ("if_icmplt", 2), 693 162 : ("if_icmpge", 2), 694 163 : ("if_icmpgt", 2), 695 164 : ("if_icmple", 2), 696 165 : ("if_acmpeq", 2), 697 166 : ("if_acmpne", 2), 698 167 : ("goto", 2), 699 168 : ("jsr", 2), 700 169 : ("ret", 1), 701 170 : ("tableswitch", None), # variable number of arguments 702 171 : ("lookupswitch", None), # variable number of arguments 703 172 : ("ireturn", 0), 704 173 : ("lreturn", 0), 705 174 : ("freturn", 0), 706 175 : ("dreturn", 0), 707 176 : ("areturn", 0), 708 177 : ("return_", 0), 709 178 : ("getstatic", 2), 710 179 : ("putstatic", 2), 711 180 : ("getfield", 2), 712 181 : ("putfield", 2), 713 182 : ("invokevirtual", 2), 714 183 : ("invokespecial", 2), 715 184 : ("invokestatic", 2), 716 185 : ("invokeinterface", 4), 717 187 : ("new", 2), 718 188 : ("newarray", 1), 719 189 : ("anewarray", 2), 720 190 : ("arraylength", 0), 721 191 : ("athrow", 0), 722 192 : ("checkcast", 2), 723 193 : ("instanceof", 2), 724 194 : ("monitorenter", 0), 725 195 : ("monitorexit", 0), 726 196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element 727 197 : ("multianewarray", 3), 728 198 : ("ifnull", 2), 729 199 : ("ifnonnull", 2), 730 200 : ("goto_w", 4), 731 201 : ("jsr_w", 4), 732 } 733 734 class BytecodeDisassembler(BytecodeReader): 735 736 "A Java bytecode disassembler." 737 738 bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()] 739 740 def __getattr__(self, name): 741 if name in self.bytecode_methods: 742 print name, 743 return self.generic 744 else: 745 raise AttributeError, name 746 747 def generic(self, arguments, program): 748 print arguments 749 750 class BytecodeDisassemblerProgram: 751 position = 0 752 def setup_except(self, target): 753 print "(setup_except %s)" % target 754 def setup_finally(self, target): 755 print "(setup_finally %s)" % target 756 def end_exception(self): 757 print "(end_exception)" 758 def pop_block(self): 759 print "(pop_block)" 760 761 class BytecodeTranslator(BytecodeReader): 762 763 "A Java bytecode translator which uses a Python bytecode writer." 764 765 def aaload(self, arguments, program): 766 # NOTE: No type checking performed. 767 program.binary_subscr() 768 769 def aastore(self, arguments, program): 770 # NOTE: No type checking performed. 771 # Stack: arrayref, index, value 772 program.rot_three() # Stack: value, arrayref, index 773 program.store_subscr() 774 775 def aconst_null(self, arguments, program): 776 program.load_global(None) 777 778 def aload(self, arguments, program): 779 program.load_fast(arguments[0]) 780 781 def aload_0(self, arguments, program): 782 program.load_fast(0) 783 784 def aload_1(self, arguments, program): 785 program.load_fast(1) 786 787 def aload_2(self, arguments, program): 788 program.load_fast(2) 789 790 def aload_3(self, arguments, program): 791 program.load_fast(3) 792 793 def anewarray(self, arguments, program): 794 # NOTE: Does not raise NegativeArraySizeException. 795 # NOTE: Not using the index to type the list/array. 796 index = (arguments[0] << 8) + arguments[1] 797 self._newarray(program) 798 799 def _newarray(self, program): 800 program.build_list() # Stack: count, list 801 program.rot_two() # Stack: list, count 802 program.setup_loop() 803 program.load_global("range") 804 program.load_const(0) # Stack: list, count, range, 0 805 program.rot_three() # Stack: list, 0, count, range 806 program.rot_three() # Stack: list, range, 0, count 807 program.call_function(2) # Stack: list, range_list 808 program.get_iter() # Stack: list, iter 809 program.for_iter() # Stack: list, iter, value 810 program.pop_top() # Stack: list, iter 811 program.rot_two() # Stack: iter, list 812 program.dup_top() # Stack: iter, list, list 813 program.load_attr("append") # Stack: iter, list, append 814 program.load_global(None) # Stack: iter, list, append, None 815 program.call_function(1) # Stack: iter, list, None 816 program.pop_top() # Stack: iter, list 817 program.rot_two() # Stack: list, iter 818 program.end_loop() # Back to for_iter above 819 820 def areturn(self, arguments, program): 821 program.return_value() 822 823 def arraylength(self, arguments, program): 824 program.load_global("len") # Stack: arrayref, len 825 program.rot_two() # Stack: len, arrayref 826 program.call_function(1) 827 828 def astore(self, arguments, program): 829 program.store_fast(arguments[0]) 830 831 def astore_0(self, arguments, program): 832 program.store_fast(0) 833 834 def astore_1(self, arguments, program): 835 program.store_fast(1) 836 837 def astore_2(self, arguments, program): 838 program.store_fast(2) 839 840 def astore_3(self, arguments, program): 841 program.store_fast(3) 842 843 def athrow(self, arguments, program): 844 # NOTE: NullPointerException not raised where null/None is found on the stack. 845 program.raise_varargs(1) 846 847 baload = aaload 848 bastore = aastore 849 850 def bipush(self, arguments, program): 851 program.load_const(arguments[0]) 852 853 caload = aaload 854 castore = aastore 855 856 def checkcast(self, arguments, program): 857 index = (arguments[0] << 8) + arguments[1] 858 target_name = self.class_file.constants[index - 1].get_name() 859 # NOTE: Using the string version of the name which may contain incompatible characters. 860 target_components = str(target_name).split("/") 861 862 program.dup_top() # Stack: objectref, objectref 863 program.load_global("isinstance") # Stack: objectref, objectref, isinstance 864 program.rot_two() # Stack: objectref, isinstance, objectref 865 program.load_global(target_components[0]) 866 for target_component in target_components[1:]: 867 program.load_attr(target_component) 868 program.call_function(2) # Stack: objectref 869 870 def d2f(self, arguments, program): 871 pass 872 873 def d2i(self, arguments, program): 874 program.load_global("int") # Stack: value, int 875 program.rot_two() # Stack: int, value 876 program.call_function(1) # Stack: result 877 878 d2l = d2i # Preserving Java semantics 879 880 def dadd(self, arguments, program): 881 # NOTE: No type checking performed. 882 program.binary_add() 883 884 daload = aaload 885 dastore = aastore 886 887 def dcmpg(self, arguments, program): 888 # NOTE: No type checking performed. 889 program.compare_op(">") 890 891 def dcmpl(self, arguments, program): 892 # NOTE: No type checking performed. 893 program.compare_op("<") 894 895 def dconst_0(self, arguments, program): 896 program.load_const(0.0) 897 898 def dconst_1(self, arguments, program): 899 program.load_const(1.0) 900 901 def ddiv(self, arguments, program): 902 # NOTE: No type checking performed. 903 program.binary_divide() 904 905 dload = aload 906 dload_0 = aload_0 907 dload_1 = aload_1 908 dload_2 = aload_2 909 dload_3 = aload_3 910 911 def dmul(self, arguments, program): 912 # NOTE: No type checking performed. 913 program.binary_multiply() 914 915 def dneg(self, arguments, program): 916 # NOTE: No type checking performed. 917 program.unary_negative() 918 919 def drem(self, arguments, program): 920 # NOTE: No type checking performed. 921 program.binary_modulo() 922 923 dreturn = areturn 924 dstore = astore 925 dstore_0 = astore_0 926 dstore_1 = astore_1 927 dstore_2 = astore_2 928 dstore_3 = astore_3 929 930 def dsub(self, arguments, program): 931 # NOTE: No type checking performed. 932 program.binary_subtract() 933 934 def dup(self, arguments, program): 935 program.dup_top() 936 937 def dup_x1(self, arguments, program): 938 # Ignoring computational type categories. 939 program.dup_top() 940 program.rot_three() 941 942 def dup_x2(self, arguments, program): 943 # Ignoring computational type categories. 944 program.dup_top() 945 program.rot_four() 946 947 dup2 = dup # Ignoring computational type categories 948 dup2_x1 = dup_x1 # Ignoring computational type categories 949 dup2_x2 = dup_x2 # Ignoring computational type categories 950 951 def f2d(self, arguments, program): 952 pass # Preserving Java semantics 953 954 def f2i(self, arguments, program): 955 program.load_global("int") # Stack: value, int 956 program.rot_two() # Stack: int, value 957 program.call_function(1) # Stack: result 958 959 f2l = f2i # Preserving Java semantics 960 fadd = dadd 961 faload = daload 962 fastore = dastore 963 fcmpg = dcmpg 964 fcmpl = dcmpl 965 fconst_0 = dconst_0 966 fconst_1 = dconst_1 967 968 def fconst_2(self, arguments, program): 969 program.load_const(2.0) 970 971 fdiv = ddiv 972 fload = dload 973 fload_0 = dload_0 974 fload_1 = dload_1 975 fload_2 = dload_2 976 fload_3 = dload_3 977 fmul = dmul 978 fneg = dneg 979 frem = drem 980 freturn = dreturn 981 fstore = dstore 982 fstore_0 = dstore_0 983 fstore_1 = dstore_1 984 fstore_2 = dstore_2 985 fstore_3 = dstore_3 986 fsub = dsub 987 988 def getfield(self, arguments, program): 989 index = (arguments[0] << 8) + arguments[1] 990 target_name = self.class_file.constants[index - 1].get_name() 991 # NOTE: Using the string version of the name which may contain incompatible characters. 992 program.load_attr(str(target_name)) 993 994 def getstatic(self, arguments, program): 995 index = (arguments[0] << 8) + arguments[1] 996 target_name = self.class_file.constants[index - 1].get_name() 997 program.load_name("self") 998 program.load_attr("__class__") 999 # NOTE: Using the string version of the name which may contain incompatible characters. 1000 program.load_attr(str(target_name)) 1001 1002 def goto(self, arguments, program): 1003 offset = signed2((arguments[0] << 8) + arguments[1]) 1004 java_absolute = self.java_position + offset 1005 program.jump_absolute(self.position_mapping[java_absolute]) 1006 1007 def goto_w(self, arguments, program): 1008 offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]) 1009 java_absolute = self.java_position + offset 1010 program.jump_absolute(self.position_mapping[java_absolute]) 1011 1012 def i2b(self, arguments, program): 1013 pass 1014 1015 def i2c(self, arguments, program): 1016 program.load_global("chr") # Stack: value, chr 1017 program.rot_two() # Stack: chr, value 1018 program.call_function(1) # Stack: result 1019 1020 def i2d(self, arguments, program): 1021 program.load_global("float") # Stack: value, float 1022 program.rot_two() # Stack: float, value 1023 program.call_function(1) # Stack: result 1024 1025 i2f = i2d # Not distinguishing between float and double 1026 1027 def i2l(self, arguments, program): 1028 pass # Preserving Java semantics 1029 1030 def i2s(self, arguments, program): 1031 pass # Not distinguishing between int and short 1032 1033 iadd = fadd 1034 iaload = faload 1035 1036 def iand(self, arguments, program): 1037 # NOTE: No type checking performed. 1038 program.binary_and() 1039 1040 iastore = fastore 1041 1042 def iconst_m1(self, arguments, program): 1043 program.load_const(-1) 1044 1045 def iconst_0(self, arguments, program): 1046 program.load_const(0) 1047 1048 def iconst_1(self, arguments, program): 1049 program.load_const(1) 1050 1051 def iconst_2(self, arguments, program): 1052 program.load_const(2) 1053 1054 def iconst_3(self, arguments, program): 1055 program.load_const(3) 1056 1057 def iconst_4(self, arguments, program): 1058 program.load_const(4) 1059 1060 def iconst_5(self, arguments, program): 1061 program.load_const(5) 1062 1063 idiv = fdiv 1064 1065 def _if_xcmpx(self, arguments, program, op): 1066 offset = signed2((arguments[0] << 8) + arguments[1]) 1067 java_absolute = self.java_position + offset 1068 program.compare_op(op) 1069 program.jump_to_label(0, "next") # skip if false 1070 program.goto(offset) 1071 program.start_label("next") 1072 1073 def if_acmpeq(self, arguments, program): 1074 # NOTE: No type checking performed. 1075 self._if_xcmpx(arguments, program, "is") 1076 1077 def if_acmpne(self, arguments, program): 1078 # NOTE: No type checking performed. 1079 self._if_xcmpx(arguments, program, "is not") 1080 1081 def if_icmpeq(self, arguments, program): 1082 # NOTE: No type checking performed. 1083 self._if_xcmpx(arguments, program, "==") 1084 1085 def if_icmpne(self, arguments, program): 1086 # NOTE: No type checking performed. 1087 self._if_xcmpx(arguments, program, "!=") 1088 1089 def if_icmplt(self, arguments, program): 1090 # NOTE: No type checking performed. 1091 self._if_xcmpx(arguments, program, "<") 1092 1093 def if_icmpge(self, arguments, program): 1094 # NOTE: No type checking performed. 1095 self._if_xcmpx(arguments, program, ">=") 1096 1097 def if_icmpgt(self, arguments, program): 1098 # NOTE: No type checking performed. 1099 self._if_xcmpx(arguments, program, ">") 1100 1101 def if_icmple(self, arguments, program): 1102 # NOTE: No type checking performed. 1103 self._if_xcmpx(arguments, program, "<=") 1104 1105 def ifeq(self, arguments, program): 1106 # NOTE: No type checking performed. 1107 program.load_const(0) 1108 self._if_xcmpx(arguments, program, "==") 1109 1110 def ifne(self, arguments, program): 1111 # NOTE: No type checking performed. 1112 program.load_const(0) 1113 self._if_xcmpx(arguments, program, "!=") 1114 1115 def iflt(self, arguments, program): 1116 # NOTE: No type checking performed. 1117 program.load_const(0) 1118 self._if_xcmpx(arguments, program, "<") 1119 1120 def ifge(self, arguments, program): 1121 # NOTE: No type checking performed. 1122 program.load_const(0) 1123 self._if_xcmpx(arguments, program, ">=") 1124 1125 def ifgt(self, arguments, program): 1126 # NOTE: No type checking performed. 1127 program.load_const(0) 1128 self._if_xcmpx(arguments, program, ">") 1129 1130 def ifle(self, arguments, program): 1131 # NOTE: No type checking performed. 1132 program.load_const(0) 1133 self._if_xcmpx(arguments, program, "<=") 1134 1135 def ifnonnull(self, arguments, program): 1136 # NOTE: No type checking performed. 1137 program.load_const(None) 1138 self._if_xcmpx(arguments, program, "is not") 1139 1140 def ifnull(self, arguments, program): 1141 # NOTE: No type checking performed. 1142 program.load_const(None) 1143 self._if_xcmpx(arguments, program, "is") 1144 1145 def iinc(self, arguments, program): 1146 # NOTE: No type checking performed. 1147 program.load_fast(arguments[0]) 1148 program.load_const(arguments[1]) 1149 program.binary_add() 1150 1151 iload = fload 1152 iload_0 = fload_0 1153 iload_1 = fload_1 1154 iload_2 = fload_2 1155 iload_3 = fload_3 1156 imul = fmul 1157 ineg = fneg 1158 1159 def instanceof(self, arguments, program): 1160 index = (arguments[0] << 8) + arguments[1] 1161 target_name = self.class_file.constants[index - 1].get_name() 1162 # NOTE: Using the string version of the name which may contain incompatible characters. 1163 target_components = str(target_name).split("/") 1164 1165 program.load_global("isinstance") # Stack: objectref, isinstance 1166 program.rot_two() # Stack: isinstance, objectref 1167 program.load_global(target_components[0]) 1168 for target_component in target_components[1:]: 1169 program.load_attr(target_component) 1170 program.call_function(2) # Stack: result 1171 1172 def _invoke(self, target_name, program): 1173 # NOTE: Using the string version of the name which may contain incompatible characters. 1174 program.load_attr(str(target_name)) # Stack: tuple, method 1175 program.rot_two() # Stack: method, tuple 1176 program.load_global("apply") # Stack: method, tuple, apply 1177 program.rot_three() # Stack: apply, method, tuple 1178 program.call_function(2) 1179 1180 def invokeinterface(self, arguments, program): 1181 # NOTE: This implementation does not perform the necessary checks for 1182 # NOTE: signature-based polymorphism. 1183 # NOTE: Java rules not specifically obeyed. 1184 index = (arguments[0] << 8) + arguments[1] 1185 count = arguments[2] 1186 target_name = self.class_file.constants[index - 1].get_name() 1187 # Stack: objectref, arg1, arg2, ... 1188 program.build_tuple(count) # Stack: objectref, tuple 1189 program.rot_two() # Stack: tuple, objectref 1190 self._invoke(target_name, program) 1191 1192 def invokespecial(self, arguments, program): 1193 # NOTE: This implementation does not perform the necessary checks for 1194 # NOTE: signature-based polymorphism. 1195 # NOTE: Java rules not specifically obeyed. 1196 index = (arguments[0] << 8) + arguments[1] 1197 target = self.class_file.constants[index - 1] 1198 target_name = target.get_name() 1199 # Get the number of parameters from the descriptor. 1200 count = len(target.get_descriptor()[0]) 1201 # Stack: objectref, arg1, arg2, ... 1202 program.build_tuple(count + 1) # Stack: tuple 1203 # Use the class to provide access to static methods. 1204 program.load_name("self") # Stack: tuple, self 1205 program.load_attr("__class__") # Stack: tuple, class 1206 program.load_attr("__bases__") # Stack: tuple, base-classes 1207 program.dup_top() # Stack: tuple, base-classes, base-classes 1208 program.load_global("len") # Stack: tuple, base-classes, base-classes, len 1209 program.rot_two() # Stack: tuple, base-classes, len, base-classes 1210 program.call_function(1) # Stack: tuple, base-classes, count 1211 program.load_const(0) # Stack: tuple, base-classes, count, 0 1212 program.compare_op("==") # Stack: tuple, base-classes, result 1213 program.jump_to_label(1, "next") 1214 program.pop_top() # Stack: tuple, base-classes 1215 program.load_const(0) # Stack: tuple, base-classes, 0 1216 program.binary_subscr() # Stack: tuple, superclass 1217 self._invoke(target_name, program) 1218 program.jump_to_label(None, "next2") 1219 program.start_label("next") 1220 program.pop_top() # Stack: tuple, base-classes 1221 program.pop_top() # Stack: tuple 1222 program.pop_top() # Stack: 1223 program.start_label("next2") 1224 1225 def invokestatic(self, arguments, program): 1226 # NOTE: This implementation does not perform the necessary checks for 1227 # NOTE: signature-based polymorphism. 1228 # NOTE: Java rules not specifically obeyed. 1229 index = (arguments[0] << 8) + arguments[1] 1230 target = self.class_file.constants[index - 1] 1231 target_name = target.get_name() 1232 # Get the number of parameters from the descriptor. 1233 count = len(target.get_descriptor()[0]) 1234 # Stack: arg1, arg2, ... 1235 program.build_tuple(count) # Stack: tuple 1236 # Use the class to provide access to static methods. 1237 program.load_name("self") # Stack: tuple, self 1238 program.load_attr("__class__") # Stack: tuple, class 1239 self._invoke(target_name, program) 1240 1241 invokevirtual = invokeinterface # Ignoring Java rules 1242 1243 def ior(self, arguments, program): 1244 # NOTE: No type checking performed. 1245 program.binary_or() 1246 1247 irem = frem 1248 ireturn = freturn 1249 1250 def ishl(self, arguments, program): 1251 # NOTE: No type checking performed. 1252 # NOTE: Not verified. 1253 program.binary_lshift() 1254 1255 def ishr(self, arguments, program): 1256 # NOTE: No type checking performed. 1257 # NOTE: Not verified. 1258 program.binary_rshift() 1259 1260 istore = fstore 1261 istore_0 = fstore_0 1262 istore_1 = fstore_1 1263 istore_2 = fstore_2 1264 istore_3 = fstore_3 1265 isub = fsub 1266 iushr = ishr # Ignoring distinctions between arithmetic and logical shifts 1267 1268 def ixor(self, arguments, program): 1269 # NOTE: No type checking performed. 1270 program.binary_xor() 1271 1272 def jsr(self, arguments, program): 1273 offset = signed2((arguments[0] << 8) + arguments[1]) 1274 java_absolute = self.java_position + offset 1275 # Store the address of the next instruction. 1276 program.load_const_ret(self.position_mapping[self.java_position + 3]) 1277 program.jump_absolute(self.position_mapping[java_absolute]) 1278 1279 def jsr_w(self, arguments, program): 1280 offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]) 1281 java_absolute = self.java_position + offset 1282 # Store the address of the next instruction. 1283 program.load_const_ret(self.position_mapping[self.java_position + 5]) 1284 program.jump_absolute(self.position_mapping[java_absolute]) 1285 1286 l2d = i2d 1287 l2f = i2f 1288 1289 def l2i(self, arguments, program): 1290 pass # Preserving Java semantics 1291 1292 ladd = iadd 1293 laload = iaload 1294 land = iand 1295 lastore = iastore 1296 1297 def lcmp(self, arguments, program): 1298 # NOTE: No type checking performed. 1299 program.dup_topx(2) # Stack: value1, value2, value1, value2 1300 program.compare_op(">") # Stack: value1, value2, result 1301 program.jump_to_label(0, "equals") 1302 # True - produce result and branch. 1303 program.pop_top() # Stack: value1, value2 1304 program.pop_top() # Stack: value1 1305 program.pop_top() # Stack: 1306 program.load_const(1) # Stack: 1 1307 program.jump_to_label(None, "next") 1308 # False - test equality. 1309 program.start_label("equals") 1310 program.pop_top() # Stack: value1, value2 1311 program.dup_topx(2) # Stack: value1, value2, value1, value2 1312 program.compare_op("==") # Stack: value1, value2, result 1313 program.jump_to_label(0, "less") 1314 # True - produce result and branch. 1315 program.pop_top() # Stack: value1, value2 1316 program.pop_top() # Stack: value1 1317 program.pop_top() # Stack: 1318 program.load_const(0) # Stack: 0 1319 program.jump_to_label(None, "next") 1320 # False - produce result. 1321 program.start_label("less") 1322 program.pop_top() # Stack: value1, value2 1323 program.pop_top() # Stack: value1 1324 program.pop_top() # Stack: 1325 program.load_const(-1) # Stack: -1 1326 program.start_label("next") 1327 1328 lconst_0 = iconst_0 1329 lconst_1 = iconst_1 1330 1331 def ldc(self, arguments, program): 1332 program.load_const(self.class_file.constants[arguments[0] - 1]) 1333 1334 def ldc_w(self, arguments, program): 1335 program.load_const(self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1]) 1336 1337 ldc2_w = ldc_w 1338 ldiv = idiv 1339 lload = iload 1340 lload_0 = iload_0 1341 lload_1 = iload_1 1342 lload_2 = iload_2 1343 lload_3 = iload_3 1344 lmul = imul 1345 lneg = ineg 1346 1347 def lookupswitch(self, arguments, program): 1348 # Find the offset to the next 4 byte boundary in the code. 1349 d, r = divmod(self.java_position, 4) 1350 to_boundary = (4 - r) % 4 1351 # Get the pertinent arguments. 1352 arguments = arguments[to_boundary:] 1353 default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3] 1354 npairs = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7] 1355 # Process the pairs. 1356 # NOTE: This is not the most optimal implementation. 1357 pair_index = 8 1358 for pair in range(0, npairs): 1359 match = ((arguments[pair_index] << 24) + (arguments[pair_index + 1] << 16) + 1360 (arguments[pair_index + 2] << 8) + arguments[pair_index + 3]) 1361 offset = signed4((arguments[pair_index + 4] << 24) + (arguments[pair_index + 5] << 16) + 1362 (arguments[pair_index + 6] << 8) + arguments[pair_index + 7]) 1363 # Calculate the branch target. 1364 java_absolute = self.java_position + offset 1365 # Generate branching code. 1366 program.dup_top() # Stack: key, key 1367 program.load_const(match) # Stack: key, key, match 1368 program.compare_op("==") # Stack: key, result 1369 program.jump_to_label(0, "end") 1370 program.pop_top() # Stack: key 1371 program.pop_top() # Stack: 1372 program.jump_absolute(self.position_mapping[java_absolute]) 1373 # Generate the label for the end of the branching code. 1374 program.start_label("end") 1375 program.pop_top() # Stack: key 1376 # Update the index. 1377 pair_index += 8 1378 # Generate the default. 1379 java_absolute = self.java_position + default 1380 program.jump_absolute(self.position_mapping[java_absolute]) 1381 1382 lor = ior 1383 lrem = irem 1384 lreturn = ireturn 1385 lshl = ishl 1386 lshr = ishr 1387 lstore = istore 1388 lstore_0 = istore_0 1389 lstore_1 = istore_1 1390 lstore_2 = istore_2 1391 lstore_3 = istore_3 1392 lsub = isub 1393 lushr = iushr 1394 lxor = ixor 1395 1396 def monitorenter(self, arguments, program): 1397 # NOTE: To be implemented. 1398 pass 1399 1400 def monitorexit(self, arguments, program): 1401 # NOTE: To be implemented. 1402 pass 1403 1404 def multianewarray(self, arguments, program): 1405 # NOTE: To be implemented. 1406 pass 1407 1408 def new(self, arguments, program): 1409 # This operation is considered to be the same as the calling of the 1410 # initialisation method of the given class with no arguments. 1411 index = (arguments[0] << 8) + arguments[1] 1412 target_name = self.class_file.constants[index - 1].get_name() 1413 # NOTE: Using the string version of the name which may contain incompatible characters. 1414 program.load_global(str(target_name)) 1415 program.call_function(0) 1416 1417 def newarray(self, arguments, program): 1418 # NOTE: Does not raise NegativeArraySizeException. 1419 # NOTE: Not using the arguments to type the list/array. 1420 self._newarray(program) 1421 1422 def nop(self, arguments, program): 1423 pass 1424 1425 def pop(self, arguments, program): 1426 program.pop_top() 1427 1428 pop2 = pop # ignoring Java stack value distinctions 1429 1430 def putfield(self, arguments, program): 1431 index = (arguments[0] << 8) + arguments[1] 1432 target_name = self.class_file.constants[index - 1].get_name() 1433 program.rot_two() 1434 # NOTE: Using the string version of the name which may contain incompatible characters. 1435 program.store_attr(str(target_name)) 1436 1437 def putstatic(self, arguments, program): 1438 index = (arguments[0] << 8) + arguments[1] 1439 target_name = self.class_file.constants[index - 1].get_name() 1440 program.load_name("self") 1441 program.load_attr("__class__") 1442 # NOTE: Using the string version of the name which may contain incompatible characters. 1443 program.store_attr(str(target_name)) 1444 1445 def ret(self, arguments, program): 1446 program.ret(arguments[0]) 1447 1448 def return_(self, arguments, program): 1449 program.load_const(None) 1450 program.return_value() 1451 1452 saload = laload 1453 sastore = lastore 1454 1455 def sipush(self, arguments, program): 1456 program.load_const((arguments[0] << 8) + arguments[1]) 1457 1458 def swap(self, arguments, program): 1459 program.rot_two() 1460 1461 def tableswitch(self, arguments, program): 1462 # Find the offset to the next 4 byte boundary in the code. 1463 d, r = divmod(self.java_position, 4) 1464 to_boundary = (4 - r) % 4 1465 # Get the pertinent arguments. 1466 arguments = arguments[to_boundary:] 1467 default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3] 1468 low = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7] 1469 high = (arguments[8] << 24) + (arguments[9] << 16) + (arguments[10] << 8) + arguments[11] 1470 # Process the jump entries. 1471 # NOTE: This is not the most optimal implementation. 1472 jump_index = 8 1473 for jump in range(low, high + 1): 1474 offset = signed4((arguments[jump_index] << 24) + (arguments[jump_index + 1] << 16) + 1475 (arguments[jump_index + 2] << 8) + arguments[jump_index + 3]) 1476 # Calculate the branch target. 1477 java_absolute = self.java_position + offset 1478 # Generate branching code. 1479 program.dup_top() # Stack: key, key 1480 program.load_const(jump) # Stack: key, key, jump 1481 program.compare_op("==") # Stack: key, result 1482 program.jump_to_label(0, "end") 1483 program.pop_top() # Stack: key 1484 program.pop_top() # Stack: 1485 program.jump_absolute(self.position_mapping[java_absolute]) 1486 # Generate the label for the end of the branching code. 1487 program.start_label("end") 1488 program.pop_top() # Stack: key 1489 # Update the index. 1490 jump_index += 8 1491 # Generate the default. 1492 java_absolute = self.java_position + default 1493 program.jump_absolute(self.position_mapping[java_absolute]) 1494 1495 def wide(self, code, program): 1496 # NOTE: To be implemented. 1497 return number_of_arguments 1498 1499 def disassemble(class_file, code, exception_table): 1500 disassembler = BytecodeDisassembler(class_file) 1501 disassembler.process(code, exception_table, BytecodeDisassemblerProgram()) 1502 1503 def translate(class_file, code, exception_table): 1504 translator = BytecodeTranslator(class_file) 1505 writer = BytecodeWriter() 1506 translator.process(code, exception_table, writer) 1507 return translator, writer 1508 1509 if __name__ == "__main__": 1510 import sys 1511 from classfile import ClassFile 1512 f = open(sys.argv[1]) 1513 c = ClassFile(f.read()) 1514 1515 # vim: tabstop=4 expandtab shiftwidth=4