Example #1
0
  private int applyInstructionToStack(Instruction i, int stackLen, byte[] stackWords)
      throws InvalidBytecodeException {
    stackLen -= i.getPoppedCount();

    if (stackLen < 0) {
      throw new InvalidBytecodeException("Stack underflow");
    }

    if (i instanceof DupInstruction) {
      DupInstruction d = (DupInstruction) i;
      int delta = d.getDelta();
      int size = d.getSize();

      System.arraycopy(stackWords, stackLen + delta, stackWords, stackLen + size + delta, size);
      System.arraycopy(stackWords, stackLen, stackWords, stackLen + size, delta);
      System.arraycopy(stackWords, stackLen + size + delta, stackWords, stackLen, size);
      stackLen += size * 2 + delta;
    } else if (i instanceof SwapInstruction) {
      if (stackWords[stackLen] != stackWords[stackLen + 1]) {
        throw new Error("OP_swap must always be swapping the same size, 1");
      }
      stackLen += 2;
    } else {
      byte pushedWords = i.getPushedWordSize();
      if (pushedWords > 0) {
        stackWords[stackLen] = pushedWords;
        stackLen++;
      }
    }

    return stackLen;
  }
Example #2
0
  private static Instruction[] makeSimpleInstructions() {
    Instruction[] table = new Instruction[256];

    table[OP_aconst_null] = ConstantInstruction.make(TYPE_null, null);
    for (int i = OP_iconst_m1; i <= OP_iconst_5; i++) {
      table[i] = ConstantInstruction.make(TYPE_int, new Integer(i - OP_iconst_m1 - 1));
    }
    for (int i = OP_lconst_0; i <= OP_lconst_1; i++) {
      table[i] = ConstantInstruction.make(TYPE_long, new Long(i - OP_lconst_0));
    }
    for (int i = OP_fconst_0; i <= OP_fconst_2; i++) {
      table[i] = ConstantInstruction.make(TYPE_float, new Float(i - OP_fconst_0));
    }
    for (int i = OP_dconst_0; i <= OP_dconst_1; i++) {
      table[i] = ConstantInstruction.make(TYPE_double, new Double(i - OP_dconst_0));
    }

    for (int i = OP_iload_0; i <= OP_aload_3; i++) {
      table[i] = LoadInstruction.make(indexedTypes[(i - OP_iload_0) / 4], (i - OP_iload_0) % 4);
    }
    for (int i = OP_iaload; i <= OP_saload; i++) {
      table[i] = ArrayLoadInstruction.make(indexedTypes[i - OP_iaload]);
    }
    for (int i = OP_istore_0; i <= OP_astore_3; i++) {
      table[i] = StoreInstruction.make(indexedTypes[(i - OP_istore_0) / 4], (i - OP_istore_0) % 4);
    }
    for (int i = OP_iastore; i <= OP_sastore; i++) {
      table[i] = ArrayStoreInstruction.make(indexedTypes[i - OP_iastore]);
    }

    table[OP_pop] = PopInstruction.make(1);
    table[OP_dup] = DupInstruction.make(1, 0);
    table[OP_dup_x1] = DupInstruction.make(1, 1);
    table[OP_swap] = SwapInstruction.make();

    for (int i = OP_iadd; i <= OP_drem; i++) {
      table[i] =
          BinaryOpInstruction.make(
              indexedTypes[(i - OP_iadd) % 4],
              BinaryOpInstruction.Operator.values()[(i - OP_iadd) / 4]);
    }
    for (int i = OP_ineg; i <= OP_dneg; i++) {
      table[i] =
          UnaryOpInstruction.make(indexedTypes[i - OP_ineg], IUnaryOpInstruction.Operator.NEG);
    }
    for (int i = OP_ishl; i <= OP_lushr; i++) {
      table[i] =
          ShiftInstruction.make(
              indexedTypes[(i - OP_ishl) % 2],
              ShiftInstruction.Operator.values()[(i - OP_ishl) / 2]);
    }
    for (int i = OP_iand; i <= OP_lxor; i++) {
      table[i] =
          BinaryOpInstruction.make(
              indexedTypes[(i - OP_iand) % 2],
              BinaryOpInstruction.Operator.values()[
                  BinaryOpInstruction.Operator.AND.ordinal() + (i - OP_iand) / 2]);
    }

    for (int i = OP_i2l; i <= OP_d2f; i++) {
      table[i] =
          ConversionInstruction.make(
              indexedTypes[(i - OP_i2l) / 3],
              indexedTypes[skip((i - OP_i2l) % 3, (i - OP_i2l) / 3)]);
    }
    for (int i = OP_i2b; i <= OP_i2s; i++) {
      table[i] = ConversionInstruction.make(TYPE_int, indexedTypes[5 + (i - OP_i2b)]);
    }

    table[OP_lcmp] = ComparisonInstruction.make(TYPE_long, ComparisonInstruction.Operator.CMP);
    for (int i = OP_fcmpl; i <= OP_dcmpg; i++) {
      table[i] =
          ComparisonInstruction.make(
              indexedTypes[2 + (i - OP_fcmpl) / 2],
              ComparisonInstruction.Operator.values()[
                  ComparisonInstruction.Operator.CMPL.ordinal() + (i - OP_fcmpl) % 2]);
    }

    for (int i = OP_ireturn; i <= OP_areturn; i++) {
      table[i] = ReturnInstruction.make(indexedTypes[i - OP_ireturn]);
    }
    table[OP_return] = ReturnInstruction.make(TYPE_void);

    table[OP_athrow] = ThrowInstruction.make(false);

    table[OP_monitorenter] = MonitorInstruction.make(true);
    table[OP_monitorexit] = MonitorInstruction.make(false);

    table[OP_arraylength] = ArrayLengthInstruction.make();

    return table;
  }
