private static object ReadAnnotationElementValue(BigEndianBinaryReader rdr, ClassFile classFile, string[] utf8_cp) { try { byte tag = rdr.ReadByte(); switch (tag) { case (byte)'Z': return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()) != 0; case (byte)'B': return (byte)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'C': return (char)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'S': return (short)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'I': return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'F': return classFile.GetConstantPoolConstantFloat(rdr.ReadUInt16()); case (byte)'J': return classFile.GetConstantPoolConstantLong(rdr.ReadUInt16()); case (byte)'D': return classFile.GetConstantPoolConstantDouble(rdr.ReadUInt16()); case (byte)'s': return classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()); case (byte)'e': { ushort type_name_index = rdr.ReadUInt16(); ushort const_name_index = rdr.ReadUInt16(); return new object[] { AnnotationDefaultAttribute.TAG_ENUM, classFile.GetConstantPoolUtf8String(utf8_cp, type_name_index), classFile.GetConstantPoolUtf8String(utf8_cp, const_name_index) }; } case (byte)'c': return new object[] { AnnotationDefaultAttribute.TAG_CLASS, classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()) }; case (byte)'@': return ReadAnnotation(rdr, classFile, utf8_cp); case (byte)'[': { ushort num_values = rdr.ReadUInt16(); object[] array = new object[num_values + 1]; array[0] = AnnotationDefaultAttribute.TAG_ARRAY; for (int i = 0; i < num_values; i++) { array[i + 1] = ReadAnnotationElementValue(rdr, classFile, utf8_cp); } return array; } default: throw new ClassFormatError("Invalid tag {0} in annotation element_value", tag); } } catch (NullReferenceException) { } catch (InvalidCastException) { } catch (IndexOutOfRangeException) { } return new object[] { AnnotationDefaultAttribute.TAG_ERROR, "java.lang.IllegalArgumentException", "Wrong type at constant pool index" }; }
private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos) { if (bsm.ArgumentCount - argpos < 1) { return false; } if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer) { return false; } int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++)); if (count < 0 || bsm.ArgumentCount - argpos < count) { return false; } for (int i = 0; i < count; i++) { if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type) { return false; } } return true; }
private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm) { ClassFile.ConstantPoolItemMethodHandle mh; AltFlags flags; int argpos = 4; return bsm.ArgumentCount >= 4 && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic && mh.Member != null && IsLambdaAltMetafactory(mh.Member) && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType && classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer && ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 && ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos)) && ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos)) && argpos == bsm.ArgumentCount; }
private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) { if (HasUnloadable(cpi)) { Fail("cpi has unloadable"); return false; } bool serializable = false; TypeWrapper[] markers = TypeWrapper.EmptyArray; ClassFile.ConstantPoolItemMethodType[] bridges = null; if (bsm.ArgumentCount > 3) { AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); serializable = (flags & AltFlags.Serializable) != 0; int argpos = 4; if ((flags & AltFlags.Markers) != 0) { markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < markers.Length; i++) { if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable) { Fail("unloadable marker"); return false; } } } if ((flags & AltFlags.Bridges) != 0) { bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < bridges.Length; i++) { bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); if (HasUnloadable(bridges[i])) { Fail("unloadable bridge"); return false; } } } } ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2)); if (HasUnloadable(samMethodType) || HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) || HasUnloadable(instantiatedMethodType)) { Fail("bsm args has unloadable"); return false; } TypeWrapper interfaceType = cpi.GetRetType(); MethodWrapper[] methodList; if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) { Fail("unsupported interface"); return false; } if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"; })) { Fail("writeReplace"); return false; } if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType)) { Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature); return false; } TypeWrapper[] implParameters = GetImplParameters(implMethod); CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters); if (bridges != null) { foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) { if (bridge.Signature == samMethodType.Signature) { Fail("bridge signature matches sam"); return false; } if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters)) { Fail("bridge constraints"); return false; } } } if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID) { TypeWrapper Rt = instantiatedMethodType.GetRetType(); TypeWrapper Ra = GetImplReturnType(implMethod); if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true)) { Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); return false; } } MethodWrapper interfaceMethod = null; List<MethodWrapper> methods = new List<MethodWrapper>(); foreach (MethodWrapper mw in methodList) { if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature) { interfaceMethod = mw; methods.Add(mw); } else if (mw.IsAbstract && !IsObjectMethod(mw)) { methods.Add(mw); } } if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType)) { Fail("interfaceMethod"); return false; } TypeBuilder tb = context.DefineAnonymousClass(); // we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore), // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1) { tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); } foreach (TypeWrapper marker in markers) { tb.AddInterfaceImplementation(marker.TypeAsBaseType); } ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); AddDefaultInterfaceMethods(context, methodList, tb); return true; }
private static object ReadAnnotationElementValue(BigEndianBinaryReader rdr, ClassFile classFile) { byte tag = rdr.ReadByte(); switch(tag) { case (byte)'Z': return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()) != 0; case (byte)'B': return (byte)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'C': return (char)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'S': return (short)classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'I': return classFile.GetConstantPoolConstantInteger(rdr.ReadUInt16()); case (byte)'F': return classFile.GetConstantPoolConstantFloat(rdr.ReadUInt16()); case (byte)'J': return classFile.GetConstantPoolConstantLong(rdr.ReadUInt16()); case (byte)'D': return classFile.GetConstantPoolConstantDouble(rdr.ReadUInt16()); case (byte)'s': return classFile.GetConstantPoolUtf8String(rdr.ReadUInt16()); case (byte)'e': { ushort type_name_index = rdr.ReadUInt16(); ushort const_name_index = rdr.ReadUInt16(); return new object[] { AnnotationDefaultAttribute.TAG_ENUM, classFile.GetConstantPoolUtf8String(type_name_index), classFile.GetConstantPoolUtf8String(const_name_index) }; } case (byte)'c': return new object[] { AnnotationDefaultAttribute.TAG_CLASS, classFile.GetConstantPoolUtf8String(rdr.ReadUInt16()) }; case (byte)'@': return ReadAnnotation(rdr, classFile); case (byte)'[': { ushort num_values = rdr.ReadUInt16(); object[] array = new object[num_values + 1]; array[0] = AnnotationDefaultAttribute.TAG_ARRAY; for(int i = 0; i < num_values; i++) { array[i + 1] = ReadAnnotationElementValue(rdr, classFile); } return array; } default: throw new ClassFormatError("Invalid tag {0} in annotation element_value", tag); } }
internal Field(ClassFile classFile, BigEndianBinaryReader br) : base(classFile, br) { if((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) || (IsFinal && IsVolatile) || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient))) { throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, access_flags); } int attributes_count = br.ReadUInt16(); for(int i = 0; i < attributes_count; i++) { switch(classFile.GetConstantPoolUtf8String(br.ReadUInt16())) { case "Deprecated": if(br.ReadUInt32() != 0) { throw new ClassFormatError("Invalid Deprecated attribute length"); } flags |= FLAG_MASK_DEPRECATED; break; case "ConstantValue": { if(br.ReadUInt32() != 2) { throw new ClassFormatError("Invalid ConstantValue attribute length"); } ushort index = br.ReadUInt16(); try { switch(Signature) { case "I": constantValue = classFile.GetConstantPoolConstantInteger(index); break; case "S": constantValue = (short)classFile.GetConstantPoolConstantInteger(index); break; case "B": constantValue = (byte)classFile.GetConstantPoolConstantInteger(index); break; case "C": constantValue = (char)classFile.GetConstantPoolConstantInteger(index); break; case "Z": constantValue = classFile.GetConstantPoolConstantInteger(index) != 0; break; case "J": constantValue = classFile.GetConstantPoolConstantLong(index); break; case "F": constantValue = classFile.GetConstantPoolConstantFloat(index); break; case "D": constantValue = classFile.GetConstantPoolConstantDouble(index); break; case "Ljava.lang.String;": constantValue = classFile.GetConstantPoolConstantString(index); break; default: throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name); } } catch(InvalidCastException) { throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); } catch(IndexOutOfRangeException) { throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); } catch(InvalidOperationException) { throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); } catch(NullReferenceException) { throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); } break; } case "Signature": if(classFile.MajorVersion < 49) { goto default; } if(br.ReadUInt32() != 2) { throw new ClassFormatError("Signature attribute has incorrect length"); } signature = classFile.GetConstantPoolUtf8String(br.ReadUInt16()); break; case "RuntimeVisibleAnnotations": if(classFile.MajorVersion < 49) { goto default; } annotations = ReadAnnotations(br, classFile); break; case "RuntimeInvisibleAnnotations": if(classFile.MajorVersion < 49) { goto default; } foreach(object[] annot in ReadAnnotations(br, classFile)) { if(annot[1].Equals("Likvm/lang/Property;")) { DecodePropertyAnnotation(classFile, annot); } #if STATIC_COMPILER else if(annot[1].Equals("Likvm/lang/Internal;")) { this.access_flags &= ~Modifiers.AccessMask; flags |= FLAG_MASK_INTERNAL; } #endif } break; default: br.Skip(br.ReadUInt32()); break; } } }