예제 #1
0
  /**
   * Read the interfaces table
   *
   * @param data
   * @param cls
   * @param cp
   * @return Some flags
   */
  private static int readInterfaces(ByteBuffer data, VmType cls, VmCP cp) {
    int flags = 0;
    final int icount = data.getChar();
    if (icount > 0) {
      final VmImplementedInterface[] itable = new VmImplementedInterface[icount];
      for (int i = 0; i < icount; i++) {
        final VmConstClass icls = cp.getConstClass(data.getChar());
        final String iclsName = icls.getClassName();
        itable[i] = new VmImplementedInterface(iclsName);

        for (PragmaInterface pi : INTERFACE_PRAGMAS) {
          if (iclsName.equals(pi.className)) {
            flags |= pi.flags;
          }
        }
      }
      cls.setInterfaceTable(itable);
    }
    return flags;
  }
예제 #2
0
  /**
   * Decode the data of a Exceptions attribute
   *
   * @param data
   * @param cls
   * @param cp
   * @return The read exceptions
   */
  private static final VmExceptions readExceptions(ByteBuffer data, VmType cls, VmCP cp) {

    // Read the exceptions
    char pragmaFlags = 0;
    int pragmas = 0;
    final int ecount = data.getChar();
    final VmConstClass[] list = new VmConstClass[ecount];
    for (int i = 0; i < ecount; i++) {
      final int idx = data.getChar();
      final VmConstClass ccls = cp.getConstClass(idx);
      list[i] = ccls;
      for (MethodPragmaException mp : METHOD_PRAGMA_EXCEPTIONS) {
        if (ccls.getClassName().equals(mp.className)) {
          pragmaFlags |= mp.flags;
          pragmas++;
          list[i] = null;
          break;
        }
      }
    }
    if (pragmas > 0) {
      final int newCnt = ecount - pragmas;
      if (newCnt == 0) {
        return new VmExceptions(null, pragmaFlags);
      } else {
        final VmConstClass[] newList = new VmConstClass[newCnt];
        int k = 0;
        for (int i = 0; i < ecount; i++) {
          final VmConstClass ccls = list[i];
          if (ccls != null) {
            newList[k++] = ccls;
          }
        }
        return new VmExceptions(newList, pragmaFlags);
      }
    } else {
      return new VmExceptions(list, pragmaFlags);
    }
  }
예제 #3
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;
  }