Example #1
0
  /**
   * Read the fields table
   *
   * @param data
   * @param cp
   * @param slotSize
   * @param loader
   */
  private static FieldData[] readFields(
      ByteBuffer data, VmCP cp, int slotSize, VmClassLoader loader) {
    final int fcount = data.getChar();
    if (fcount > 0) {
      final FieldData[] ftable = new FieldData[fcount];

      for (int i = 0; i < fcount; i++) {
        int modifiers = data.getChar();
        final String name = cp.getUTF8(data.getChar());
        final String signature = cp.getUTF8(data.getChar());
        final boolean isstatic = ((modifiers & Modifier.ACC_STATIC) != 0);

        // Read field attributes
        final int acount = data.getChar();
        VmAnnotation[] rVisAnn = null;
        byte[] rawAnnotations = null;
        Object constantValue = null;
        for (int a = 0; a < acount; a++) {
          final String attrName = cp.getUTF8(data.getChar());
          final int length = data.getInt();
          if (isstatic && VmArray.equals(ConstantValueAttrName, attrName)) {
            constantValue = cp.getAny(data.getChar());
          } else if (VmArray.equals(RuntimeVisibleAnnotationsAttrName, attrName)) {
            rawAnnotations = new byte[length];
            data.slice().get(rawAnnotations);
            rVisAnn = readRuntimeAnnotations(data, cp, true, loader);
          } else if (VmArray.equals(RuntimeInvisibleAnnotationsAttrName, attrName)) {
            readRuntimeAnnotations(data, cp, false, loader);
          } else {
            skip(data, length);
          }
        }

        ftable[i] =
            new FieldData(name, signature, modifiers, constantValue, rVisAnn, rawAnnotations);
      }
      return ftable;
    } else {
      return null;
    }
  }
Example #2
0
  /**
   * Decode the data of a code-attribute
   *
   * @param data
   * @param cls
   * @param cp
   * @param method
   * @return The read code
   */
  private static final VmByteCode readCode(ByteBuffer data, VmType cls, VmCP cp, VmMethod method) {

    final int maxStack = data.getChar();
    final int noLocals = data.getChar();
    final int codelength = data.getInt();
    final ByteBuffer code = readBytes(data, codelength);

    // Read the exception Table
    final int ecount = data.getChar();
    final VmInterpretedExceptionHandler[] etable = new VmInterpretedExceptionHandler[ecount];
    for (int i = 0; i < ecount; i++) {
      final int startPC = data.getChar();
      final int endPC = data.getChar();
      final int handlerPC = data.getChar();
      final int catchType = data.getChar();
      etable[i] = new VmInterpretedExceptionHandler(cp, startPC, endPC, handlerPC, catchType);
    }

    // Read the attributes
    VmLineNumberMap lnTable = null;
    VmLocalVariableTable lvTable = VmLocalVariableTable.EMPTY;
    final int acount = data.getChar();
    for (int i = 0; i < acount; i++) {
      final String attrName = cp.getUTF8(data.getChar());
      final int len = data.getInt();
      if (VmArray.equals(LineNrTableAttrName, attrName)) {
        lnTable = readLineNrTable(data);
      } else if (VmArray.equals(LocalVariableTableAttrName, attrName)) {
        lvTable = readLocalVariableTable(data, cp);
      } else {
        skip(data, len);
      }
    }

    return new VmByteCode(method, code, noLocals, maxStack, etable, lnTable, lvTable);
  }
