private static Object ExtractArrayValue(Signature.Type type, BinaryReader reader, MetaDataResolver resolver, MetaDataResolver[] resolvers) { int arraySize = reader.ReadInt32(); if (arraySize >= 0) { ElementTypes elementType = type.ElementType; if (elementType == ElementTypes.CLASS) { Object[] array = new Object[arraySize]; for (int i = 0; i < arraySize; i++) { array[i] = ExtractParameter(type, reader, resolver, resolvers); } return(array); } else { return(ExtractArrayValue(elementType, arraySize, reader)); } } else { throw new Exception("Not implemented: custom attribute class " + "array with negative length"); } }
private static MetaDataTypeDefinition ResolveName(MetaDataResolver resolver, MetaDataResolver[] resolvers, String typeName) { MetaDataTypeDefinition typeDef = resolver.ResolveName(typeName); int i = 0; while (typeDef == null && i < resolvers.Length) { MetaDataResolver testResolver = resolvers[i]; i++; if (testResolver != resolver) { typeDef = testResolver.ResolveName(typeName); } } return(typeDef); }
private static MetaDataObject ResolveTypeRef(MetaDataResolver resolver, MetaDataResolver[] resolvers, MetaDataTypeReference typeRef) { MetaDataObject result = resolver.ResolveTypeRef(typeRef); int i = 0; while (result == null && i < resolvers.Length) { MetaDataResolver testResolver = resolvers[i]; i++; if (testResolver != resolver) { result = testResolver.ResolveTypeRef(typeRef); } } return(result); }
private static Object ExtractEnumValue(MetaDataTypeDefinition typeDef, BinaryReader reader, MetaDataResolver resolver, MetaDataResolver[] resolvers) { MetaDataField[] classFields = typeDef.Fields; for (int i = 0; i < classFields.Length; i++) { if ((classFields[i].Flags & (int)MetaDataField.FieldAttributes.Static) == 0) { if (!classFields[i].Name.Equals("value__")) { throw new MetaDataLoader.IllegalMetaDataFormatException("Found enum with non-static field " + classFields[i].Name); } return(ExtractParameter(classFields[i].Signature.FieldType, reader, resolver, resolvers)); } } throw new MetaDataLoader.IllegalMetaDataFormatException("Found enum without non-static field"); }
// Resolve all the custom attributes found in the assemblies registered // in 'resolver', using all the type information found in 'resolver' and // 'resolvers'. internal void resolveReferences(MetaDataResolver resolver, MetaDataResolver[] resolvers) { if (this.buffer[0] != 0x01 || this.buffer[1] != 0x00) { throw new MetaDataLoader.IllegalMetaDataFormatException("Custom Attribute doesn't start with 0x0001!"); } SignatureMethod signature; if (this.type is MetaDataMethod) { MetaDataMethod method = (MetaDataMethod)this.type; signature = (SignatureMethod)method.Signature; if (!method.Name.Equals(".ctor")) { throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected method name: " + method.Name); } this.typeDefOrRef = method.Parent; this.name = method.Parent.FullName; } else if (this.type is MetaDataMemberRef) { MetaDataMemberRef memberRef = (MetaDataMemberRef)this.type; signature = (SignatureMethod)memberRef.Signature; if (!memberRef.Name.Equals(".ctor")) { throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected memberRef name: " + memberRef.Name); } MetaDataObject methodParent = memberRef.Class; this.typeDefOrRef = methodParent; if (methodParent is MetaDataTypeDefinition) { this.name = ((MetaDataTypeDefinition)methodParent).FullName; } else if (methodParent is MetaDataTypeReference) { this.name = ((MetaDataTypeReference)methodParent).FullName; } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected class type: " + methodParent); } } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Custom attribute with unexpected type: " + this.type); } Signature.Param[] parameters = signature.Parameters; int fixedCount = parameters.Length; this.fixedArgs = new Object[fixedCount]; MemoryStream stream = new MemoryStream(this.buffer, 2, this.buffer.Length - 2, false); BinaryReader reader = new BinaryReader(stream); for (int i = 0; i < fixedCount; i++) { Signature.Param parameter = parameters[i]; Signature.Type paramType = parameter.Type; Object value = ExtractParameter(paramType, reader, resolver, resolvers); fixedArgs[i] = value; } short namedCount = ((reader.PeekChar() == -1) ? (short)0 : reader.ReadInt16()); if (namedCount > this.buffer.Length && this.Name.Equals("System.Runtime.CompilerServices.RequiredAttributeAttribute")) { // Some CLR libraries have been compiled against a version of // mscorlib that had a fixed parameter to RequiredAttribute. // Simply ignore whatever the parameter was! namedCount = 0; } this.namedArgs = new NamedArg[namedCount]; for (int i = 0; i < namedCount; i++) { SerializationTypes propOrField = (SerializationTypes) reader.ReadByte(); ElementTypes fieldType = (ElementTypes)reader.ReadByte(); ElementTypes arrayType = ElementTypes.END; switch (fieldType) { case ElementTypes.SZARRAY: { arrayType = (ElementTypes)reader.ReadByte(); if (arrayType == (ElementTypes)SerializationTypes.ENUM) { throw new Exception("Not implemented: Array of ENUM " + "for named field/property"); } break; } case (ElementTypes)SerializationTypes.ENUM: { String enumName = ExtractString(reader); if (enumName.Length == 0) { throw new Exception("Empty enum name"); } // Hope it is a 4-byte enum fieldType = (ElementTypes)SerializationTypes.U4; break; } case (ElementTypes)SerializationTypes.TAGGED_OBJECT: { throw new Exception("Not implemented: " + fieldType + " for named field/property"); } default: { break; } } String name = ExtractString(reader); Object value; if (fieldType == ElementTypes.SZARRAY) { value = ExtractArrayValue(arrayType, reader); } else { value = ExtractValue(fieldType, reader); } if (propOrField == SerializationTypes.FIELD || propOrField == SerializationTypes.PROPERTY) { this.namedArgs[i] = new NamedArg(propOrField == SerializationTypes.FIELD, -1, name, value); } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Unknown prop-or-field type: " + propOrField); } } }
private static Object ExtractParameter(Signature.Type type, BinaryReader reader, MetaDataResolver resolver, MetaDataResolver[] resolvers) { switch (type.ElementType) { case ElementTypes.VALUETYPE: { MetaDataObject classObject = type.ClassObject; if (classObject is MetaDataTypeReference) { MetaDataTypeReference classReference = (MetaDataTypeReference)classObject; MetaDataObject resolvedObject = ResolveTypeRef(resolver, resolvers, classReference); if (resolvedObject is MetaDataTypeDefinition) { classObject = resolvedObject; } } if (classObject is MetaDataTypeReference) { // We will simply assume it is an I4 enum Console.Out.WriteLine("====>>> WARNING: Making I4 enum assumption for " + classObject); return(reader.ReadInt32()); } else if (classObject is MetaDataTypeDefinition) { MetaDataTypeDefinition classDef = (MetaDataTypeDefinition)classObject; MetaDataObject superClass = classDef.Extends; String superName; if (superClass is MetaDataTypeDefinition) { superName = ((MetaDataTypeDefinition)superClass).FullName; } else if (superClass is MetaDataTypeReference) { superName = ((MetaDataTypeReference)superClass).FullName; } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected superclass of valuetype: " + superClass); } if (!superName.Equals("System.Enum")) { throw new MetaDataLoader.IllegalMetaDataFormatException("Found valuetype that wasn't an Enum"); } return(ExtractEnumValue(classDef, reader, resolver, resolvers)); } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected valuetype class: " + classObject); } } case ElementTypes.CLASS: { MetaDataObject classObject = type.ClassObject; if (classObject is MetaDataTypeReference) { MetaDataTypeReference classReference = (MetaDataTypeReference)classObject; MetaDataObject resolvedObject = ResolveTypeRef(resolver, resolvers, classReference); if (resolvedObject is MetaDataTypeDefinition) { classObject = resolvedObject; } } String className; if (classObject is MetaDataTypeReference) { className = ((MetaDataTypeReference)classObject).FullName; } else if (classObject is MetaDataTypeDefinition) { className = ((MetaDataTypeDefinition)classObject).FullName; } else { throw new MetaDataLoader.IllegalMetaDataFormatException("Unexpected class: " + classObject); } if (className.Equals("System.String")) { return(ExtractString(reader)); } else if (className.Equals("System.Object")) { goto case ElementTypes.OBJECT; } else if (className.Equals("System.Type")) { return(ExtractString(reader)); } if (!(classObject is MetaDataTypeDefinition)) { throw new MetaDataLoader.IllegalMetaDataFormatException("Cannot determine whether the following is an array: " + classObject); } MetaDataObject superClass = ((MetaDataTypeDefinition)classObject).Extends; Console.WriteLine("class is " + classObject); throw new Exception("Not implemented: object encoding an array"); } case ElementTypes.OBJECT: case (ElementTypes)SerializationTypes.TAGGED_OBJECT: { SerializationTypes objectType = (SerializationTypes) reader.ReadByte(); switch (objectType) { case SerializationTypes.ENUM: { String typeName = ExtractString(reader); // Some Stringified type names include a bunch of // information past the type, none of which we // are concerned about for the moment. int nameEnd = typeName.IndexOf(','); if (nameEnd >= 0) { typeName = typeName.Substring(0, nameEnd); } // A type defined within another type has a "+" // as the separator. Convert it to ".", which is // the convention the rest of the reader uses. typeName = typeName.Replace('+', '.'); MetaDataTypeDefinition typeDef = ResolveName(resolver, resolvers, typeName); if (typeDef == null) { throw new Exception("No typedef for " + typeName); } return(ExtractEnumValue(typeDef, reader, resolver, resolvers)); } case SerializationTypes.TYPE: { return(ExtractValue((ElementTypes)objectType, reader)); } default: { throw new Exception("Found OBJECT type with type " + objectType); } } } case ElementTypes.SZARRAY: { return(ExtractArrayValue(type.TypeObject, reader, resolver, resolvers)); } default: { return(ExtractValue(type.ElementType, reader)); } } }