Example #3
0
  private int decodeBytecodeInstruction(int index, int stackLen, byte[] stackWords)
      throws InvalidBytecodeException {
    int opcode = code[index] & 0xFF;

    Instruction i = simpleInstructions[opcode];
    if (i != null) {
      decoded.add(i);
      return index + 1;
    }

    boolean wide = false;

    while (true) {
      index++;

      switch (opcode) {
        case OP_nop:
          break;
        case OP_bipush:
          i = ConstantInstruction.make(code[index]);
          index++;
          break;
        case OP_sipush:
          i = ConstantInstruction.make(decodeShort(index));
          index += 2;
          break;
        case OP_ldc:
          i = makeConstantPoolLoad(code[index] & 0xFF);
          index++;
          break;
        case OP_ldc_w:
          i = makeConstantPoolLoad(decodeShort(index));
          index += 2;
          break;
        case OP_ldc2_w:
          i = makeConstantPoolLoad(decodeShort(index));
          index += 2;
          break;
        case OP_iload:
        case OP_lload:
        case OP_fload:
        case OP_dload:
        case OP_aload:
          i =
              LoadInstruction.make(
                  indexedTypes[opcode - OP_iload],
                  wide ? decodeUShort(index) : (code[index] & 0xFF));
          index += wide ? 2 : 1;
          break;
        case OP_istore:
        case OP_lstore:
        case OP_fstore:
        case OP_dstore:
        case OP_astore:
          i =
              StoreInstruction.make(
                  indexedTypes[opcode - OP_istore],
                  wide ? decodeUShort(index) : (code[index] & 0xFF));
          index += wide ? 2 : 1;
          break;
        case OP_pop2:
          i = PopInstruction.make(elemCount(stackWords, stackLen - 1));
          break;
        case OP_dup_x2:
          i = DupInstruction.make(1, elemCount(stackWords, stackLen - 2));
          break;
        case OP_dup2:
          i = DupInstruction.make(elemCount(stackWords, stackLen - 1), 0);
          break;
        case OP_dup2_x1:
          i = DupInstruction.make(elemCount(stackWords, stackLen - 1), 1);
          break;
        case OP_dup2_x2:
          i =
              DupInstruction.make(
                  elemCount(stackWords, stackLen - 1), elemCount(stackWords, stackLen - 2));
          break;
        case OP_iinc:
          {
            int v = wide ? decodeUShort(index) : (code[index] & 0xFF);
            int c = wide ? decodeShort(index + 2) : code[index + 1];

            decoded.add(LoadInstruction.make(TYPE_int, v));
            decoded.add(ConstantInstruction.make(c));
            decoded.add(BinaryOpInstruction.make(TYPE_int, Operator.ADD));
            i = StoreInstruction.make(TYPE_int, v);
            index += wide ? 4 : 2;
            break;
          }
        case OP_ifeq:
        case OP_ifne:
        case OP_iflt:
        case OP_ifle:
        case OP_ifgt:
        case OP_ifge:
          decoded.add(makeZero);
          i =
              ConditionalBranchInstruction.make(
                  TYPE_int,
                  ConditionalBranchInstruction.Operator.values()[opcode - OP_ifeq],
                  (index - 1) + decodeShort(index));
          index += 2;
          break;
        case OP_if_icmpeq:
        case OP_if_icmpne:
        case OP_if_icmplt:
        case OP_if_icmple:
        case OP_if_icmpgt:
        case OP_if_icmpge:
          i = ConditionalBranchInstruction.make((short) opcode, (index - 1) + decodeShort(index));
          index += 2;
          break;
        case OP_if_acmpeq:
        case OP_if_acmpne:
          i =
              ConditionalBranchInstruction.make(
                  TYPE_Object,
                  ConditionalBranchInstruction.Operator.values()[opcode - OP_if_acmpeq],
                  (index - 1) + decodeShort(index));
          index += 2;
          break;
        case OP_goto:
          i = GotoInstruction.make((index - 1) + decodeShort(index));
          index += 2;
          break;
        case OP_jsr:
          {
            index += 2;
            break;
          }
        case OP_jsr_w:
          {
            index += 4;
            break;
          }
        case OP_ret:
          int v = wide ? decodeUShort(index) : (code[index] & 0xFF);
          i = GotoInstruction.make(-1 - v);

          if (retInfo == null) {
            throw new InvalidBytecodeException("'ret' outside of subroutine");
          }
          retInfo[index - (wide ? 2 : 1)] = new RetInfo(-1, v, stackLen, stackWords);

          index += wide ? 2 : 1;
          break;
        case OP_tableswitch:
          {
            int start = index - 1;
            while ((index & 3) != 0) {
              index++;
            }
            int def = start + decodeInt(index);
            int low = decodeInt(index + 4);
            int high = decodeInt(index + 8);
            int[] t = new int[(high - low + 1) * 2];

            for (int j = 0; j < t.length; j += 2) {
              t[j] = j / 2 + low;
              t[j + 1] = start + decodeInt(index + 12 + j * 2);
            }
            i = SwitchInstruction.make(t, def);
            index += 12 + (high - low + 1) * 4;
            break;
          }
        case OP_lookupswitch:
          {
            int start = index - 1;
            while ((index & 3) != 0) {
              index++;
            }
            int def = start + decodeInt(index);
            int n = decodeInt(index + 4);
            int[] t = new int[n * 2];

            for (int j = 0; j < t.length; j += 2) {
              t[j] = decodeInt(index + 8 + j * 4);
              t[j + 1] = start + decodeInt(index + 12 + j * 4);
            }
            i = SwitchInstruction.make(t, def);
            index += 8 + n * 8;
            break;
          }
        case OP_getstatic:
        case OP_getfield:
          {
            int f = decodeUShort(index);
            i = GetInstruction.make(constantPool, f, opcode == OP_getstatic);
            index += 2;
            break;
          }
        case OP_putstatic:
        case OP_putfield:
          {
            int f = decodeUShort(index);
            i = PutInstruction.make(constantPool, f, opcode == OP_putstatic);
            index += 2;
            break;
          }
        case OP_invokevirtual:
        case OP_invokespecial:
        case OP_invokestatic:
          {
            int m = decodeUShort(index);
            i = InvokeInstruction.make(constantPool, m, opcode);
            index += 2;
            break;
          }
        case OP_invokeinterface:
          {
            int m = decodeUShort(index);
            i = InvokeInstruction.make(constantPool, m, opcode);
            index += 4;
            break;
          }
        case OP_new:
          i = NewInstruction.make(constantPool.getConstantPoolClassType(decodeUShort(index)), 0);
          index += 2;
          break;
        case OP_newarray:
          i = NewInstruction.make(Util.makeArray(getPrimitiveType(code[index])), 1);
          index++;
          break;
        case OP_anewarray:
          i =
              NewInstruction.make(
                  Util.makeArray(constantPool.getConstantPoolClassType(decodeUShort(index))), 1);
          index += 2;
          break;
        case OP_checkcast:
          i = CheckCastInstruction.make(constantPool.getConstantPoolClassType(decodeUShort(index)));
          index += 2;
          break;
        case OP_instanceof:
          i =
              InstanceofInstruction.make(
                  constantPool.getConstantPoolClassType(decodeUShort(index)));
          index += 2;
          break;
        case OP_wide:
          wide = true;
          opcode = code[index] & 0xFF;
          continue;
        case OP_multianewarray:
          i =
              NewInstruction.make(
                  constantPool.getConstantPoolClassType(decodeUShort(index)),
                  code[index + 2] & 0xFF);
          index += 3;
          break;
        case OP_ifnull:
        case OP_ifnonnull:
          decoded.add(ConstantInstruction.make(TYPE_Object, null));
          i =
              ConditionalBranchInstruction.make(
                  TYPE_Object,
                  ConditionalBranchInstruction.Operator.values()[opcode - OP_ifnull],
                  (index - 1) + decodeShort(index));
          index += 2;
          break;
        case OP_goto_w:
          i = GotoInstruction.make((index - 1) + decodeInt(index));
          index += 4;
          break;
        default:
          throw new InvalidBytecodeException("Unknown opcode " + opcode);
      }

      break;
    }

    if (i != null) {
      decoded.add(i);
    }

    return index;
  }