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");
            }
        }
Exemplo n.º 2
0
        internal void resolveReferences(MetaDataLoader loader,
                                        PELoader peLoader,
                                        Stream fileStream)
        {
            this.field.resolveReferences(this);
            int dataOffset = peLoader.VaToOffsetSafe(this.rva);

            if (dataOffset != -1)
            {
                fileStream.Seek(dataOffset, SeekOrigin.Begin);
                BinaryReader   reader         = new BinaryReader(fileStream);
                SignatureField fieldSignature = (SignatureField)
                                                this.field.Signature;
                Signature.Type fieldType = fieldSignature.FieldType;
                int            dataSize  = this.getFieldSize(fieldType);
                byte[]         data      = new byte[dataSize];
                int            count     = reader.Read(data, 0, dataSize);
                if (loader.HasVtableFixup() &&
                    loader.RVAHasRelocation(dataOffset) &&
                    dataSize == 4)
                {
                    // if this corresponds to a vtable label, we need to fix it
                    int location = data[0] | (data[1] << 8) |
                                   (data[2] << 16) | (data[3] << 24);
                    int imageBase = peLoader.getImageBase();
                    location -= imageBase; // use RVA
                    fileStream.Seek(location, SeekOrigin.Begin);
                    BinaryReader binaryReader = new BinaryReader(fileStream);
                    short        prefix       = binaryReader.ReadInt16();
                    if (prefix == 0x25FF) // this starts a vtable lable
                    {
                        count = binaryReader.Read(data, 0, 4);
                    }
                }
                this.dataBytes = data;

                if (count != dataSize)
                {
                    throw new MetaDataLoader.IllegalMetaDataFormatException("Only got " + count + " out of " + dataSize + " data bytes for FieldRVA " + this.rva);
                }
            }
            else
            {
                Console.WriteLine("Found no data for " + this.field);
            }
        }
Exemplo n.º 3
0
        // Helper Methods

        private int getFieldSize(Signature.Type fieldType)
        {
            switch (fieldType.ElementType)
            {
            case ElementTypes.VOID:
                return(0);

            case ElementTypes.BOOLEAN:
            case ElementTypes.I1:
            case ElementTypes.U1:
                return(1);

            case ElementTypes.CHAR:
            case ElementTypes.I2:
            case ElementTypes.U2:
                return(2);

            case ElementTypes.I4:
            case ElementTypes.U4:
            case ElementTypes.R4:
                return(4);

            case ElementTypes.I8:
            case ElementTypes.U8:
            case ElementTypes.R8:
                return(8);

            case ElementTypes.OBJECT:
            case ElementTypes.STRING:
            case ElementTypes.FNPTR:
            case ElementTypes.CLASS:
            case ElementTypes.PTR:
            case ElementTypes.BYREF:
            case ElementTypes.U:
            case ElementTypes.I:
                return(machineIntSize);

            case ElementTypes.TYPEDBYREF:
                return(2 * machineIntSize);

            case ElementTypes.VALUETYPE: {
                MetaDataObject classObject = fieldType.ClassObject;
                if (!(classObject is MetaDataTypeDefinition))
                {
                    return(-1);
                }
                MetaDataTypeDefinition typedef = (MetaDataTypeDefinition)classObject;
                if ((typedef.Flags & TypeAttributes.Interface) != 0 ||
                    (typedef.Flags & TypeAttributes.Abstract) != 0)
                {
                    return(-1);
                }
                int classSize = 0;
                int packSize  = 0;
                if (typedef.ClassLayout != null)
                {
                    classSize = typedef.ClassLayout.ClassSize;
                    packSize  = typedef.ClassLayout.PackingSize;
                }
                int instanceFieldSize = 0;
                if ((typedef.Flags & TypeAttributes.ExplicitLayout) != 0)
                {
                    foreach (MetaDataField mdField in typedef.Fields)
                    {
                        if ((mdField.Flags & (int)MetaDataField.FieldAttributes.Static) == 0)
                        {
                            Signature.Type nestedFieldType =
                                ((SignatureField)mdField.Signature).FieldType;
                            int fieldSize = this.getFieldSize(nestedFieldType);
                            int offset    = mdField.Layout.Offset;
                            int fieldEnd  = fieldSize + offset;
                            if (fieldEnd > instanceFieldSize)
                            {
                                instanceFieldSize = fieldEnd;
                            }
                        }
                    }
                }
                else
                {
                    foreach (MetaDataField mdField in typedef.Fields)
                    {
                        if ((mdField.Flags & (int)MetaDataField.FieldAttributes.Static) == 0)
                        {
                            Signature.Type nestedFieldType =
                                ((SignatureField)mdField.Signature).FieldType;
                            int fieldSize = this.getFieldSize(nestedFieldType);
                            if (fieldSize == -1)
                            {
                                return(-1);
                            }
                            if (packSize > 1)
                            {
                                int delta = instanceFieldSize % packSize;
                                if (delta > 0)
                                {
                                    instanceFieldSize += packSize - delta;
                                }
                            }
                            instanceFieldSize += fieldSize;
                        }
                    }
                }
                if (instanceFieldSize > classSize)
                {
                    return(instanceFieldSize);
                }
                else if (classSize > 0)
                {
                    return(classSize);
                }
                else
                {
                    return(1);
                }
            }

            case ElementTypes.ARRAY: {
                int    elementCount = 1;
                uint[] lowerBounds  = fieldType.LowerBounds;
                uint[] upperBounds  = fieldType.UpperBounds;
                int    rank         = upperBounds.Length;
                for (int i = 0; i < rank; i++)
                {
                    int dimSize = (int)(upperBounds[i] - lowerBounds[i]);
                    if (dimSize == 0)
                    {
                        // Must be an array of pointers to other arrays
                        return(elementCount * machineIntSize);
                    }
                    else
                    {
                        elementCount *= dimSize;
                    }
                }
                int elementSize = this.getFieldSize(fieldType.TypeObject);
                return(elementCount * elementSize);
            }

            case ElementTypes.CMOD_REQD:
            case ElementTypes.CMOD_OPT:
                return(this.getFieldSize(fieldType.TypeObject));

            case ElementTypes.PINNED:
                return(this.getFieldSize(fieldType.TypeObject));

            case ElementTypes.SZARRAY:
                // Should be machine dependent!
                return(4);

            case ElementTypes.SENTINEL:
            case ElementTypes.END:
            default:
                return(-1);
            }
        }
        // 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));
            }
            }
        }
