1.1 --- a/bytecode.py Sun Nov 07 17:42:07 2004 +0100
1.2 +++ b/bytecode.py Sun Nov 07 20:53:03 2004 +0100
1.3 @@ -7,12 +7,15 @@
1.4 NOTE: Synchronized constructs are not actually supported.
1.5 """
1.6
1.7 -import dis # for access to Python bytecode values
1.8 +from dis import opmap # for access to Python bytecode values
1.9 from UserDict import UserDict
1.10
1.11 # Bytecode production classes.
1.12
1.13 class BytecodeWriter:
1.14 +
1.15 + "A Python bytecode writer."
1.16 +
1.17 def __init__(self):
1.18 self.loops = []
1.19 self.jumps = {}
1.20 @@ -26,6 +29,9 @@
1.21 # NOTE: This may be acquired from elsewhere.
1.22 self.globals = {}
1.23
1.24 + # Mapping from names to indexes.
1.25 + self.names = {}
1.26 +
1.27 def get_output(self):
1.28 output = []
1.29 for element in self.output:
1.30 @@ -67,16 +73,26 @@
1.31 if not self.constants.has_key(value):
1.32 self.constants[value] = len(self.constants.keys())
1.33 self.output.append(self.constants[value])
1.34 + self.position += 2
1.35
1.36 def load_global(self, name):
1.37 self.output.append(opmap["LOAD_GLOBAL"])
1.38 - if not self.globals.has_key(value):
1.39 + if not self.globals.has_key(name):
1.40 self.globals[name] = len(self.globals.keys())
1.41 self.output.append(self.globals[name])
1.42 + self.position += 2
1.43 +
1.44 + def load_attr(self, name):
1.45 + self.output.append(opmap["LOAD_ATTR"])
1.46 + if not self.names.has_key(name):
1.47 + self.names[name] = len(self.names.keys())
1.48 + self.output.append(self.names[name])
1.49 + self.position += 2
1.50
1.51 def load_fast(self, index):
1.52 self.output.append(opmap["LOAD_FAST"])
1.53 self.output.append(index)
1.54 + self.position += 2
1.55
1.56 # Normal bytecode generators.
1.57
1.58 @@ -101,6 +117,28 @@
1.59 self.output.append(offset) # May be filled in later
1.60 self.position += 2
1.61
1.62 + def build_tuple(self, count):
1.63 + self.output.append(opmap["BUILD_TUPLE"])
1.64 + self.output.append(count)
1.65 + self.position += 2
1.66 +
1.67 + def rot_two(self):
1.68 + self.output.append(opmap["ROT_TWO"])
1.69 + self.position += 1
1.70 +
1.71 + def rot_three(self):
1.72 + self.output.append(opmap["ROT_THREE"])
1.73 + self.position += 1
1.74 +
1.75 + def rot_four(self):
1.76 + self.output.append(opmap["ROT_FOUR"])
1.77 + self.position += 1
1.78 +
1.79 + def call_function(self, count):
1.80 + self.output.append(opmap["CALL_FUNCTION"])
1.81 + self.output.append(count)
1.82 + self.position += 2
1.83 +
1.84 # Utility classes and functions.
1.85
1.86 class LazyDict(UserDict):
1.87 @@ -144,6 +182,9 @@
1.88 # Bytecode conversion.
1.89
1.90 class BytecodeReader:
1.91 +
1.92 + "A generic Java bytecode reader."
1.93 +
1.94 def __init__(self, class_file):
1.95 self.class_file = class_file
1.96 self.position_mapping = LazyDict()
1.97 @@ -154,9 +195,9 @@
1.98 self.position_mapping[self.java_position] = program.position
1.99 bytecode = ord(code[self.java_position])
1.100 mnemonic, number_of_arguments = self.java_bytecodes[bytecode]
1.101 - self.process_bytecode(mnemonic, number_of_arguments)
1.102 + self.process_bytecode(mnemonic, number_of_arguments, code, program)
1.103
1.104 - def process_bytecode(self, mnemonic, number_of_arguments):
1.105 + def process_bytecode(self, mnemonic, number_of_arguments, code, program):
1.106 if number_of_arguments is not None:
1.107 arguments = []
1.108 for j in range(0, number_of_arguments):
1.109 @@ -170,636 +211,6 @@
1.110
1.111 self.java_position = self.java_position + 1 + number_of_arguments
1.112
1.113 - def nop(self, arguments, program):
1.114 - pass
1.115 -
1.116 - def aaload(self, arguments, program):
1.117 - # NOTE: No type checking performed.
1.118 - program.binary_subscr()
1.119 -
1.120 - def aastore(self, arguments, program):
1.121 - # NOTE: No type checking performed.
1.122 - # Stack: arrayref, index, value
1.123 - program.rot_three() # Stack: value, arrayref, index
1.124 - program.store_subscr()
1.125 -
1.126 - def aconst_null(self, arguments, program):
1.127 - program.load_global(None)
1.128 -
1.129 - def aload(self, arguments, program):
1.130 - program.load_fast(arguments[0])
1.131 -
1.132 - def aload_0(self, arguments, program):
1.133 - program.load_fast(0)
1.134 -
1.135 - def aload_1(self, arguments, program):
1.136 - program.load_fast(1)
1.137 -
1.138 - def aload_2(self, arguments, program):
1.139 - program.load_fast(2)
1.140 -
1.141 - def aload_3(self, arguments, program):
1.142 - program.load_fast(3)
1.143 -
1.144 - def anewarray(self, arguments, program):
1.145 - # NOTE: Does not raise NegativeArraySizeException.
1.146 - # NOTE: Not using the index to type the list/array.
1.147 - index = arguments[0] << 8 + arguments[1]
1.148 -
1.149 - program.build_list() # Stack: count, list
1.150 - program.rot_two() # Stack: list, count
1.151 - program.setup_loop()
1.152 - program.load_global("range")
1.153 - program.load_const(0) # Stack: list, count, range, 0
1.154 - program.rot_three() # Stack: list, 0, count, range
1.155 - program.rot_three() # Stack: list, range, 0, count
1.156 - program.call_function(2) # Stack: list, range_list
1.157 - program.get_iter() # Stack: list, iter
1.158 - program.for_iter() # Stack: list, iter, value
1.159 - program.pop_top() # Stack: list, iter
1.160 - program.rot_two() # Stack: iter, list
1.161 - program.dup_top() # Stack: iter, list, list
1.162 - program.load_attr("append") # Stack: iter, list, append
1.163 - program.load_global(None) # Stack: iter, list, append, None
1.164 - program.call_function(1) # Stack: iter, list, None
1.165 - program.pop_top() # Stack: iter, list
1.166 - program.rot_two() # Stack: list, iter
1.167 - program.end_loop() # Back to for_iter above
1.168 -
1.169 - def areturn(self, arguments, program):
1.170 - program.return_value()
1.171 -
1.172 - def arraylength(self, arguments, program):
1.173 - program.load_global("len") # Stack: arrayref, len
1.174 - program.rot_two() # Stack: len, arrayref
1.175 - program.call_function(1)
1.176 -
1.177 - def astore(self, arguments, program):
1.178 - program.store_fast(arguments[0])
1.179 -
1.180 - def astore_0(self, arguments, program):
1.181 - program.store_fast(0)
1.182 -
1.183 - def astore_1(self, arguments, program):
1.184 - program.store_fast(1)
1.185 -
1.186 - def astore_2(self, arguments, program):
1.187 - program.store_fast(2)
1.188 -
1.189 - def astore_3(self, arguments, program):
1.190 - program.store_fast(3)
1.191 -
1.192 - def athrow(self, arguments, program):
1.193 - # NOTE: NullPointerException not raised where null/None is found on the stack.
1.194 - program.raise_varargs(1)
1.195 -
1.196 - baload = aaload
1.197 - bastore = aastore
1.198 -
1.199 - def bipush(self, arguments, program):
1.200 - program.load_const(arguments[0])
1.201 -
1.202 - caload = aaload
1.203 - castore = aastore
1.204 -
1.205 - def checkcast(self, arguments, program):
1.206 - index = arguments[0] << 8 + arguments[1]
1.207 - target_name = self.class_file.constants[index - 1].get_name()
1.208 - target_components = target_name.split("/")
1.209 -
1.210 - program.dup_top() # Stack: objectref, objectref
1.211 - program.load_global("isinstance") # Stack: objectref, objectref, isinstance
1.212 - program.rot_two() # Stack: objectref, isinstance, objectref
1.213 - program.load_global(target_components[0])
1.214 - for target_component in target_components[1:]:
1.215 - program.load_attr(target_component)
1.216 - program.call_function(2) # Stack: objectref
1.217 -
1.218 - def d2f(self, arguments, program):
1.219 - pass
1.220 -
1.221 - def d2i(self, arguments, program):
1.222 - program.load_global("int") # Stack: value, int
1.223 - program.rot_two() # Stack: int, value
1.224 - program.call_function(1) # Stack: result
1.225 -
1.226 - d2l = d2i # Preserving Java semantics
1.227 -
1.228 - def dadd(self, arguments, program):
1.229 - # NOTE: No type checking performed.
1.230 - program.binary_add()
1.231 -
1.232 - daload = aaload
1.233 - dastore = aastore
1.234 -
1.235 - def dcmpg(self, arguments, program):
1.236 - # NOTE: No type checking performed.
1.237 - program.compare_op(">")
1.238 -
1.239 - def dcmpl(self, arguments, program):
1.240 - # NOTE: No type checking performed.
1.241 - program.compare_op("<")
1.242 -
1.243 - def dconst_0(self, arguments, program):
1.244 - program.load_const(0.0)
1.245 -
1.246 - def dconst_1(self, arguments, program):
1.247 - program.load_const(1.0)
1.248 -
1.249 - def ddiv(self, arguments, program):
1.250 - # NOTE: No type checking performed.
1.251 - program.binary_divide()
1.252 -
1.253 - dload = aload
1.254 - dload_0 = aload_0
1.255 - dload_1 = aload_1
1.256 - dload_2 = aload_2
1.257 - dload_3 = aload_3
1.258 -
1.259 - def dmul(self, arguments, program):
1.260 - # NOTE: No type checking performed.
1.261 - program.binary_multiply()
1.262 -
1.263 - def dneg(self, arguments, program):
1.264 - # NOTE: No type checking performed.
1.265 - program.unary_negative()
1.266 -
1.267 - def drem(self, arguments, program):
1.268 - # NOTE: No type checking performed.
1.269 - program.binary_modulo()
1.270 -
1.271 - dreturn = areturn
1.272 - dstore = astore
1.273 - dstore_0 = astore_0
1.274 - dstore_1 = astore_1
1.275 - dstore_2 = astore_2
1.276 - dstore_3 = astore_3
1.277 -
1.278 - def dsub(self, arguments, program):
1.279 - # NOTE: No type checking performed.
1.280 - program.binary_subtract()
1.281 -
1.282 - def dup(self, arguments, program):
1.283 - program.dup_top()
1.284 -
1.285 - def dup_x1(self, arguments, program):
1.286 - # Ignoring computational type categories.
1.287 - program.dup_top()
1.288 - program.rot_three()
1.289 -
1.290 - def dup_x2(self, arguments, program):
1.291 - # Ignoring computational type categories.
1.292 - program.dup_top()
1.293 - program.rot_four()
1.294 -
1.295 - dup2 = dup # Ignoring computational type categories
1.296 - dup2_x1 = dup_x1 # Ignoring computational type categories
1.297 - dup2_x2 = dup_x2 # Ignoring computational type categories
1.298 -
1.299 - def f2d(self, arguments, program):
1.300 - pass # Preserving Java semantics
1.301 -
1.302 - def f2i(self, arguments, program):
1.303 - program.load_global("int") # Stack: value, int
1.304 - program.rot_two() # Stack: int, value
1.305 - program.call_function(1) # Stack: result
1.306 -
1.307 - f2l = f2i # Preserving Java semantics
1.308 - fadd = dadd
1.309 - faload = daload
1.310 - fastore = dastore
1.311 - fcmpg = dcmpg
1.312 - fcmpl = dcmpl
1.313 - fconst_0 = dconst_0
1.314 - fconst_1 = dconst_1
1.315 -
1.316 - def fconst_2(self, arguments, program):
1.317 - program.load_const(2.0)
1.318 -
1.319 - fdiv = ddiv
1.320 - fload = dload
1.321 - fload_0 = dload_0
1.322 - fload_1 = dload_1
1.323 - fload_2 = dload_2
1.324 - fload_3 = dload_3
1.325 - fmul = dmul
1.326 - fneg = dneg
1.327 - frem = drem
1.328 - freturn = dreturn
1.329 - fstore = dstore
1.330 - fstore_0 = dstore_0
1.331 - fstore_1 = dstore_1
1.332 - fstore_2 = dstore_2
1.333 - fstore_3 = dstore_3
1.334 - fsub = dsub
1.335 -
1.336 - def getfield(self, arguments, program):
1.337 - index = arguments[0] << 8 + arguments[1]
1.338 - target_name = self.class_file.constants[index - 1].get_name()
1.339 - # NOTE: Using the string version of the name which may contain incompatible characters.
1.340 - program.load_attr(str(target_name))
1.341 -
1.342 - getstatic = getfield # Ignoring Java restrictions
1.343 -
1.344 - def goto(self, arguments, program):
1.345 - offset = signed2(arguments[0] << 8 + arguments[1])
1.346 - java_absolute = self.java_position + offset
1.347 - program.jump_absolute(self.position_mapping[java_absolute])
1.348 -
1.349 - def goto_w(self, arguments, program):
1.350 - offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3])
1.351 - java_absolute = self.java_position + offset
1.352 - program.jump_absolute(self.position_mapping[java_absolute])
1.353 -
1.354 - def i2b(self, arguments, program):
1.355 - pass
1.356 -
1.357 - def i2c(self, arguments, program):
1.358 - program.load_global("chr") # Stack: value, chr
1.359 - program.rot_two() # Stack: chr, value
1.360 - program.call_function(1) # Stack: result
1.361 -
1.362 - def i2d(self, arguments, program):
1.363 - program.load_global("float") # Stack: value, float
1.364 - program.rot_two() # Stack: float, value
1.365 - program.call_function(1) # Stack: result
1.366 -
1.367 - i2f = i2d # Not distinguishing between float and double
1.368 -
1.369 - def i2l(self, arguments, program):
1.370 - pass # Preserving Java semantics
1.371 -
1.372 - def i2s(self, arguments, program):
1.373 - pass # Not distinguishing between int and short
1.374 -
1.375 - iadd = fadd
1.376 - iaload = faload
1.377 -
1.378 - def iand(self, arguments, program):
1.379 - # NOTE: No type checking performed.
1.380 - program.binary_and()
1.381 -
1.382 - iastore = fastore
1.383 -
1.384 - def iconst_m1(self, arguments, program):
1.385 - program.load_const(-1)
1.386 -
1.387 - def iconst_0(self, arguments, program):
1.388 - program.load_const(0)
1.389 -
1.390 - def iconst_1(self, arguments, program):
1.391 - program.load_const(1)
1.392 -
1.393 - def iconst_2(self, arguments, program):
1.394 - program.load_const(2)
1.395 -
1.396 - def iconst_3(self, arguments, program):
1.397 - program.load_const(3)
1.398 -
1.399 - def iconst_4(self, arguments, program):
1.400 - program.load_const(4)
1.401 -
1.402 - def iconst_5(self, arguments, program):
1.403 - program.load_const(5)
1.404 -
1.405 - idiv = fdiv
1.406 -
1.407 - def _if_xcmpx(self, arguments, program, op):
1.408 - offset = signed2(arguments[0] << 8 + arguments[1])
1.409 - java_absolute = self.java_position + offset
1.410 - program.compare_op(op)
1.411 - program.jump_to_label(0, "next") # skip if false
1.412 - program.goto(offset)
1.413 - program.start_label("next")
1.414 -
1.415 - def if_acmpeq(self, arguments, program):
1.416 - # NOTE: No type checking performed.
1.417 - self._if_xcmpx(arguments, program, "is")
1.418 -
1.419 - def if_acmpne(self, arguments, program):
1.420 - # NOTE: No type checking performed.
1.421 - self._if_xcmpx(arguments, program, "is not")
1.422 -
1.423 - def if_icmpeq(self, arguments, program):
1.424 - # NOTE: No type checking performed.
1.425 - self._if_xcmpx(arguments, program, "==")
1.426 -
1.427 - def if_icmpne(self, arguments, program):
1.428 - # NOTE: No type checking performed.
1.429 - self._if_xcmpx(arguments, program, "!=")
1.430 -
1.431 - def if_icmplt(self, arguments, program):
1.432 - # NOTE: No type checking performed.
1.433 - self._if_xcmpx(arguments, program, "<")
1.434 -
1.435 - def if_icmpge(self, arguments, program):
1.436 - # NOTE: No type checking performed.
1.437 - self._if_xcmpx(arguments, program, ">=")
1.438 -
1.439 - def if_icmpgt(self, arguments, program):
1.440 - # NOTE: No type checking performed.
1.441 - self._if_xcmpx(arguments, program, ">")
1.442 -
1.443 - def if_icmple(self, arguments, program):
1.444 - # NOTE: No type checking performed.
1.445 - self._if_xcmpx(arguments, program, "<=")
1.446 -
1.447 - def ifeq(self, arguments, program):
1.448 - # NOTE: No type checking performed.
1.449 - program.load_const(0)
1.450 - self._if_xcmpx(arguments, program, "==")
1.451 -
1.452 - def ifne(self, arguments, program):
1.453 - # NOTE: No type checking performed.
1.454 - program.load_const(0)
1.455 - self._if_xcmpx(arguments, program, "!=")
1.456 -
1.457 - def iflt(self, arguments, program):
1.458 - # NOTE: No type checking performed.
1.459 - program.load_const(0)
1.460 - self._if_xcmpx(arguments, program, "<")
1.461 -
1.462 - def ifge(self, arguments, program):
1.463 - # NOTE: No type checking performed.
1.464 - program.load_const(0)
1.465 - self._if_xcmpx(arguments, program, ">=")
1.466 -
1.467 - def ifgt(self, arguments, program):
1.468 - # NOTE: No type checking performed.
1.469 - program.load_const(0)
1.470 - self._if_xcmpx(arguments, program, ">")
1.471 -
1.472 - def ifle(self, arguments, program):
1.473 - # NOTE: No type checking performed.
1.474 - program.load_const(0)
1.475 - self._if_xcmpx(arguments, program, "<=")
1.476 -
1.477 - def ifnonnull(self, arguments, program):
1.478 - # NOTE: No type checking performed.
1.479 - program.load_const(None)
1.480 - self._if_xcmpx(arguments, program, "is not")
1.481 -
1.482 - def ifnull(self, arguments, program):
1.483 - # NOTE: No type checking performed.
1.484 - program.load_const(None)
1.485 - self._if_xcmpx(arguments, program, "is")
1.486 -
1.487 - def iinc(self, arguments, program):
1.488 - # NOTE: No type checking performed.
1.489 - program.load_fast(arguments[0])
1.490 - program.load_const(arguments[1])
1.491 - program.binary_add()
1.492 -
1.493 - iload = fload
1.494 - iload_0 = fload_0
1.495 - iload_1 = fload_1
1.496 - iload_2 = fload_2
1.497 - iload_3 = fload_3
1.498 - imul = fmul
1.499 - ineg = fneg
1.500 -
1.501 - def instanceof(self, arguments, program):
1.502 - index = arguments[0] << 8 + arguments[1]
1.503 - target_name = self.class_file.constants[index - 1].get_name()
1.504 - target_components = target_name.split("/")
1.505 -
1.506 - program.load_global("isinstance") # Stack: objectref, isinstance
1.507 - program.rot_two() # Stack: isinstance, objectref
1.508 - program.load_global(target_components[0])
1.509 - for target_component in target_components[1:]:
1.510 - program.load_attr(target_component)
1.511 - program.call_function(2) # Stack: result
1.512 -
1.513 - def _invoke(self, target_name, program):
1.514 - program.rot_two() # Stack: tuple, objectref
1.515 - # NOTE: Using the string version of the name which may contain incompatible characters.
1.516 - program.load_attr(str(target_name)) # Stack: tuple, method
1.517 - program.rot_two() # Stack: method, tuple
1.518 - program.load_global("apply") # Stack: method, tuple, apply
1.519 - program.rot_three() # Stack: apply, method, tuple
1.520 - program.call_function(2)
1.521 -
1.522 - def invokeinterface(self, arguments, program):
1.523 - # NOTE: This implementation does not perform the necessary checks for
1.524 - # NOTE: signature-based polymorphism.
1.525 - # NOTE: Java rules not specifically obeyed.
1.526 - index = arguments[0] << 8 + arguments[1]
1.527 - count = arguments[2]
1.528 - target_name = self.class_file.constants[index - 1].get_name()
1.529 - # Stack: objectref, arg1, arg2, ...
1.530 - program.build_tuple(count) # Stack: objectref, tuple
1.531 - self._invoke(target_name, program)
1.532 -
1.533 - def invokespecial(self, arguments, program):
1.534 - # NOTE: This implementation does not perform the necessary checks for
1.535 - # NOTE: signature-based polymorphism.
1.536 - # NOTE: Java rules not specifically obeyed.
1.537 - index = arguments[0] << 8 + arguments[1]
1.538 - target = self.class_file.constants[index - 1]
1.539 - target_name = target.get_name()
1.540 - # Get the number of parameters from the descriptor.
1.541 - count = len(target.get_descriptor()[0])
1.542 - # Stack: objectref, arg1, arg2, ...
1.543 - program.build_tuple(count) # Stack: objectref, tuple
1.544 - self._invoke(target_name, program)
1.545 -
1.546 - def invokestatic(self, arguments, program):
1.547 - # NOTE: This implementation does not perform the necessary checks for
1.548 - # NOTE: signature-based polymorphism.
1.549 - # NOTE: Java rules not specifically obeyed.
1.550 - index = arguments[0] << 8 + arguments[1]
1.551 - target = self.class_file.constants[index - 1]
1.552 - target_name = target.get_name()
1.553 - # Get the number of parameters from the descriptor.
1.554 - count = len(target.get_descriptor()[0])
1.555 - # Stack: arg1, arg2, ...
1.556 - program.build_tuple(count) # Stack: tuple
1.557 - # NOTE: Should probably use Python static methods.
1.558 - program.load_name("self") # Stack: tuple, self
1.559 - self._invoke(target_name, program)
1.560 -
1.561 - invokevirtual = invokeinterface # Ignoring Java rules
1.562 -
1.563 - def ior(self, arguments, program):
1.564 - # NOTE: No type checking performed.
1.565 - program.binary_or()
1.566 -
1.567 - irem = frem
1.568 - ireturn = freturn
1.569 -
1.570 - def ishl(self, arguments, program):
1.571 - # NOTE: No type checking performed.
1.572 - # NOTE: Not verified.
1.573 - program.binary_lshift()
1.574 -
1.575 - def ishr(self, arguments, program):
1.576 - # NOTE: No type checking performed.
1.577 - # NOTE: Not verified.
1.578 - program.binary_rshift()
1.579 -
1.580 - istore = fstore
1.581 - istore_0 = fstore_0
1.582 - istore_1 = fstore_1
1.583 - istore_2 = fstore_2
1.584 - istore_3 = fstore_3
1.585 - isub = fsub
1.586 - iushr = ishr # Ignoring distinctions between arithmetic and logical shifts
1.587 -
1.588 - def ixor(self, arguments, program):
1.589 - # NOTE: No type checking performed.
1.590 - program.binary_xor()
1.591 -
1.592 - def jsr(self, arguments, program):
1.593 - offset = signed2(arguments[0] << 8 + arguments[1])
1.594 - java_absolute = self.java_position + offset
1.595 - # Store the address of the next instruction.
1.596 - program.load_const(self.position_mapping[self.java_position + 3])
1.597 - program.jump_absolute(self.position_mapping[java_absolute])
1.598 -
1.599 - def jsr_w(self, arguments, program):
1.600 - offset = signed4(arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3])
1.601 - java_absolute = self.java_position + offset
1.602 - # Store the address of the next instruction.
1.603 - program.load_const(self.position_mapping[self.java_position + 5])
1.604 - program.jump_absolute(self.position_mapping[java_absolute])
1.605 -
1.606 - l2d = i2d
1.607 - l2f = i2f
1.608 -
1.609 - def l2i(self, arguments, program):
1.610 - pass # Preserving Java semantics
1.611 -
1.612 - ladd = iadd
1.613 - laload = iaload
1.614 - land = iand
1.615 - lastore = iastore
1.616 -
1.617 - def lcmp(self, arguments, program):
1.618 - # NOTE: No type checking performed.
1.619 - program.dup_topx(2) # Stack: value1, value2, value1, value2
1.620 - program.compare_op(">") # Stack: value1, value2, result
1.621 - program.jump_to_label(0, "equals")
1.622 - # True - produce result and branch.
1.623 - program.pop_top() # Stack: value1, value2
1.624 - program.pop_top() # Stack: value1
1.625 - program.pop_top() # Stack:
1.626 - program.load_const(1) # Stack: 1
1.627 - program.jump_to_label(None, "next")
1.628 - # False - test equality.
1.629 - program.start_label("equals")
1.630 - program.pop_top() # Stack: value1, value2
1.631 - program.dup_topx(2) # Stack: value1, value2, value1, value2
1.632 - program.compare_op("==") # Stack: value1, value2, result
1.633 - program.jump_to_label(0, "less")
1.634 - # True - produce result and branch.
1.635 - program.pop_top() # Stack: value1, value2
1.636 - program.pop_top() # Stack: value1
1.637 - program.pop_top() # Stack:
1.638 - program.load_const(0) # Stack: 0
1.639 - program.jump_to_label(None, "next")
1.640 - # False - produce result.
1.641 - program.start_label("less")
1.642 - program.pop_top() # Stack: value1, value2
1.643 - program.pop_top() # Stack: value1
1.644 - program.pop_top() # Stack:
1.645 - program.load_const(-1) # Stack: -1
1.646 - program.start_label("next")
1.647 -
1.648 - lconst_0 = iconst_0
1.649 - lconst_1 = iconst_1
1.650 -
1.651 - def ldc(self, arguments, program):
1.652 - program.load_const(self.class_file.constants[arguments[0] - 1])
1.653 -
1.654 - def ldc_w(self, arguments, program):
1.655 - program.load_const(self.class_file.constants[arguments[0] << 8 + arguments[1] - 1])
1.656 -
1.657 - ldc2_w = ldc_w
1.658 - ldiv = idiv
1.659 - lload = iload
1.660 - lload_0 = iload_0
1.661 - lload_1 = iload_1
1.662 - lload_2 = iload_2
1.663 - lload_3 = iload_3
1.664 - lmul = imul
1.665 - lneg = ineg
1.666 -
1.667 - def lookupswitch(self, arguments, program):
1.668 - # Find the offset to the next 4 byte boundary in the code.
1.669 - d, r = divmod(self.java_position, 4)
1.670 - to_boundary = (4 - r) % 4
1.671 - # Get the pertinent arguments.
1.672 - arguments = arguments[to_boundary:]
1.673 - default = arguments[0] << 24 + arguments[1] << 16 + arguments[2] << 8 + arguments[3]
1.674 - npairs = arguments[4] << 24 + arguments[5] << 16 + arguments[6] << 8 + arguments[7]
1.675 - # Process the pairs.
1.676 - # NOTE: This is not the most optimal implementation.
1.677 - pair_index = 8
1.678 - for pair in range(0, npairs):
1.679 - match = (arguments[pair_index] << 24 + arguments[pair_index + 1] << 16 +
1.680 - arguments[pair_index + 2] << 8 + arguments[pair_index + 3])
1.681 - offset = signed4(arguments[pair_index + 4] << 24 + arguments[pair_index + 5] << 16 +
1.682 - arguments[pair_index + 6] << 8 + arguments[pair_index + 7])
1.683 - # Calculate the branch target.
1.684 - java_absolute = self.java_position + offset
1.685 - # Generate branching code.
1.686 - program.dup_top() # Stack: key, key
1.687 - program.load_const(match) # Stack: key, key, match
1.688 - program.compare_op("==") # Stack: key, result
1.689 - program.jump_to_label(0, "end" + str(pair))
1.690 - program.pop_top() # Stack: key
1.691 - program.pop_top() # Stack:
1.692 - program.jump_absolute(self.position_mapping[java_absolute])
1.693 - # Generate the label for the end of the branching code.
1.694 - program.start_label("end" + str(pair))
1.695 - program.pop_top() # Stack: key
1.696 - # Update the index.
1.697 - pair_index += 8
1.698 - # Generate the default.
1.699 - java_absolute = self.java_position + default
1.700 - program.jump_absolute(self.position_mapping[java_absolute])
1.701 -
1.702 - lor = ior
1.703 - lrem = irem
1.704 - lreturn = ireturn
1.705 - lshl = ishl
1.706 - lshr = ishr
1.707 - lstore = istore
1.708 - lstore_0 = istore_0
1.709 - lstore_1 = istore_1
1.710 - lstore_2 = istore_2
1.711 - lstore_3 = istore_3
1.712 - lsub = isub
1.713 - lushr = iushr
1.714 - lxor = ixor
1.715 -
1.716 - def monitorenter(self, arguments, program):
1.717 - # NOTE: To be implemented.
1.718 - pass
1.719 -
1.720 - def monitorexit(self, arguments, program):
1.721 - # NOTE: To be implemented.
1.722 - pass
1.723 -
1.724 - def multianewarray(self, arguments, program):
1.725 - program.build_list() # Stack: count1, count2, ..., countN, list
1.726 - program.rot_two() # Stack: count1, count2, ..., list, countN
1.727 - program.setup_loop()
1.728 - program.load_global("range")
1.729 - program.load_const(0) # Stack: list, count, range, 0
1.730 - program.rot_three() # Stack: list, 0, count, range
1.731 - program.rot_three() # Stack: list, range, 0, count
1.732 - program.call_function(2) # Stack: list, range_list
1.733 - program.get_iter() # Stack: list, iter
1.734 - program.for_iter() # Stack: list, iter, value
1.735 - for i in range(0, arguments[2]):
1.736 - # Stack:
1.737 - self.anewarray(arguments, program) # Stack: list, iter
1.738 -
1.739 - def wide(self, code, program):
1.740 - # NOTE: To be implemented.
1.741 - return number_of_arguments
1.742 -
1.743 java_bytecodes = {
1.744 # code : (mnemonic, number of following bytes, change in stack)
1.745 0 : ("nop", 0),
1.746 @@ -1005,6 +416,669 @@
1.747 201 : ("jsr_w", 4),
1.748 }
1.749
1.750 +class BytecodeDisassembler(BytecodeReader):
1.751 +
1.752 + "A Java bytecode disassembler."
1.753 +
1.754 + bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()]
1.755 +
1.756 + def __getattr__(self, name):
1.757 + if name in self.bytecode_methods:
1.758 + print name,
1.759 + return self.generic
1.760 + else:
1.761 + raise AttributeError, name
1.762 +
1.763 + def generic(self, arguments, program):
1.764 + print arguments
1.765 +
1.766 +class BytecodeDisassemblerProgram:
1.767 + position = 0
1.768 +
1.769 +class BytecodeTranslator(BytecodeReader):
1.770 +
1.771 + "A Java bytecode translator which uses a Python bytecode writer."
1.772 +
1.773 + def nop(self, arguments, program):
1.774 + pass
1.775 +
1.776 + def aaload(self, arguments, program):
1.777 + # NOTE: No type checking performed.
1.778 + program.binary_subscr()
1.779 +
1.780 + def aastore(self, arguments, program):
1.781 + # NOTE: No type checking performed.
1.782 + # Stack: arrayref, index, value
1.783 + program.rot_three() # Stack: value, arrayref, index
1.784 + program.store_subscr()
1.785 +
1.786 + def aconst_null(self, arguments, program):
1.787 + program.load_global(None)
1.788 +
1.789 + def aload(self, arguments, program):
1.790 + program.load_fast(arguments[0])
1.791 +
1.792 + def aload_0(self, arguments, program):
1.793 + program.load_fast(0)
1.794 +
1.795 + def aload_1(self, arguments, program):
1.796 + program.load_fast(1)
1.797 +
1.798 + def aload_2(self, arguments, program):
1.799 + program.load_fast(2)
1.800 +
1.801 + def aload_3(self, arguments, program):
1.802 + program.load_fast(3)
1.803 +
1.804 + def anewarray(self, arguments, program):
1.805 + # NOTE: Does not raise NegativeArraySizeException.
1.806 + # NOTE: Not using the index to type the list/array.
1.807 + index = (arguments[0] << 8) + arguments[1]
1.808 +
1.809 + program.build_list() # Stack: count, list
1.810 + program.rot_two() # Stack: list, count
1.811 + program.setup_loop()
1.812 + program.load_global("range")
1.813 + program.load_const(0) # Stack: list, count, range, 0
1.814 + program.rot_three() # Stack: list, 0, count, range
1.815 + program.rot_three() # Stack: list, range, 0, count
1.816 + program.call_function(2) # Stack: list, range_list
1.817 + program.get_iter() # Stack: list, iter
1.818 + program.for_iter() # Stack: list, iter, value
1.819 + program.pop_top() # Stack: list, iter
1.820 + program.rot_two() # Stack: iter, list
1.821 + program.dup_top() # Stack: iter, list, list
1.822 + program.load_attr("append") # Stack: iter, list, append
1.823 + program.load_global(None) # Stack: iter, list, append, None
1.824 + program.call_function(1) # Stack: iter, list, None
1.825 + program.pop_top() # Stack: iter, list
1.826 + program.rot_two() # Stack: list, iter
1.827 + program.end_loop() # Back to for_iter above
1.828 +
1.829 + def areturn(self, arguments, program):
1.830 + program.return_value()
1.831 +
1.832 + def arraylength(self, arguments, program):
1.833 + program.load_global("len") # Stack: arrayref, len
1.834 + program.rot_two() # Stack: len, arrayref
1.835 + program.call_function(1)
1.836 +
1.837 + def astore(self, arguments, program):
1.838 + program.store_fast(arguments[0])
1.839 +
1.840 + def astore_0(self, arguments, program):
1.841 + program.store_fast(0)
1.842 +
1.843 + def astore_1(self, arguments, program):
1.844 + program.store_fast(1)
1.845 +
1.846 + def astore_2(self, arguments, program):
1.847 + program.store_fast(2)
1.848 +
1.849 + def astore_3(self, arguments, program):
1.850 + program.store_fast(3)
1.851 +
1.852 + def athrow(self, arguments, program):
1.853 + # NOTE: NullPointerException not raised where null/None is found on the stack.
1.854 + program.raise_varargs(1)
1.855 +
1.856 + baload = aaload
1.857 + bastore = aastore
1.858 +
1.859 + def bipush(self, arguments, program):
1.860 + program.load_const(arguments[0])
1.861 +
1.862 + caload = aaload
1.863 + castore = aastore
1.864 +
1.865 + def checkcast(self, arguments, program):
1.866 + index = (arguments[0] << 8) + arguments[1]
1.867 + target_name = self.class_file.constants[index - 1].get_name()
1.868 + target_components = target_name.split("/")
1.869 +
1.870 + program.dup_top() # Stack: objectref, objectref
1.871 + program.load_global("isinstance") # Stack: objectref, objectref, isinstance
1.872 + program.rot_two() # Stack: objectref, isinstance, objectref
1.873 + program.load_global(target_components[0])
1.874 + for target_component in target_components[1:]:
1.875 + program.load_attr(target_component)
1.876 + program.call_function(2) # Stack: objectref
1.877 +
1.878 + def d2f(self, arguments, program):
1.879 + pass
1.880 +
1.881 + def d2i(self, arguments, program):
1.882 + program.load_global("int") # Stack: value, int
1.883 + program.rot_two() # Stack: int, value
1.884 + program.call_function(1) # Stack: result
1.885 +
1.886 + d2l = d2i # Preserving Java semantics
1.887 +
1.888 + def dadd(self, arguments, program):
1.889 + # NOTE: No type checking performed.
1.890 + program.binary_add()
1.891 +
1.892 + daload = aaload
1.893 + dastore = aastore
1.894 +
1.895 + def dcmpg(self, arguments, program):
1.896 + # NOTE: No type checking performed.
1.897 + program.compare_op(">")
1.898 +
1.899 + def dcmpl(self, arguments, program):
1.900 + # NOTE: No type checking performed.
1.901 + program.compare_op("<")
1.902 +
1.903 + def dconst_0(self, arguments, program):
1.904 + program.load_const(0.0)
1.905 +
1.906 + def dconst_1(self, arguments, program):
1.907 + program.load_const(1.0)
1.908 +
1.909 + def ddiv(self, arguments, program):
1.910 + # NOTE: No type checking performed.
1.911 + program.binary_divide()
1.912 +
1.913 + dload = aload
1.914 + dload_0 = aload_0
1.915 + dload_1 = aload_1
1.916 + dload_2 = aload_2
1.917 + dload_3 = aload_3
1.918 +
1.919 + def dmul(self, arguments, program):
1.920 + # NOTE: No type checking performed.
1.921 + program.binary_multiply()
1.922 +
1.923 + def dneg(self, arguments, program):
1.924 + # NOTE: No type checking performed.
1.925 + program.unary_negative()
1.926 +
1.927 + def drem(self, arguments, program):
1.928 + # NOTE: No type checking performed.
1.929 + program.binary_modulo()
1.930 +
1.931 + dreturn = areturn
1.932 + dstore = astore
1.933 + dstore_0 = astore_0
1.934 + dstore_1 = astore_1
1.935 + dstore_2 = astore_2
1.936 + dstore_3 = astore_3
1.937 +
1.938 + def dsub(self, arguments, program):
1.939 + # NOTE: No type checking performed.
1.940 + program.binary_subtract()
1.941 +
1.942 + def dup(self, arguments, program):
1.943 + program.dup_top()
1.944 +
1.945 + def dup_x1(self, arguments, program):
1.946 + # Ignoring computational type categories.
1.947 + program.dup_top()
1.948 + program.rot_three()
1.949 +
1.950 + def dup_x2(self, arguments, program):
1.951 + # Ignoring computational type categories.
1.952 + program.dup_top()
1.953 + program.rot_four()
1.954 +
1.955 + dup2 = dup # Ignoring computational type categories
1.956 + dup2_x1 = dup_x1 # Ignoring computational type categories
1.957 + dup2_x2 = dup_x2 # Ignoring computational type categories
1.958 +
1.959 + def f2d(self, arguments, program):
1.960 + pass # Preserving Java semantics
1.961 +
1.962 + def f2i(self, arguments, program):
1.963 + program.load_global("int") # Stack: value, int
1.964 + program.rot_two() # Stack: int, value
1.965 + program.call_function(1) # Stack: result
1.966 +
1.967 + f2l = f2i # Preserving Java semantics
1.968 + fadd = dadd
1.969 + faload = daload
1.970 + fastore = dastore
1.971 + fcmpg = dcmpg
1.972 + fcmpl = dcmpl
1.973 + fconst_0 = dconst_0
1.974 + fconst_1 = dconst_1
1.975 +
1.976 + def fconst_2(self, arguments, program):
1.977 + program.load_const(2.0)
1.978 +
1.979 + fdiv = ddiv
1.980 + fload = dload
1.981 + fload_0 = dload_0
1.982 + fload_1 = dload_1
1.983 + fload_2 = dload_2
1.984 + fload_3 = dload_3
1.985 + fmul = dmul
1.986 + fneg = dneg
1.987 + frem = drem
1.988 + freturn = dreturn
1.989 + fstore = dstore
1.990 + fstore_0 = dstore_0
1.991 + fstore_1 = dstore_1
1.992 + fstore_2 = dstore_2
1.993 + fstore_3 = dstore_3
1.994 + fsub = dsub
1.995 +
1.996 + def getfield(self, arguments, program):
1.997 + index = (arguments[0] << 8) + arguments[1]
1.998 + target_name = self.class_file.constants[index - 1].get_name()
1.999 + # NOTE: Using the string version of the name which may contain incompatible characters.
1.1000 + program.load_attr(str(target_name))
1.1001 +
1.1002 + getstatic = getfield # Ignoring Java restrictions
1.1003 +
1.1004 + def goto(self, arguments, program):
1.1005 + offset = signed2((arguments[0] << 8) + arguments[1])
1.1006 + java_absolute = self.java_position + offset
1.1007 + program.jump_absolute(self.position_mapping[java_absolute])
1.1008 +
1.1009 + def goto_w(self, arguments, program):
1.1010 + offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])
1.1011 + java_absolute = self.java_position + offset
1.1012 + program.jump_absolute(self.position_mapping[java_absolute])
1.1013 +
1.1014 + def i2b(self, arguments, program):
1.1015 + pass
1.1016 +
1.1017 + def i2c(self, arguments, program):
1.1018 + program.load_global("chr") # Stack: value, chr
1.1019 + program.rot_two() # Stack: chr, value
1.1020 + program.call_function(1) # Stack: result
1.1021 +
1.1022 + def i2d(self, arguments, program):
1.1023 + program.load_global("float") # Stack: value, float
1.1024 + program.rot_two() # Stack: float, value
1.1025 + program.call_function(1) # Stack: result
1.1026 +
1.1027 + i2f = i2d # Not distinguishing between float and double
1.1028 +
1.1029 + def i2l(self, arguments, program):
1.1030 + pass # Preserving Java semantics
1.1031 +
1.1032 + def i2s(self, arguments, program):
1.1033 + pass # Not distinguishing between int and short
1.1034 +
1.1035 + iadd = fadd
1.1036 + iaload = faload
1.1037 +
1.1038 + def iand(self, arguments, program):
1.1039 + # NOTE: No type checking performed.
1.1040 + program.binary_and()
1.1041 +
1.1042 + iastore = fastore
1.1043 +
1.1044 + def iconst_m1(self, arguments, program):
1.1045 + program.load_const(-1)
1.1046 +
1.1047 + def iconst_0(self, arguments, program):
1.1048 + program.load_const(0)
1.1049 +
1.1050 + def iconst_1(self, arguments, program):
1.1051 + program.load_const(1)
1.1052 +
1.1053 + def iconst_2(self, arguments, program):
1.1054 + program.load_const(2)
1.1055 +
1.1056 + def iconst_3(self, arguments, program):
1.1057 + program.load_const(3)
1.1058 +
1.1059 + def iconst_4(self, arguments, program):
1.1060 + program.load_const(4)
1.1061 +
1.1062 + def iconst_5(self, arguments, program):
1.1063 + program.load_const(5)
1.1064 +
1.1065 + idiv = fdiv
1.1066 +
1.1067 + def _if_xcmpx(self, arguments, program, op):
1.1068 + offset = signed2((arguments[0] << 8) + arguments[1])
1.1069 + java_absolute = self.java_position + offset
1.1070 + program.compare_op(op)
1.1071 + program.jump_to_label(0, "next") # skip if false
1.1072 + program.goto(offset)
1.1073 + program.start_label("next")
1.1074 +
1.1075 + def if_acmpeq(self, arguments, program):
1.1076 + # NOTE: No type checking performed.
1.1077 + self._if_xcmpx(arguments, program, "is")
1.1078 +
1.1079 + def if_acmpne(self, arguments, program):
1.1080 + # NOTE: No type checking performed.
1.1081 + self._if_xcmpx(arguments, program, "is not")
1.1082 +
1.1083 + def if_icmpeq(self, arguments, program):
1.1084 + # NOTE: No type checking performed.
1.1085 + self._if_xcmpx(arguments, program, "==")
1.1086 +
1.1087 + def if_icmpne(self, arguments, program):
1.1088 + # NOTE: No type checking performed.
1.1089 + self._if_xcmpx(arguments, program, "!=")
1.1090 +
1.1091 + def if_icmplt(self, arguments, program):
1.1092 + # NOTE: No type checking performed.
1.1093 + self._if_xcmpx(arguments, program, "<")
1.1094 +
1.1095 + def if_icmpge(self, arguments, program):
1.1096 + # NOTE: No type checking performed.
1.1097 + self._if_xcmpx(arguments, program, ">=")
1.1098 +
1.1099 + def if_icmpgt(self, arguments, program):
1.1100 + # NOTE: No type checking performed.
1.1101 + self._if_xcmpx(arguments, program, ">")
1.1102 +
1.1103 + def if_icmple(self, arguments, program):
1.1104 + # NOTE: No type checking performed.
1.1105 + self._if_xcmpx(arguments, program, "<=")
1.1106 +
1.1107 + def ifeq(self, arguments, program):
1.1108 + # NOTE: No type checking performed.
1.1109 + program.load_const(0)
1.1110 + self._if_xcmpx(arguments, program, "==")
1.1111 +
1.1112 + def ifne(self, arguments, program):
1.1113 + # NOTE: No type checking performed.
1.1114 + program.load_const(0)
1.1115 + self._if_xcmpx(arguments, program, "!=")
1.1116 +
1.1117 + def iflt(self, arguments, program):
1.1118 + # NOTE: No type checking performed.
1.1119 + program.load_const(0)
1.1120 + self._if_xcmpx(arguments, program, "<")
1.1121 +
1.1122 + def ifge(self, arguments, program):
1.1123 + # NOTE: No type checking performed.
1.1124 + program.load_const(0)
1.1125 + self._if_xcmpx(arguments, program, ">=")
1.1126 +
1.1127 + def ifgt(self, arguments, program):
1.1128 + # NOTE: No type checking performed.
1.1129 + program.load_const(0)
1.1130 + self._if_xcmpx(arguments, program, ">")
1.1131 +
1.1132 + def ifle(self, arguments, program):
1.1133 + # NOTE: No type checking performed.
1.1134 + program.load_const(0)
1.1135 + self._if_xcmpx(arguments, program, "<=")
1.1136 +
1.1137 + def ifnonnull(self, arguments, program):
1.1138 + # NOTE: No type checking performed.
1.1139 + program.load_const(None)
1.1140 + self._if_xcmpx(arguments, program, "is not")
1.1141 +
1.1142 + def ifnull(self, arguments, program):
1.1143 + # NOTE: No type checking performed.
1.1144 + program.load_const(None)
1.1145 + self._if_xcmpx(arguments, program, "is")
1.1146 +
1.1147 + def iinc(self, arguments, program):
1.1148 + # NOTE: No type checking performed.
1.1149 + program.load_fast(arguments[0])
1.1150 + program.load_const(arguments[1])
1.1151 + program.binary_add()
1.1152 +
1.1153 + iload = fload
1.1154 + iload_0 = fload_0
1.1155 + iload_1 = fload_1
1.1156 + iload_2 = fload_2
1.1157 + iload_3 = fload_3
1.1158 + imul = fmul
1.1159 + ineg = fneg
1.1160 +
1.1161 + def instanceof(self, arguments, program):
1.1162 + index = (arguments[0] << 8) + arguments[1]
1.1163 + target_name = self.class_file.constants[index - 1].get_name()
1.1164 + target_components = target_name.split("/")
1.1165 +
1.1166 + program.load_global("isinstance") # Stack: objectref, isinstance
1.1167 + program.rot_two() # Stack: isinstance, objectref
1.1168 + program.load_global(target_components[0])
1.1169 + for target_component in target_components[1:]:
1.1170 + program.load_attr(target_component)
1.1171 + program.call_function(2) # Stack: result
1.1172 +
1.1173 + def _invoke(self, target_name, program):
1.1174 + program.rot_two() # Stack: tuple, objectref
1.1175 + # NOTE: Using the string version of the name which may contain incompatible characters.
1.1176 + program.load_attr(str(target_name)) # Stack: tuple, method
1.1177 + program.rot_two() # Stack: method, tuple
1.1178 + program.load_global("apply") # Stack: method, tuple, apply
1.1179 + program.rot_three() # Stack: apply, method, tuple
1.1180 + program.call_function(2)
1.1181 +
1.1182 + def invokeinterface(self, arguments, program):
1.1183 + # NOTE: This implementation does not perform the necessary checks for
1.1184 + # NOTE: signature-based polymorphism.
1.1185 + # NOTE: Java rules not specifically obeyed.
1.1186 + index = (arguments[0] << 8) + arguments[1]
1.1187 + count = arguments[2]
1.1188 + target_name = self.class_file.constants[index - 1].get_name()
1.1189 + # Stack: objectref, arg1, arg2, ...
1.1190 + program.build_tuple(count) # Stack: objectref, tuple
1.1191 + self._invoke(target_name, program)
1.1192 +
1.1193 + def invokespecial(self, arguments, program):
1.1194 + # NOTE: This implementation does not perform the necessary checks for
1.1195 + # NOTE: signature-based polymorphism.
1.1196 + # NOTE: Java rules not specifically obeyed.
1.1197 + index = (arguments[0] << 8) + arguments[1]
1.1198 + target = self.class_file.constants[index - 1]
1.1199 + target_name = target.get_name()
1.1200 + # Get the number of parameters from the descriptor.
1.1201 + count = len(target.get_descriptor()[0])
1.1202 + # Stack: objectref, arg1, arg2, ...
1.1203 + program.build_tuple(count) # Stack: objectref, tuple
1.1204 + self._invoke(target_name, program)
1.1205 +
1.1206 + def invokestatic(self, arguments, program):
1.1207 + # NOTE: This implementation does not perform the necessary checks for
1.1208 + # NOTE: signature-based polymorphism.
1.1209 + # NOTE: Java rules not specifically obeyed.
1.1210 + index = (arguments[0] << 8) + arguments[1]
1.1211 + target = self.class_file.constants[index - 1]
1.1212 + target_name = target.get_name()
1.1213 + # Get the number of parameters from the descriptor.
1.1214 + count = len(target.get_descriptor()[0])
1.1215 + # Stack: arg1, arg2, ...
1.1216 + program.build_tuple(count) # Stack: tuple
1.1217 + # NOTE: Should probably use Python static methods.
1.1218 + program.load_name("self") # Stack: tuple, self
1.1219 + self._invoke(target_name, program)
1.1220 +
1.1221 + invokevirtual = invokeinterface # Ignoring Java rules
1.1222 +
1.1223 + def ior(self, arguments, program):
1.1224 + # NOTE: No type checking performed.
1.1225 + program.binary_or()
1.1226 +
1.1227 + irem = frem
1.1228 + ireturn = freturn
1.1229 +
1.1230 + def ishl(self, arguments, program):
1.1231 + # NOTE: No type checking performed.
1.1232 + # NOTE: Not verified.
1.1233 + program.binary_lshift()
1.1234 +
1.1235 + def ishr(self, arguments, program):
1.1236 + # NOTE: No type checking performed.
1.1237 + # NOTE: Not verified.
1.1238 + program.binary_rshift()
1.1239 +
1.1240 + istore = fstore
1.1241 + istore_0 = fstore_0
1.1242 + istore_1 = fstore_1
1.1243 + istore_2 = fstore_2
1.1244 + istore_3 = fstore_3
1.1245 + isub = fsub
1.1246 + iushr = ishr # Ignoring distinctions between arithmetic and logical shifts
1.1247 +
1.1248 + def ixor(self, arguments, program):
1.1249 + # NOTE: No type checking performed.
1.1250 + program.binary_xor()
1.1251 +
1.1252 + def jsr(self, arguments, program):
1.1253 + offset = signed2((arguments[0] << 8) + arguments[1])
1.1254 + java_absolute = self.java_position + offset
1.1255 + # Store the address of the next instruction.
1.1256 + program.load_const(self.position_mapping[self.java_position + 3])
1.1257 + program.jump_absolute(self.position_mapping[java_absolute])
1.1258 +
1.1259 + def jsr_w(self, arguments, program):
1.1260 + offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])
1.1261 + java_absolute = self.java_position + offset
1.1262 + # Store the address of the next instruction.
1.1263 + program.load_const(self.position_mapping[self.java_position + 5])
1.1264 + program.jump_absolute(self.position_mapping[java_absolute])
1.1265 +
1.1266 + l2d = i2d
1.1267 + l2f = i2f
1.1268 +
1.1269 + def l2i(self, arguments, program):
1.1270 + pass # Preserving Java semantics
1.1271 +
1.1272 + ladd = iadd
1.1273 + laload = iaload
1.1274 + land = iand
1.1275 + lastore = iastore
1.1276 +
1.1277 + def lcmp(self, arguments, program):
1.1278 + # NOTE: No type checking performed.
1.1279 + program.dup_topx(2) # Stack: value1, value2, value1, value2
1.1280 + program.compare_op(">") # Stack: value1, value2, result
1.1281 + program.jump_to_label(0, "equals")
1.1282 + # True - produce result and branch.
1.1283 + program.pop_top() # Stack: value1, value2
1.1284 + program.pop_top() # Stack: value1
1.1285 + program.pop_top() # Stack:
1.1286 + program.load_const(1) # Stack: 1
1.1287 + program.jump_to_label(None, "next")
1.1288 + # False - test equality.
1.1289 + program.start_label("equals")
1.1290 + program.pop_top() # Stack: value1, value2
1.1291 + program.dup_topx(2) # Stack: value1, value2, value1, value2
1.1292 + program.compare_op("==") # Stack: value1, value2, result
1.1293 + program.jump_to_label(0, "less")
1.1294 + # True - produce result and branch.
1.1295 + program.pop_top() # Stack: value1, value2
1.1296 + program.pop_top() # Stack: value1
1.1297 + program.pop_top() # Stack:
1.1298 + program.load_const(0) # Stack: 0
1.1299 + program.jump_to_label(None, "next")
1.1300 + # False - produce result.
1.1301 + program.start_label("less")
1.1302 + program.pop_top() # Stack: value1, value2
1.1303 + program.pop_top() # Stack: value1
1.1304 + program.pop_top() # Stack:
1.1305 + program.load_const(-1) # Stack: -1
1.1306 + program.start_label("next")
1.1307 +
1.1308 + lconst_0 = iconst_0
1.1309 + lconst_1 = iconst_1
1.1310 +
1.1311 + def ldc(self, arguments, program):
1.1312 + program.load_const(self.class_file.constants[arguments[0] - 1])
1.1313 +
1.1314 + def ldc_w(self, arguments, program):
1.1315 + program.load_const(self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1])
1.1316 +
1.1317 + ldc2_w = ldc_w
1.1318 + ldiv = idiv
1.1319 + lload = iload
1.1320 + lload_0 = iload_0
1.1321 + lload_1 = iload_1
1.1322 + lload_2 = iload_2
1.1323 + lload_3 = iload_3
1.1324 + lmul = imul
1.1325 + lneg = ineg
1.1326 +
1.1327 + def lookupswitch(self, arguments, program):
1.1328 + # Find the offset to the next 4 byte boundary in the code.
1.1329 + d, r = divmod(self.java_position, 4)
1.1330 + to_boundary = (4 - r) % 4
1.1331 + # Get the pertinent arguments.
1.1332 + arguments = arguments[to_boundary:]
1.1333 + default = (arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3]
1.1334 + npairs = (arguments[4] << 24) + (arguments[5] << 16) + (arguments[6] << 8) + arguments[7]
1.1335 + # Process the pairs.
1.1336 + # NOTE: This is not the most optimal implementation.
1.1337 + pair_index = 8
1.1338 + for pair in range(0, npairs):
1.1339 + match = ((arguments[pair_index] << 24) + (arguments[pair_index + 1] << 16) +
1.1340 + (arguments[pair_index + 2] << 8) + arguments[pair_index + 3])
1.1341 + offset = signed4((arguments[pair_index + 4] << 24) + (arguments[pair_index + 5] << 16) +
1.1342 + (arguments[pair_index + 6] << 8) + arguments[pair_index + 7])
1.1343 + # Calculate the branch target.
1.1344 + java_absolute = self.java_position + offset
1.1345 + # Generate branching code.
1.1346 + program.dup_top() # Stack: key, key
1.1347 + program.load_const(match) # Stack: key, key, match
1.1348 + program.compare_op("==") # Stack: key, result
1.1349 + program.jump_to_label(0, "end" + str(pair))
1.1350 + program.pop_top() # Stack: key
1.1351 + program.pop_top() # Stack:
1.1352 + program.jump_absolute(self.position_mapping[java_absolute])
1.1353 + # Generate the label for the end of the branching code.
1.1354 + program.start_label("end" + str(pair))
1.1355 + program.pop_top() # Stack: key
1.1356 + # Update the index.
1.1357 + pair_index += 8
1.1358 + # Generate the default.
1.1359 + java_absolute = self.java_position + default
1.1360 + program.jump_absolute(self.position_mapping[java_absolute])
1.1361 +
1.1362 + lor = ior
1.1363 + lrem = irem
1.1364 + lreturn = ireturn
1.1365 + lshl = ishl
1.1366 + lshr = ishr
1.1367 + lstore = istore
1.1368 + lstore_0 = istore_0
1.1369 + lstore_1 = istore_1
1.1370 + lstore_2 = istore_2
1.1371 + lstore_3 = istore_3
1.1372 + lsub = isub
1.1373 + lushr = iushr
1.1374 + lxor = ixor
1.1375 +
1.1376 + def monitorenter(self, arguments, program):
1.1377 + # NOTE: To be implemented.
1.1378 + pass
1.1379 +
1.1380 + def monitorexit(self, arguments, program):
1.1381 + # NOTE: To be implemented.
1.1382 + pass
1.1383 +
1.1384 + def multianewarray(self, arguments, program):
1.1385 + program.build_list() # Stack: count1, count2, ..., countN, list
1.1386 + program.rot_two() # Stack: count1, count2, ..., list, countN
1.1387 + program.setup_loop()
1.1388 + program.load_global("range")
1.1389 + program.load_const(0) # Stack: list, count, range, 0
1.1390 + program.rot_three() # Stack: list, 0, count, range
1.1391 + program.rot_three() # Stack: list, range, 0, count
1.1392 + program.call_function(2) # Stack: list, range_list
1.1393 + program.get_iter() # Stack: list, iter
1.1394 + program.for_iter() # Stack: list, iter, value
1.1395 + for i in range(0, arguments[2]):
1.1396 + # Stack:
1.1397 + self.anewarray(arguments, program) # Stack: list, iter
1.1398 +
1.1399 + def wide(self, code, program):
1.1400 + # NOTE: To be implemented.
1.1401 + return number_of_arguments
1.1402 +
1.1403 +def disassemble(class_file, code):
1.1404 + disassembler = BytecodeDisassembler(class_file)
1.1405 + disassembler.process(code, BytecodeDisassemblerProgram())
1.1406 +
1.1407 +def translate(class_file, code):
1.1408 + translator = BytecodeTranslator(class_file)
1.1409 + writer = BytecodeWriter()
1.1410 + translator.process(code, writer)
1.1411 + return writer
1.1412 +
1.1413 if __name__ == "__main__":
1.1414 import sys
1.1415 from classfile import ClassFile