Example #3
0
  /**
   * Read the method table
   *
   * @param data
   * @param rejectNatives
   * @param cls
   * @param cp
   * @param statics
   * @param cl
   */
  private static void readMethods(
      ByteBuffer data,
      boolean rejectNatives,
      VmType cls,
      VmCP cp,
      VmStatics statics,
      VmClassLoader cl) {
    final int mcount = data.getChar();
    if (mcount > 0) {
      final VmMethod[] mtable = new VmMethod[mcount];

      for (int i = 0; i < mcount; i++) {
        final int modifiers = data.getChar();
        final String name = cp.getUTF8(data.getChar());
        final String signature = cp.getUTF8(data.getChar());
        final boolean isStatic = ((modifiers & Modifier.ACC_STATIC) != 0);

        final VmMethod mts;
        final boolean isSpecial = name.equals("<init>");
        // final int staticsIdx = statics.allocMethod();
        if (isStatic || isSpecial) {
          if (isSpecial) {
            mts = new VmSpecialMethod(name, signature, modifiers, cls);
          } else {
            mts = new VmStaticMethod(name, signature, modifiers, cls);
          }
        } else {
          mts = new VmInstanceMethod(name, signature, modifiers, cls);
        }
        // statics.setMethod(staticsIdx, mts);
        mtable[i] = mts;

        // Read methods attributes
        final int acount = data.getChar();
        VmAnnotation[] rVisAnn = null;
        VmAnnotation[] rInvisAnn = null;
        for (int a = 0; a < acount; a++) {
          String attrName = cp.getUTF8(data.getChar());
          int length = data.getInt();
          if (VmArray.equals(CodeAttrName, attrName)) {
            mts.setBytecode(readCode(data, cls, cp, mts));
          } else if (VmArray.equals(ExceptionsAttrName, attrName)) {
            mts.setExceptions(readExceptions(data, cls, cp));
          } else if (VmArray.equals(RuntimeVisibleAnnotationsAttrName, attrName)) {
            byte[] buf = new byte[length];
            data.slice().get(buf);
            mts.setRawAnnotations(buf);

            // todo will get obsolate with openjdk based annotation support
            // rVisAnn = readRuntimeAnnotations(data, cp, true, cl);
            rVisAnn = readRuntimeAnnotations2(data, cp, true, cl, cls);

          } else if (VmArray.equals(RuntimeInvisibleAnnotationsAttrName, attrName)) {
            rInvisAnn = readRuntimeAnnotations(data, cp, false, cl);
          } else if (VmArray.equals(RuntimeVisibleParameterAnnotationsAttrName, attrName)) {

            byte[] buf = new byte[length];
            data.slice().get(buf);
            mts.setRawParameterAnnotations(buf);
            // todo will get obsolate with openjdk based annotation support
            readRuntimeParameterAnnotations(data, cp, true, cl);
          } else if (VmArray.equals(RuntimeInvisibleParameterAnnotationsAttrName, attrName)) {
            readRuntimeParameterAnnotations(data, cp, false, cl);
          } else if (VmArray.equals(AnnotationDefaultAttrName, attrName)) {
            // todo will get obsolate with openjdk based annotation support
            byte[] buf = new byte[length];
            data.slice().get(buf);
            mts.setRawAnnotationDefault(buf);

            Class r_class;
            VmType vtm = mts.getReturnType();
            if (vtm.isPrimitive()) {
              r_class = getClassForJvmType(vtm.getJvmType());
            } else {
              try {
                r_class = Class.forName(vtm.getName(), false, vtm.getLoader().asClassLoader());
              } catch (ClassNotFoundException cnf) {
                throw new RuntimeException(cnf);
              }
            }
            Object defo =
                AnnotationParser.parseMemberValue(
                    r_class,
                    data,
                    new VmConstantPool(cls),
                    VmUtils.isRunningVm() ? cls.asClass() : cls.asClassDuringBootstrap());
            mts.setAnnotationDefault(defo);
          } else {
            skip(data, length);
          }
        }
        mts.setRuntimeAnnotations(rVisAnn);
        if (rVisAnn != null) {
          mts.addPragmaFlags(getMethodPragmaFlags(rVisAnn, cls.getName()));
        }
        if (rInvisAnn != null) {
          mts.addPragmaFlags(getMethodPragmaFlags(rInvisAnn, cls.getName()));
        }
        if ((modifiers & Modifier.ACC_NATIVE) != 0) {
          final VmByteCode bc = getNativeCodeReplacement(mts, cl, rejectNatives);
          if (bc != null) {
            mts.setModifier(false, Modifier.ACC_NATIVE);
            mts.setBytecode(bc);
          } else {
            if (rejectNatives) {
              throw new ClassFormatError("Native method " + mts);
            }
          }
        }
      }
      cls.setMethodTable(mtable);
    }
  }
