Exemple #1
0
        private void ProcessType(ModuleDesc assembly)
        {
            if (ShouldProcessElement())
            {
                string typeName = _reader.GetAttribute("fullname");

                if (typeName.Contains('*'))
                {
                    throw new NotSupportedException();
                }

                TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, typeName, throwIfNotFound: false);
                if (type == null)
                {
                    //Context.LogWarning ($"Could not resolve type '{fullname}'", 2008, _xmlDocumentLocation);
                    _reader.Skip();
                    return;
                }

                _reader.Read();

                while (_reader.IsStartElement())
                {
                    if (_reader.Name == "method")
                    {
                        ProcessMethod(type);
                    }
                    else if (_reader.Name == "field")
                    {
                        ProcessField(type);
                    }
                    else if (_reader.Name == "attribute")
                    {
                        ProcessAttribute(type);
                    }

                    _reader.Skip();
                }
            }

            _reader.Skip();
        }
        /// <summary>
        /// Extract preinitialize data as byte[] from a RVA field, and perform necessary validations.
        /// </summary>
        private static PreInitFieldInfo ConstructPreInitFieldInfo(FieldDesc field, FieldDesc dataField)
        {
            if (!dataField.HasRva)
            {
                throw new BadImageFormatException();
            }

            var ecmaDataField = dataField as EcmaField;

            if (ecmaDataField == null)
            {
                throw new NotSupportedException();
            }

            var      rvaData   = ecmaDataField.GetFieldRvaData();
            var      fieldType = field.FieldType;
            int      elementCount;
            int      realDataOffset;
            TypeDesc realDataType = null;

            //
            // Construct fixups
            //
            List <PreInitFixupInfo> fixups = null;

            var typeFixupAttrs = ecmaDataField.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "TypeHandleFixupAttribute");

            foreach (var typeFixupAttr in typeFixupAttrs)
            {
                if (typeFixupAttr.FixedArguments[0].Type != field.Context.GetWellKnownType(WellKnownType.Int32))
                {
                    throw new BadImageFormatException();
                }

                int offset    = (int)typeFixupAttr.FixedArguments[0].Value;
                var typeArg   = typeFixupAttr.FixedArguments[1].Value;
                var fixupType = typeArg as TypeDesc;
                if (fixupType == null)
                {
                    if (typeArg is string fixupTypeName)
                    {
                        fixupType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(ecmaDataField.Module, fixupTypeName, throwIfNotFound: true);
                    }
                    else
                    {
                        throw new BadImageFormatException();
                    }
                }

                fixups = fixups ?? new List <PreInitFixupInfo>();

                if (offset == 0 && fieldType.IsSzArray)
                {
                    // For array field, offset 0 is the element type handle followed by the element count
                    realDataType = fixupType;
                }
                else
                {
                    fixups.Add(new PreInitTypeFixupInfo(offset, fixupType));
                }
            }

            var methodFixupAttrs = ecmaDataField.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "MethodAddrFixupAttribute");

            foreach (var methodFixupAttr in methodFixupAttrs)
            {
                if (methodFixupAttr.FixedArguments[0].Type != field.Context.GetWellKnownType(WellKnownType.Int32))
                {
                    throw new BadImageFormatException();
                }

                int      offset    = (int)methodFixupAttr.FixedArguments[0].Value;
                TypeDesc fixupType = methodFixupAttr.FixedArguments[1].Value as TypeDesc;
                if (fixupType == null)
                {
                    throw new BadImageFormatException();
                }

                string methodName = methodFixupAttr.FixedArguments[2].Value as string;
                if (methodName == null)
                {
                    throw new BadImageFormatException();
                }

                var method = fixupType.GetMethod(methodName, signature: null);
                if (method == null)
                {
                    throw new BadImageFormatException();
                }

                fixups = fixups ?? new List <PreInitFixupInfo>();

                fixups.Add(new PreInitMethodFixupInfo(offset, method));
            }

            var fieldFixupAttrs = ecmaDataField.GetDecodedCustomAttributes("System.Runtime.CompilerServices", "FieldAddrFixupAttribute");

            foreach (var fieldFixupAttr in fieldFixupAttrs)
            {
                if (fieldFixupAttr.FixedArguments[0].Type != field.Context.GetWellKnownType(WellKnownType.Int32))
                {
                    throw new BadImageFormatException();
                }

                int      offset    = (int)fieldFixupAttr.FixedArguments[0].Value;
                TypeDesc fixupType = fieldFixupAttr.FixedArguments[1].Value as TypeDesc;
                if (fixupType == null)
                {
                    throw new BadImageFormatException();
                }

                string fieldName = fieldFixupAttr.FixedArguments[2].Value as string;
                if (fieldName == null)
                {
                    throw new BadImageFormatException();
                }

                var fixupField = fixupType.GetField(fieldName);
                if (fixupField == null)
                {
                    throw new BadImageFormatException();
                }

                if (!fixupField.IsStatic)
                {
                    throw new BadImageFormatException();
                }

                fixups = fixups ?? new List <PreInitFixupInfo>();

                fixups.Add(new PreInitFieldFixupInfo(offset, fixupField));
            }

            if (fieldType.IsValueType || fieldType.IsPointer)
            {
                elementCount   = -1;
                realDataOffset = 0;
                realDataType   = fieldType;
            }
            else if (fieldType.IsSzArray)
            {
                // Offset 0 is the element type handle fixup followed by the element count
                if (realDataType == null)
                {
                    throw new BadImageFormatException();
                }

                int ptrSize = fieldType.Context.Target.PointerSize;
                elementCount   = rvaData[ptrSize] | rvaData[ptrSize + 1] << 8 | rvaData[ptrSize + 2] << 16 | rvaData[ptrSize + 3] << 24;
                realDataOffset = ptrSize * 2;
                realDataType   = realDataType.MakeArrayType();
            }
            else
            {
                throw new NotSupportedException();
            }

            return(new PreInitFieldInfo(field, realDataType, rvaData, realDataOffset, elementCount, fixups));
        }