Esempio n. 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;
    }
  }
Esempio n. 2
0
 /**
  * Read a single annotation structure.
  *
  * @param data
  * @param cp
  */
 private static VmAnnotation readAnnotation(ByteBuffer data, VmCP cp, boolean visible) {
   final String typeDescr = cp.getUTF8(data.getChar());
   final int numElemValuePairs = data.getChar();
   final VmAnnotation.ElementValue[] values;
   if (numElemValuePairs == 0) {
     values = VmAnnotation.ElementValue.EMPTY_ARR;
   } else if (visible) {
     values = new VmAnnotation.ElementValue[numElemValuePairs];
     for (int i = 0; i < numElemValuePairs; i++) {
       final String elemName = cp.getUTF8(data.getChar());
       final Object value = readElementValue(data, cp);
       values[i] = new VmAnnotation.ElementValue(elemName, value);
     }
   } else {
     values = VmAnnotation.ElementValue.EMPTY_ARR;
     for (int i = 0; i < numElemValuePairs; i++) {
       data.getChar(); // Skip name ref
       skipElementValue(data, cp);
     }
   }
   return new VmAnnotation(typeDescr, values);
 }
Esempio n. 3
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;
  }
Esempio n. 4
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);
    }
  }
Esempio n. 5
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);
  }
Esempio n. 6
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);
    }
  }
Esempio n. 7
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;
  }
Esempio n. 8
0
 /**
  * Read a single element_value structure.
  *
  * @param data
  * @param cp
  */
 private static Object readElementValue(ByteBuffer data, VmCP cp) {
   final int tag = data.get() & 0xFF;
   switch (tag) {
     case 'B':
       return (byte) cp.getInt(data.getChar());
     case 'C':
       return (char) cp.getInt(data.getChar());
     case 'D':
       return cp.getDouble(data.getChar());
     case 'F':
       return cp.getFloat(data.getChar());
     case 'I':
       return cp.getInt(data.getChar());
     case 'J':
       return cp.getLong(data.getChar());
     case 'S':
       return (short) cp.getInt(data.getChar());
     case 'Z':
       return cp.getInt(data.getChar()) != 0;
     case 's':
       return cp.getAny(data.getChar());
     case 'e': // enum
       {
         final String typeDescr = cp.getUTF8(data.getChar());
         final String constName = cp.getUTF8(data.getChar());
         return new VmAnnotation.EnumValue(typeDescr, constName);
       }
     case 'c': // class
       {
         final String classDescr = cp.getUTF8(data.getChar());
         return new VmAnnotation.ClassInfo(classDescr);
       }
     case '@': // annotation
       return readAnnotation(data, cp, true);
     case '[': // array
       {
         final int numValues = data.getChar();
         final Object[] arr = new Object[numValues];
         for (int i = 0; i < numValues; i++) {
           arr[i] = readElementValue(data, cp);
         }
         return arr;
       }
     default:
       throw new ClassFormatError("Unknown element_value tag '" + (char) tag + '\'');
   }
 }
Esempio n. 9
0
  /**
   * Read a single annotation structure.
   *
   * @param data
   * @param cp
   */
  private static VmAnnotation readAnnotation2(
      ByteBuffer data, VmCP cp, boolean visible, VmClassLoader loader, VmType vmType) {
    final String typeDescr = cp.getUTF8(data.getChar());
    final int numElemValuePairs = data.getChar();
    final VmAnnotation.ElementValue[] values;
    if (numElemValuePairs == 0) {
      values = VmAnnotation.ElementValue.EMPTY_ARR;
    } else if (visible) {
      values = new VmAnnotation.ElementValue[numElemValuePairs];
      for (int i = 0; i < numElemValuePairs; i++) {
        final String elemName = cp.getUTF8(data.getChar());

        Object defo = null; // readElementValue(data, cp);

        try {
          VmType annType = new Signature(typeDescr, loader).getType();

          VmMethod mts = null;
          int dmc = annType.getNoDeclaredMethods();
          for (int v = 0; v < dmc; v++) {
            VmMethod m = annType.getDeclaredMethod(v);
            if (elemName.equals(m.getName())) {
              mts = m;
              break;
            }
          }

          Class r_class;
          VmType vtm = mts.getReturnType();
          if (vtm.isPrimitive()) {
            r_class = getClassForJvmType(vtm.getJvmType());
          } else {
            try {
              r_class = vtm.getLoader().asClassLoader().loadClass(vtm.getName());
            } catch (ClassNotFoundException cnf) {
              throw new RuntimeException(cnf);
            }
          }
          Class container;
          try {

            container = annType.getLoader().asClassLoader().loadClass(annType.getName());
          } catch (ClassNotFoundException cnf) {
            throw new RuntimeException(cnf);
          }
          defo =
              AnnotationParser.parseMemberValue(
                  r_class, data, new VmConstantPool(vmType), container);

          if (defo instanceof ExceptionProxy)
            throw new RuntimeException(
                "Error parsing annotation parameter value (annotation= "
                    + annType.getName()
                    + ", parameter="
                    + mts.getName()
                    + ')');

        } catch (Exception e) {
          throw new RuntimeException(e);
        }

        final Object value = defo; // readElementValue(data, cp);
        values[i] = new VmAnnotation.ElementValue(elemName, value);
      }
    } else {
      values = VmAnnotation.ElementValue.EMPTY_ARR;
      for (int i = 0; i < numElemValuePairs; i++) {
        data.getChar(); // Skip name ref
        skipElementValue(data, cp);
      }
    }
    return new VmAnnotation(typeDescr, values);
  }