Example #4
0
  /**
   * Decode a given class.
   *
   * @param data
   * @param rejectNatives
   * @param clc
   * @param protectionDomain
   * @return The decoded class
   * @throws ClassFormatError
   */
  private static final VmType decodeClass(
      ByteBuffer data, boolean rejectNatives, VmClassLoader clc, ProtectionDomain protectionDomain)
      throws ClassFormatError {
    final VmSharedStatics sharedStatics = clc.getSharedStatics();
    final VmIsolatedStatics isolatedStatics = clc.getIsolatedStatics();
    final int slotSize = clc.getArchitecture().getReferenceSize();

    final int magic = data.getInt();
    if (magic != 0xCAFEBABE) {
      throw new ClassFormatError("invalid magic");
    }
    final int min_version = data.getChar();
    final int maj_version = data.getChar();

    if (false) {
      BootLogInstance.get().debug("Class file version " + maj_version + ';' + min_version);
    }

    final int cpcount = data.getChar();
    // allocate enough space for the CP
    final byte[] tags = new byte[cpcount];
    final VmCP cp = new VmCP(cpcount);
    for (int i = 1; i < cpcount; i++) {
      final int tag = data.get() & 0xFF;
      tags[i] = (byte) tag;
      switch (tag) {
        case 1:
          // Utf8
          cp.setUTF8(i, readUTF(data));
          break;
        case 3:
          // int
          cp.setInt(i, data.getInt());
          break;
        case 4:
          // float
          // cp.setInt(i, data.getInt());
          final int ival = data.getInt();
          final float fval = Float.intBitsToFloat(ival);
          cp.setFloat(i, fval);
          break;
        case 5:
          // long
          cp.setLong(i, data.getLong());
          i++;
          break;
        case 6:
          // double
          // cp.setLong(i, data.getLong());
          final long lval = data.getLong();
          final double dval = Double.longBitsToDouble(lval);
          cp.setDouble(i, dval);
          i++;
          break;
        case 7:
          // class
          cp.setInt(i, data.getChar());
          break;
        case 8:
          // String
          cp.setInt(i, data.getChar());
          break;
        case 9: // Fieldref
        case 10: // Methodref
        case 11: // IMethodref
          {
            final int clsIdx = data.getChar();
            final int ntIdx = data.getChar();
            cp.setInt(i, clsIdx << 16 | ntIdx);
            break;
          }
        case 12:
          // Name and Type
          {
            final int nIdx = data.getChar();
            final int dIdx = data.getChar();
            cp.setInt(i, nIdx << 16 | dIdx);
            break;
          }
        default:
          throw new ClassFormatError("Invalid constantpool tag: " + tags[i]);
      }
    }

    // Now patch the required entries (level 1)
    for (int i = 1; i < cpcount; i++) {
      switch (tags[i]) {
        case 7:
          {
            // Class
            final int idx = cp.getInt(i);
            final VmConstClass constClass = new VmConstClass(cp.getUTF8(idx));
            cp.setConstClass(i, constClass);
            break;
          }
        case 8:
          {
            // String
            final int idx = cp.getInt(i);
            final int staticsIdx = sharedStatics.allocConstantStringField(cp.getUTF8(idx));
            final VmConstString constStr = new VmConstString(staticsIdx);
            cp.setString(i, constStr);
            break;
          }
      }
    }

    // Now patch the required entries (level 2)
    for (int i = 1; i < cpcount; i++) {
      final int tag = tags[i];
      if ((tag >= 9) && (tag <= 11)) {
        final int v = cp.getInt(i);
        final VmConstClass constClass = cp.getConstClass(v >>> 16);
        final int nat = cp.getInt(v & 0xFFFF);
        final String name = cp.getUTF8(nat >>> 16);
        final String descriptor = cp.getUTF8(nat & 0xFFFF);
        switch (tag) {
          case 9:
            // FieldRef
            cp.setConstFieldRef(i, new VmConstFieldRef(constClass, name, descriptor));
            break;
          case 10:
            // MethodRef
            cp.setConstMethodRef(i, new VmConstMethodRef(constClass, name, descriptor));
            break;
          case 11:
            // IMethodRef
            cp.setConstIMethodRef(i, new VmConstIMethodRef(constClass, name, descriptor));
            break;
        }
      }
    }

    // Cleanup the unwantend entries
    for (int i = 1; i < cpcount; i++) {
      switch (tags[i]) {
        case 12:
          // Name and Type
          cp.reset(i);
          break;
      }
    }

    final int classModifiers = data.getChar();

    final VmConstClass this_class = cp.getConstClass(data.getChar());
    final String clsName = this_class.getClassName();

    final VmConstClass super_class = cp.getConstClass(data.getChar());
    final String superClassName;
    if (super_class != null) {
      superClassName = super_class.getClassName();
    } else {
      superClassName = null;
    }

    // Allocate the class object
    final VmType cls;
    if (Modifier.isInterface(classModifiers)) {
      cls = new VmInterfaceClass(clsName, superClassName, clc, classModifiers, protectionDomain);
    } else {
      cls = new VmNormalClass(clsName, superClassName, clc, classModifiers, protectionDomain);
    }
    cls.setCp(cp);

    // Determine if we can safely align the fields
    // int pragmaFlags = 0;
    if (isBootType(cls)) {
      cls.addPragmaFlags(TypePragmaFlags.NO_FIELD_ALIGNMENT);
    }
    cls.addPragmaFlags(getClassNamePragmaFlags(clsName));

    // Interface table
    cls.addPragmaFlags(readInterfaces(data, cls, cp));

    // Field table
    final FieldData[] fieldData = readFields(data, cp, slotSize, clc);

    // Method Table
    readMethods(data, rejectNatives, cls, cp, sharedStatics, clc);

    // Read class attributes
    final int acount = data.getChar();
    VmAnnotation[] rVisAnn = null;
    VmAnnotation[] rInvisAnn = null;
    String sourceFile = null;
    String signature = null;
    for (int a = 0; a < acount; a++) {
      final String attrName = cp.getUTF8(data.getChar());
      final int length = data.getInt();
      if (VmArray.equals(RuntimeVisibleAnnotationsAttrName, attrName)) {
        byte[] buf = new byte[length];
        data.slice().get(buf);
        cls.setRawAnnotations(buf);
        rVisAnn = readRuntimeAnnotations(data, cp, true, clc);
      } else if (VmArray.equals(RuntimeInvisibleAnnotationsAttrName, attrName)) {
        rInvisAnn = readRuntimeAnnotations(data, cp, false, clc);
      } else if (VmArray.equals(SourceFileAttrName, attrName)) {
        sourceFile = cp.getUTF8(data.getChar());
      } else if (VmArray.equals(SignatureAttrName, attrName)) {
        signature = cp.getUTF8(data.getChar());
      } else {
        skip(data, length);
      }
    }
    cls.setRuntimeAnnotations(rVisAnn);
    cls.setSourceFile(sourceFile);
    cls.setSignature(signature);
    if (rInvisAnn != null) {
      cls.addPragmaFlags(getClassPragmaFlags(rInvisAnn, clsName));
    }
    if (rVisAnn != null) {
      cls.addPragmaFlags(getClassPragmaFlags(rVisAnn, clsName));
    }

    // Create the fields
    if (fieldData != null) {
      createFields(cls, fieldData, sharedStatics, isolatedStatics, slotSize, cls.getPragmaFlags());
    }

    return cls;
  }