Exemplo n.º 6
0
    Type GetType(Bartok.MSIL.Signature.Type type, string path)
    {
        if (type == null)
        {
            return(global.Types.TypedReference);
        }
        switch (type.ElementType)
        {
        case ElementTypes.VOID: return(global.Types.Void);

        case ElementTypes.BOOLEAN: return(global.Types.Bool);

        case ElementTypes.CHAR: return(global.Types.Char);

        case ElementTypes.I1: return(global.Types.SByte);

        case ElementTypes.U1: return(global.Types.Byte);

        case ElementTypes.I2: return(global.Types.Short);

        case ElementTypes.U2: return(global.Types.UShort);

        case ElementTypes.I:
        case ElementTypes.I4: return(global.Types.Int);

        case ElementTypes.U:
        case ElementTypes.U4: return(global.Types.UInt);

        case ElementTypes.I8: return(global.Types.Long);

        case ElementTypes.U8: return(global.Types.ULong);

        case ElementTypes.R4: return(global.Types.Float);

        case ElementTypes.R8: return(global.Types.Double);

        case ElementTypes.OBJECT: return(global.Types.Object);

        case ElementTypes.STRING: return(global.Types.String);

        case ElementTypes.TYPEDBYREF: return(global.Types.TypedReference);

        case ElementTypes.VALUETYPE:
        case ElementTypes.CLASS:
            Type t = ResolveTypeRef(type.ClassObject, path);
            if (t == null)
            {
                Debug.Fail("unknown CLASSTYPE " + type.ClassObject.ToStringLong());
            }
            return(t);

        case ElementTypes.SZARRAY:
            return(new ArrayType(GetType(type.TypeObject, path), global.Types.Array));

        case ElementTypes.ARRAY:
            return(new ArrayType(GetType(type.TypeObject, path), type.Rank, global.Types.Array));

        case ElementTypes.FNPTR:
        case ElementTypes.CMOD_OPT:
        case ElementTypes.CMOD_REQD: return(GetType(type.TypeObject, path));

        case ElementTypes.PINNED:
        case ElementTypes.PTR:
            return(new UnmanagedPointerType(GetType(type.TypeObject, path)));

        case ElementTypes.BYREF:
            return(new ManagedPointerType(GetType(type.TypeObject, path)));

        default:
            Debug.Fail("unknown element type " + type); break;
        }
        return(global.Types.Object);
    }