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)); }