Esempio n. 1
0
        // TODO
        // bool _hasModifiers;

        public EcmaSignatureParser(EcmaModule module, BlobReader reader)
        {
            _module = module;
            _reader = reader;

            // _hasModifiers = false;
        }
Esempio n. 2
0
        private void ReadXmlSecurityAttribute(ref SRM.BlobReader reader, CustomAttributeTypedArgument <IType> securityAction)
        {
            string xml = reader.ReadUTF16(reader.RemainingBytes);
            var    b   = new AttributeBuilder(module, KnownAttribute.PermissionSet);

            b.AddFixedArg(securityAction);
            b.AddNamedArg("XML", KnownTypeCode.String, xml);
        }
        private unsafe static ImmutableArray<LocalSlotDebugInfo> UncompressSlotMap(ImmutableArray<byte> compressedSlotMap)
        {
            if (compressedSlotMap.IsDefaultOrEmpty)
            {
                return default(ImmutableArray<LocalSlotDebugInfo>);
            }

            var mapBuilder = ArrayBuilder<LocalSlotDebugInfo>.GetInstance();
            int syntaxOffsetBaseline = -1;

            fixed (byte* compressedSlotMapPtr = &compressedSlotMap.ToArray()[0])
            {
                var blobReader = new BlobReader(compressedSlotMapPtr, compressedSlotMap.Length);
                while (blobReader.RemainingBytes > 0)
                {
                    byte b = blobReader.ReadByte();

                    if (b == SyntaxOffsetBaseline)
                    {
                        syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();
                        continue;
                    }

                    if (b == 0)
                    {
                        // short-lived temp, no info
                        mapBuilder.Add(new LocalSlotDebugInfo(SynthesizedLocalKind.LoweringTemp, default(LocalDebugId)));
                        continue;
                    }

                    var kind = (SynthesizedLocalKind)((b & 0x3f) - 1);
                    bool hasOrdinal = (b & (1 << 7)) != 0;

                    int syntaxOffset;
                    if (!blobReader.TryReadCompressedInteger(out syntaxOffset))
                    {
                        // invalid data
                        return default(ImmutableArray<LocalSlotDebugInfo>);
                    }

                    syntaxOffset += syntaxOffsetBaseline;

                    int ordinal = 0;
                    if (hasOrdinal && !blobReader.TryReadCompressedInteger(out ordinal))
                    {
                        // invalid data
                        return default(ImmutableArray<LocalSlotDebugInfo>);
                    }

                    mapBuilder.Add(new LocalSlotDebugInfo(kind, new LocalDebugId(syntaxOffset, ordinal)));
                }
            }

            return mapBuilder.ToImmutableAndFree();
        }
        /// <exception cref="InvalidDataException">Invalid data.</exception>
        private unsafe static ImmutableArray<LocalSlotDebugInfo> UncompressSlotMap(ImmutableArray<byte> compressedSlotMap)
        {
            if (compressedSlotMap.IsDefaultOrEmpty)
            {
                return default(ImmutableArray<LocalSlotDebugInfo>);
            }

            var mapBuilder = ArrayBuilder<LocalSlotDebugInfo>.GetInstance();
            int syntaxOffsetBaseline = -1;

            fixed (byte* compressedSlotMapPtr = &compressedSlotMap.ToArray()[0])
            {
                var blobReader = new BlobReader(compressedSlotMapPtr, compressedSlotMap.Length);
                while (blobReader.RemainingBytes > 0)
                {
                    try
                    {
                        // Note: integer operations below can't overflow since compressed integers are in range [0, 0x20000000)

                        byte b = blobReader.ReadByte();

                        if (b == SyntaxOffsetBaseline)
                        {
                            syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();
                            continue;
                        }

                        if (b == 0)
                        {
                            // short-lived temp, no info
                            mapBuilder.Add(new LocalSlotDebugInfo(SynthesizedLocalKind.LoweringTemp, default(LocalDebugId)));
                            continue;
                        }

                        var kind = (SynthesizedLocalKind)((b & 0x3f) - 1);
                        bool hasOrdinal = (b & (1 << 7)) != 0;

                        int syntaxOffset = blobReader.ReadCompressedInteger() + syntaxOffsetBaseline;

                        int ordinal = hasOrdinal ? blobReader.ReadCompressedInteger() : 0;

                        mapBuilder.Add(new LocalSlotDebugInfo(kind, new LocalDebugId(syntaxOffset, ordinal)));
                    }
                    catch (BadImageFormatException)
                    {
                        throw CreateInvalidDataException(compressedSlotMap, blobReader.Offset);
                    }
                }
            }

            return mapBuilder.ToImmutableAndFree();
        }
Esempio n. 5
0
 // cf. MetadataDecoder<>.DecodeTypeOrThrow.
 private TypeSignature DecodeType(ref BlobReader signatureReader, SignatureTypeCode typeCode)
 {
     switch (typeCode)
     {
         case SignatureTypeCode.TypeHandle:
             {
                 int typeArgumentOffset = 0;
                 return DecodeType(signatureReader.ReadTypeHandle(), ImmutableArray<TypeSignature>.Empty, ref typeArgumentOffset);
             }
         case SignatureTypeCode.Array:
             {
                 var elementType = DecodeModifiersAndType(ref signatureReader);
                 int rank;
                 int sizes;
                 signatureReader.TryReadCompressedInteger(out rank);
                 signatureReader.TryReadCompressedInteger(out sizes);
                 if (sizes != 0)
                 {
                     throw UnhandledMetadata();
                 }
                 return new ArrayTypeSignature(elementType, rank);
             }
         case SignatureTypeCode.SZArray:
             {
                 var elementType = DecodeModifiersAndType(ref signatureReader);
                 return new ArrayTypeSignature(elementType, 1);
             }
         case SignatureTypeCode.GenericTypeInstance:
             return DecodeGenericTypeInstance(ref signatureReader);
         case SignatureTypeCode.Pointer:
             {
                 var pointedAtType = DecodeModifiersAndType(ref signatureReader);
                 return new PointerTypeSignature(pointedAtType);
             }
         case SignatureTypeCode.GenericTypeParameter:
             return DecodeGenericTypeParameter(ref signatureReader, _allTypeParameters, _containingArity);
         case SignatureTypeCode.GenericMethodParameter:
             return DecodeGenericTypeParameter(ref signatureReader, _methodTypeParameters, 0);
         default:
             {
                 var signature = typeCode.ToSpecialType().GetTypeSignature();
                 if (signature == null)
                 {
                     throw UnhandledMetadata();
                 }
                 return signature;
             }
     }
 }
Esempio n. 6
0
        private IAttribute ReadBinarySecurityAttribute(ref SRM.BlobReader reader, CustomAttributeTypedArgument <IType> securityAction)
        {
            string attributeTypeName = reader.ReadSerializedString();
            IType  attributeType     = module.TypeProvider.GetTypeFromSerializedName(attributeTypeName);

            reader.ReadCompressedInteger();             // ??
            // The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
            int numNamed = reader.ReadCompressedInteger();

            var decoder   = new Metadata.CustomAttributeDecoder <IType>(module.TypeProvider, module.metadata);
            var namedArgs = decoder.DecodeNamedArguments(ref reader, numNamed);

            return(new DefaultAttribute(
                       attributeType,
                       fixedArguments: ImmutableArray.Create(securityAction),
                       namedArguments: namedArgs));
        }
Esempio n. 7
0
        public static ILResult GetInstructions(BlobReader reader)
        {
            var instructions = ImmutableArray.CreateBuilder<Instruction>();
            List<int[]> switches = null;

            while (reader.RemainingBytes > 0)
            {
                ushort pos = (ushort)reader.Offset;
                byte op0 = reader.ReadByte();
                InstrCode code = (InstrCode)(op0 == 0xFE ? unchecked(0xFE00 + reader.ReadByte()) : op0);
                OperandType opType = code.GetOperandType();

                ulong operand = 0;
                if (code == InstrCode.Switch)
                {
                    if (switches == null)
                        switches = new List<int[]>();

                    operand = (ulong)switches.Count;
                    uint branchCount = reader.ReadUInt32();
                    int[] branches = new int[branchCount];
                    for (int i = 0; i < branchCount; i++)
                    {
                        branches[i] = reader.ReadInt32();
                    }
                    switches.Add(branches);
                }
                else
                {
                    byte operandSize = opType.GetOperandSize();
                    operand = operandSize == 8 ? reader.ReadUInt64()
                        : operandSize == 4 ? reader.ReadUInt32()
                        : operandSize == 2 ? reader.ReadUInt16()
                        : operandSize == 1 ? (ulong)reader.ReadByte()
                        : 0;
                }

                instructions.Add(new Instruction(pos, code, opType, operand));
            }

            return new ILResult
            {
                Instructions = instructions.ToImmutable(),
                Switches = switches?.ToArray()
            };
        }
        /// <summary>
        /// Returns a body block of a method with specified Relative Virtual Address (RVA);
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="peReader"/> is null.</exception>
        /// <exception cref="BadImageFormatException">The body is not found in the metadata or is invalid.</exception>
        /// <exception cref="InvalidOperationException">Section where the method is stored is not available.</exception>
        public static unsafe MethodBodyBlock GetMethodBody(this PEReader peReader, int relativeVirtualAddress)
        {
            if (peReader == null)
            {
                throw new ArgumentNullException(nameof(peReader));
            }

            var block = peReader.GetSectionData(relativeVirtualAddress);
            if (block.Length == 0)
            {
                throw new BadImageFormatException(SR.Format(SR.InvalidMethodRva, relativeVirtualAddress));
            }

            // Call to validating public BlobReader constructor is by design -- we need to throw PlatformNotSupported on big-endian architecture.
            var blobReader = new BlobReader(block.Pointer, block.Length);
            return MethodBodyBlock.Create(blobReader);
        }
Esempio n. 9
0
        public static unsafe string GetMethodIL(this ImmutableArray<byte> ilArray)
        {
            var result = new StringBuilder();
            fixed (byte* ilPtr = ilArray.ToArray())
            {
                int offset = 0;
                while (true)
                {
                    // skip padding:
                    while (offset < ilArray.Length && ilArray[offset] == 0)
                    {
                        offset++;
                    }

                    if (offset == ilArray.Length)
                    {
                        break;
                    }

                    var reader = new BlobReader(ilPtr + offset, ilArray.Length - offset);
                    var methodIL = MethodBodyBlock.Create(reader);

                    if (methodIL == null)
                    {
                        result.AppendFormat("<invalid byte 0x{0:X2} at offset {1}>", ilArray[offset], offset);
                        offset++;
                    }
                    else
                    {
                        ILVisualizerAsTokens.Instance.DumpMethod(
                            result,
                            methodIL.MaxStack,
                            methodIL.GetILContent(),
                            ImmutableArray.Create<ILVisualizer.LocalInfo>(),
                            ImmutableArray.Create<ILVisualizer.HandlerSpan>());

                        offset += methodIL.Size;
                    }
                }
            }

            return result.ToString();
        }
Esempio n. 10
0
        public unsafe BlobReader(byte* buffer, int length)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            if (buffer == null && length != 0)
            {
                throw new ArgumentNullException("buffer");
            }

            // the reader performs little-endian specific operations
            if (!BitConverter.IsLittleEndian)
            {
                throw new PlatformNotSupportedException(MetadataResources.LitteEndianArchitectureRequired);
            }

            this = new BlobReader(new MemoryBlock(buffer, length));
        }
Esempio n. 11
0
        private static int IndexOfCharacter(BlobReader blobReader, char ch)
        {
            // This function is only safe for searching for ascii characters.
            Debug.Assert(ch < 127);
            unsafe
            {
                var ptr = blobReader.CurrentPointer;
                for (int i = 0, n = blobReader.RemainingBytes; i < n; i++)
                {
                    if (*ptr == ch)
                    {
                        return i;
                    }

                    ptr++;
                }

                return -1;
            }
        }
Esempio n. 12
0
 // cf. MetadataDecoder<>.DecodeParameterOrThrow.
 private ParameterSignature DecodeParameter(ref BlobReader signatureReader)
 {
     bool isByRef = false;
     while (true)
     {
         var typeCode = signatureReader.ReadSignatureTypeCode();
         switch (typeCode)
         {
             case SignatureTypeCode.RequiredModifier:
             case SignatureTypeCode.OptionalModifier:
                 // Skip modifiers.
                 break;
             case SignatureTypeCode.ByReference:
                 isByRef = true;
                 break;
             default:
                 var type = DecodeType(ref signatureReader, typeCode);
                 return new ParameterSignature(type, isByRef);
         }
     }
 }
Esempio n. 13
0
        /// <summary>
        /// Creates a metadata reader from the metadata stored at the given memory location.
        /// </summary>
        /// <remarks>
        /// The memory is owned by the caller and it must be kept memory alive and unmodified throughout the lifetime of the <see cref="MetadataReader"/>.
        /// Use <see cref="PEReaderExtensions.GetMetadataReader(PortableExecutable.PEReader, MetadataReaderOptions, MetadataStringDecoder)"/> to obtain 
        /// metadata from a PE image.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is not positive.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="metadata"/> is null.</exception>
        /// <exception cref="ArgumentException">The encoding of <paramref name="utf8Decoder"/> is not <see cref="UTF8Encoding"/>.</exception>
        /// <exception cref="PlatformNotSupportedException">The current platform is big-endian.</exception>
        public unsafe MetadataReader(byte* metadata, int length, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
        {
            // Do not throw here when length is 0. We'll throw BadImageFormatException later on, so that the caller doesn't need to 
            // worry about the image (stream) being empty and can handle all image errors by catching BadImageFormatException.
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            if (utf8Decoder == null)
            {
                utf8Decoder = MetadataStringDecoder.DefaultUTF8;
            }

            if (!(utf8Decoder.Encoding is UTF8Encoding))
            {
                throw new ArgumentException(SR.MetadataStringDecoderEncodingMustBeUtf8, nameof(utf8Decoder));
            }

            if (!BitConverter.IsLittleEndian)
            {
                Throw.LitteEndianArchitectureRequired();
            }

            this.Block = new MemoryBlock(metadata, length);

            _options = options;
            this.UTF8Decoder = utf8Decoder;

            var headerReader = new BlobReader(this.Block);
            this.ReadMetadataHeader(ref headerReader, out _versionString);
            _metadataKind = GetMetadataKind(_versionString);
            var streamHeaders = this.ReadStreamHeaders(ref headerReader);

            // storage header and stream headers:
            MemoryBlock metadataTableStream;
            MemoryBlock standalonePdbStream;
            this.InitializeStreamReaders(ref this.Block, streamHeaders, out _metadataStreamKind, out metadataTableStream, out standalonePdbStream);

            int[] externalTableRowCountsOpt;
            if (standalonePdbStream.Length > 0)
            {
                ReadStandalonePortablePdbStream(standalonePdbStream, out _debugMetadataHeader, out externalTableRowCountsOpt);
            }
            else
            {
                externalTableRowCountsOpt = null;
            }

            var tableReader = new BlobReader(metadataTableStream);

            HeapSizes heapSizes;
            int[] metadataTableRowCounts;
            this.ReadMetadataTableHeader(ref tableReader, out heapSizes, out metadataTableRowCounts, out _sortedTables);

            this.InitializeTableReaders(tableReader.GetMemoryBlockAt(0, tableReader.RemainingBytes), heapSizes, metadataTableRowCounts, externalTableRowCountsOpt);

            // This previously could occur in obfuscated assemblies but a check was added to prevent 
            // it getting to this point
            Debug.Assert(this.AssemblyTable.NumberOfRows <= 1);

            // Although the specification states that the module table will have exactly one row,
            // the native metadata reader would successfully read files containing more than one row.
            // Such files exist in the wild and may be produced by obfuscators.
            if (standalonePdbStream.Length == 0 && this.ModuleTable.NumberOfRows < 1)
            {
                throw new BadImageFormatException(SR.Format(SR.ModuleTableInvalidNumberOfRows, this.ModuleTable.NumberOfRows));
            }

            //  read 
            this.NamespaceCache = new NamespaceCache(this);

            if (_metadataKind != MetadataKind.Ecma335)
            {
                this.WinMDMscorlibRef = FindMscorlibAssemblyRefNoProjection();
            }
        }
Esempio n. 14
0
        /// <summary>
        /// Reads all Debug Directory table entries.
        /// </summary>
        /// <exception cref="BadImageFormatException">Bad format of the entry.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        public unsafe ImmutableArray<DebugDirectoryEntry> ReadDebugDirectory()
        {
            var debugDirectory = PEHeaders.PEHeader.DebugTableDirectory;
            if (debugDirectory.Size == 0)
            {
                return ImmutableArray<DebugDirectoryEntry>.Empty;
            }

            int position;
            if (!PEHeaders.TryGetDirectoryOffset(debugDirectory, out position))
            {
                throw new BadImageFormatException(SR.InvalidDirectoryRVA);
            }

            if (debugDirectory.Size % DebugDirectoryEntry.Size != 0)
            {
                throw new BadImageFormatException(SR.InvalidDirectorySize);
            }

            using (AbstractMemoryBlock block = _peImage.GetMemoryBlock(position, debugDirectory.Size))
            {
                var reader = new BlobReader(block.Pointer, block.Size);
                return ReadDebugDirectoryEntries(reader);
            }
        }
Esempio n. 15
0
        private static int[] ReadMetadataTableRowCounts(ref BlobReader memReader, ulong presentTableMask)
        {
            ulong currentTableBit = 1;

            var rowCounts = new int[MetadataTokens.TableCount];
            for (int i = 0; i < rowCounts.Length; i++)
            {
                if ((presentTableMask & currentTableBit) != 0)
                {
                    if (memReader.RemainingBytes < sizeof(uint))
                    {
                        throw new BadImageFormatException(SR.TableRowCountSpaceTooSmall);
                    }

                    uint rowCount = memReader.ReadUInt32();
                    if (rowCount > TokenTypeIds.RIDMask)
                    {
                        throw new BadImageFormatException(SR.Format(SR.InvalidRowCount, rowCount));
                    }

                    rowCounts[i] = (int)rowCount;
                }

                currentTableBit <<= 1;
            }

            return rowCounts;
        }
Esempio n. 16
0
        // internal for testing
        internal static void ReadStandalonePortablePdbStream(MemoryBlock block, out DebugMetadataHeader debugMetadataHeader, out int[] externalTableRowCounts)
        {
            var reader = new BlobReader(block);

            const int PdbIdSize = 20;
            byte[] pdbId = reader.ReadBytes(PdbIdSize);

            // ECMA-335 15.4.1.2:
            // The entry point to an application shall be static.
            // This entry point method can be a global method or it can appear inside a type. 
            // The entry point method shall either accept no arguments or a vector of strings.
            // The return type of the entry point method shall be void, int32, or unsigned int32. 
            // The entry point method cannot be defined in a generic class.
            uint entryPointToken = reader.ReadUInt32();
            int entryPointRowId = (int)(entryPointToken & TokenTypeIds.RIDMask);
            if (entryPointToken != 0 && ((entryPointToken & TokenTypeIds.TypeMask) != TokenTypeIds.MethodDef || entryPointRowId == 0))
            {
                throw new BadImageFormatException(string.Format(SR.InvalidEntryPointToken, entryPointToken));
            }

            ulong externalTableMask = reader.ReadUInt64();

            // EnC & Ptr tables can't be referenced from standalone PDB metadata:
            const ulong validTables = (ulong)TableMask.ValidPortablePdbExternalTables;

            if ((externalTableMask & ~validTables) != 0)
            {
                throw new BadImageFormatException(string.Format(SR.UnknownTables, (TableMask)externalTableMask));
            }

            externalTableRowCounts = ReadMetadataTableRowCounts(ref reader, externalTableMask);

            debugMetadataHeader = new DebugMetadataHeader(
                ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref pdbId),
                MethodDefinitionHandle.FromRowId(entryPointRowId));
        }
Esempio n. 17
0
        IAttribute ConvertMarshalInfo(SRM.BlobReader marshalInfo)
        {
            var   b = new AttributeBuilder(module, KnownAttribute.MarshalAs);
            IType unmanagedTypeType = module.Compilation.FindType(new TopLevelTypeName(InteropServices, nameof(UnmanagedType)));

            int type = marshalInfo.ReadByte();

            b.AddFixedArg(unmanagedTypeType, type);

            int size;

            switch (type)
            {
            case 0x1e:                     // FixedArray
                if (!marshalInfo.TryReadCompressedInteger(out size))
                {
                    size = 0;
                }
                b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size);
                if (marshalInfo.RemainingBytes > 0)
                {
                    type = marshalInfo.ReadByte();
                    if (type != 0x66)                             // None
                    {
                        b.AddNamedArg("ArraySubType", unmanagedTypeType, type);
                    }
                }
                break;

            case 0x1d:                     // SafeArray
                if (marshalInfo.RemainingBytes > 0)
                {
                    VarEnum varType = (VarEnum)marshalInfo.ReadByte();
                    if (varType != VarEnum.VT_EMPTY)
                    {
                        var varEnumType = new TopLevelTypeName(InteropServices, nameof(VarEnum));
                        b.AddNamedArg("SafeArraySubType", varEnumType, (int)varType);
                    }
                }
                break;

            case 0x2a:                     // NATIVE_TYPE_ARRAY
                if (marshalInfo.RemainingBytes > 0)
                {
                    type = marshalInfo.ReadByte();
                }
                else
                {
                    type = 0x66;                            // Cecil uses NativeType.None as default.
                }
                if (type != 0x50)                           // Max
                {
                    b.AddNamedArg("ArraySubType", unmanagedTypeType, type);
                }
                int sizeParameterIndex = marshalInfo.TryReadCompressedInteger(out int value) ? value : -1;
                size = marshalInfo.TryReadCompressedInteger(out value) ? value : -1;
                int sizeParameterMultiplier = marshalInfo.TryReadCompressedInteger(out value) ? value : -1;
                if (size >= 0)
                {
                    b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size);
                }
                if (sizeParameterMultiplier != 0 && sizeParameterIndex >= 0)
                {
                    b.AddNamedArg("SizeParamIndex", KnownTypeCode.Int16, (short)sizeParameterIndex);
                }
                break;

            case 0x2c:                     // CustomMarshaler
                string guidValue     = marshalInfo.ReadSerializedString();
                string unmanagedType = marshalInfo.ReadSerializedString();
                string managedType   = marshalInfo.ReadSerializedString();
                string cookie        = marshalInfo.ReadSerializedString();
                if (managedType != null)
                {
                    b.AddNamedArg("MarshalType", KnownTypeCode.String, managedType);
                }
                if (!string.IsNullOrEmpty(cookie))
                {
                    b.AddNamedArg("MarshalCookie", KnownTypeCode.String, cookie);
                }
                break;

            case 0x17:                     // FixedSysString
                b.AddNamedArg("SizeConst", KnownTypeCode.Int32, marshalInfo.ReadCompressedInteger());
                break;
            }

            return(b.Build());
        }
Esempio n. 18
0
        private MetadataRecord HandleConstant(Cts.Ecma.EcmaModule module, Ecma.ConstantHandle constantHandle)
        {
            Ecma.MetadataReader reader   = module.MetadataReader;
            Ecma.Constant       constant = reader.GetConstant(constantHandle);

            Ecma.BlobReader blob = reader.GetBlobReader(constant.Value);

            switch (constant.TypeCode)
            {
            case ConstantTypeCode.Boolean:
                return(new ConstantBooleanValue {
                    Value = blob.ReadBoolean()
                });

            case ConstantTypeCode.Byte:
                return(new ConstantByteValue {
                    Value = blob.ReadByte()
                });

            case ConstantTypeCode.Char:
                return(new ConstantCharValue {
                    Value = blob.ReadChar()
                });

            case ConstantTypeCode.Double:
                return(new ConstantDoubleValue {
                    Value = blob.ReadDouble()
                });

            case ConstantTypeCode.Int16:
                return(new ConstantInt16Value {
                    Value = blob.ReadInt16()
                });

            case ConstantTypeCode.Int32:
                return(new ConstantInt32Value {
                    Value = blob.ReadInt32()
                });

            case ConstantTypeCode.Int64:
                return(new ConstantInt64Value {
                    Value = blob.ReadInt64()
                });

            case ConstantTypeCode.SByte:
                return(new ConstantSByteValue {
                    Value = blob.ReadSByte()
                });

            case ConstantTypeCode.Single:
                return(new ConstantSingleValue {
                    Value = blob.ReadSingle()
                });

            case ConstantTypeCode.String:
                return(HandleString(blob.ReadUTF16(blob.Length)));

            case ConstantTypeCode.UInt16:
                return(new ConstantUInt16Value {
                    Value = blob.ReadUInt16()
                });

            case ConstantTypeCode.UInt32:
                return(new ConstantUInt32Value {
                    Value = blob.ReadUInt32()
                });

            case ConstantTypeCode.UInt64:
                return(new ConstantUInt64Value {
                    Value = blob.ReadUInt64()
                });

            case ConstantTypeCode.NullReference:
                return(new ConstantReferenceValue());

            default:
                throw new BadImageFormatException();
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Looks like this function reads beginning of the header described in
        /// Ecma-335 24.2.1 Metadata root
        /// </summary>
        private void ReadMetadataHeader(ref BlobReader memReader)
        {
            if (memReader.RemainingBytes < COR20Constants.MinimumSizeofMetadataHeader)
            {
                throw new BadImageFormatException(MetadataResources.MetadataHeaderTooSmall);
            }

            this.metadataHeader.Signature = memReader.ReadUInt32();
            if (this.metadataHeader.Signature != COR20Constants.COR20MetadataSignature)
            {
                throw new BadImageFormatException(MetadataResources.MetadataSignature);
            }

            this.metadataHeader.MajorVersion = memReader.ReadUInt16();
            this.metadataHeader.MinorVersion = memReader.ReadUInt16();
            this.metadataHeader.ExtraData = memReader.ReadUInt32();
            this.metadataHeader.VersionStringSize = memReader.ReadInt32();
            if (memReader.RemainingBytes < this.metadataHeader.VersionStringSize)
            {
                throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForVersionString);
            }

            int numberOfBytesRead;
            this.metadataHeader.VersionString = memReader.GetMemoryBlockAt(0, this.metadataHeader.VersionStringSize).PeekUtf8NullTerminated(0, null, utf8Decoder, out numberOfBytesRead, '\0');
            memReader.SkipBytes(this.metadataHeader.VersionStringSize);
            this.metadataKind = GetMetadataKind(metadataHeader.VersionString);
        }
Esempio n. 20
0
        /// <summary>
        /// Reads stream headers described in Ecma-335 24.2.2 Stream header
        /// </summary>
        private StreamHeader[] ReadStreamHeaders(ref BlobReader memReader)
        {
            // storage header:
            memReader.ReadUInt16();
            int streamCount = memReader.ReadInt16();

            var streamHeaders = new StreamHeader[streamCount];
            for (int i = 0; i < streamHeaders.Length; i++)
            {
                if (memReader.RemainingBytes < COR20Constants.MinimumSizeofStreamHeader)
                {
                    throw new BadImageFormatException(MetadataResources.StreamHeaderTooSmall);
                }

                streamHeaders[i].Offset = memReader.ReadUInt32();
                streamHeaders[i].Size = memReader.ReadInt32();
                streamHeaders[i].Name = memReader.ReadUtf8NullTerminated();
                bool aligned = memReader.TryAlign(4);

                if (!aligned || memReader.RemainingBytes == 0)
                {
                    throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForStreamHeaderName);
                }
            }

            return streamHeaders;
        }
Esempio n. 21
0
        internal static ImmutableArray<DebugDirectoryEntry> ReadDebugDirectoryEntries(BlobReader reader)
        {
            int entryCount = reader.Length / DebugDirectoryEntry.Size;
            var builder = ImmutableArray.CreateBuilder<DebugDirectoryEntry>(entryCount);
            for (int i = 0; i < entryCount; i++)
            {
                // Reserved, must be zero.
                int characteristics = reader.ReadInt32();
                if (characteristics != 0)
                {
                    throw new BadImageFormatException(SR.InvalidDebugDirectoryEntryCharacteristics);
                }

                uint stamp = reader.ReadUInt32();
                ushort majorVersion = reader.ReadUInt16();
                ushort minorVersion = reader.ReadUInt16();

                var type = (DebugDirectoryEntryType)reader.ReadInt32();

                int dataSize = reader.ReadInt32();
                int dataRva = reader.ReadInt32();
                int dataPointer = reader.ReadInt32();

                builder.Add(new DebugDirectoryEntry(stamp, majorVersion, minorVersion, type, dataSize, dataRva, dataPointer));
            }

            return builder.MoveToImmutable();
        }
Esempio n. 22
0
        private static ImmutableArray<ExceptionRegion> ReadFatExceptionHandlers(ref BlobReader memReader, int count)
        {
            var result = new ExceptionRegion[count];
            for (int i = 0; i < result.Length; i++)
            {
                var sehFlags = (ExceptionRegionKind)memReader.ReadUInt32();
                int tryOffset = memReader.ReadInt32();
                int tryLength = memReader.ReadInt32();
                int handlerOffset = memReader.ReadInt32();
                int handlerLength = memReader.ReadInt32();
                int classTokenOrFilterOffset = memReader.ReadInt32();
                result[i] = new ExceptionRegion(sehFlags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset);
            }

            return ImmutableArray.Create(result);
        }
Esempio n. 23
0
        /// <summary>
        /// Reads all Debug Directory table entries.
        /// </summary>
        /// <exception cref="BadImageFormatException">Bad format of the entry.</exception>
        public unsafe ImmutableArray<DebugDirectoryEntry> ReadDebugDirectory()
        {
            var debugDirectory = PEHeaders.PEHeader.DebugTableDirectory;
            if (debugDirectory.Size == 0)
            {
                return ImmutableArray<DebugDirectoryEntry>.Empty;
            }

            int position;
            if (!PEHeaders.TryGetDirectoryOffset(debugDirectory, out position))
            {
                throw new BadImageFormatException(SR.InvalidDirectoryRVA);
            }

            const int entrySize = 0x1c;

            if (debugDirectory.Size % entrySize != 0)
            {
                throw new BadImageFormatException(SR.InvalidDirectorySize);
            }

            using (AbstractMemoryBlock block = _peImage.GetMemoryBlock(position, debugDirectory.Size))
            {
                var reader = new BlobReader(block.Pointer, block.Size);

                int entryCount = debugDirectory.Size / entrySize;
                var builder = ImmutableArray.CreateBuilder<DebugDirectoryEntry>(entryCount);
                for (int i = 0; i < entryCount; i++)
                {
                    // Reserved, must be zero.
                    int characteristics = reader.ReadInt32();
                    if (characteristics != 0)
                    {
                        throw new BadImageFormatException(SR.InvalidDebugDirectoryEntryCharacteristics);
                    }

                    uint stamp = reader.ReadUInt32();
                    ushort majorVersion = reader.ReadUInt16();
                    ushort minorVersion = reader.ReadUInt16();

                    var type = (DebugDirectoryEntryType)reader.ReadInt32();

                    int dataSize = reader.ReadInt32();
                    int dataRva = reader.ReadInt32();
                    int dataPointer = reader.ReadInt32();

                    builder.Add(new DebugDirectoryEntry(stamp, majorVersion, minorVersion, type, dataSize, dataRva, dataPointer));
                }

                return builder.MoveToImmutable();
            }
        }
 public FieldSignature(BlobReader blobReader)
 {
     _reader = blobReader;
 }
 public TypeSpecificationSignature(BlobReader blobReader)
 {
     _reader = blobReader;
 }
Esempio n. 26
0
        public static MethodBodyBlock Create(BlobReader reader)
        {
            int startOffset = reader.Offset;
            int ilSize;

            // Error need to check if the Memory Block is empty. This is calse for all the calls...
            byte headByte = reader.ReadByte();
            if ((headByte & ILFormatMask) == ILTinyFormat)
            {
                // tiny IL can't have locals so technically this shouldn't matter,
                // but false is consistent with other metadata readers and helps
                // for use cases involving comparing our output with theirs.
                const bool initLocalsForTinyIL = false;

                ilSize = headByte >> ILTinyFormatSizeShift;
                return new MethodBodyBlock(
                    initLocalsForTinyIL,
                    8,
                    default(StandaloneSignatureHandle),
                    reader.GetMemoryBlockAt(0, ilSize),
                    ImmutableArray<ExceptionRegion>.Empty,
                    1 + ilSize // header + IL
                );
            }

            if ((headByte & ILFormatMask) != ILFatFormat)
            {
                throw new BadImageFormatException(string.Format(MetadataResources.InvalidMethodHeader1, headByte));
            }

            // FatILFormat
            byte headByte2 = reader.ReadByte();
            if ((headByte2 >> ILFatFormatHeaderSizeShift) != ILFatFormatHeaderSize)
            {
                throw new BadImageFormatException(string.Format(MetadataResources.InvalidMethodHeader2, headByte, headByte2));
            }

            bool localsInitialized = (headByte & ILInitLocals) == ILInitLocals;
            bool hasExceptionHandlers = (headByte & ILMoreSects) == ILMoreSects;

            ushort maxStack = reader.ReadUInt16();
            ilSize = reader.ReadInt32();

            int localSignatureToken = reader.ReadInt32();
            StandaloneSignatureHandle localSignatureHandle;
            if (localSignatureToken == 0)
            {
                localSignatureHandle = default(StandaloneSignatureHandle);
            }
            else if ((localSignatureToken & TokenTypeIds.TokenTypeMask) == TokenTypeIds.Signature)
            {
                localSignatureHandle = StandaloneSignatureHandle.FromRowId((uint)localSignatureToken & TokenTypeIds.RIDMask);
            }
            else
            {
                throw new BadImageFormatException(string.Format(MetadataResources.InvalidLocalSignatureToken, unchecked((uint)localSignatureToken)));
            }

            var ilBlock = reader.GetMemoryBlockAt(0, ilSize);
            reader.SkipBytes(ilSize);

            ImmutableArray<ExceptionRegion> exceptionHandlers;
            if (hasExceptionHandlers)
            {
                reader.Align(4);
                byte sehHeader = reader.ReadByte();
                if ((sehHeader & SectEHTable) != SectEHTable)
                {
                    throw new BadImageFormatException(string.Format(MetadataResources.InvalidSehHeader, sehHeader));
                }

                bool sehFatFormat = (sehHeader & SectFatFormat) == SectFatFormat;
                int dataSize = reader.ReadByte();
                if (sehFatFormat)
                {
                    dataSize += reader.ReadUInt16() << 8;
                    exceptionHandlers = ReadFatExceptionHandlers(ref reader, dataSize / 24);
                }
                else
                {
                    reader.SkipBytes(2); // skip over reserved field
                    exceptionHandlers = ReadSmallExceptionHandlers(ref reader, dataSize / 12);
                }
            }
            else
            {
                exceptionHandlers = ImmutableArray<ExceptionRegion>.Empty;
            }

            return new MethodBodyBlock(
                localsInitialized,
                maxStack,
                localSignatureHandle,
                ilBlock,
                exceptionHandlers,
                reader.Offset - startOffset);
        }
Esempio n. 27
0
        private static ImmutableArray<ExceptionRegion> ReadSmallExceptionHandlers(ref BlobReader memReader, int count)
        {
            var result = new ExceptionRegion[count];
            for (int i = 0; i < result.Length; i++)
            {
                var kind = (ExceptionRegionKind)memReader.ReadUInt16();
                var tryOffset = memReader.ReadUInt16();
                var tryLength = memReader.ReadByte();
                var handlerOffset = memReader.ReadUInt16();
                var handlerLength = memReader.ReadByte();
                var classTokenOrFilterOffset = memReader.ReadInt32();
                result[i] = new ExceptionRegion(kind, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset);
            }

            return ImmutableArray.Create(result);
        }
Esempio n. 28
0
        /// <summary>
        /// Reads the data pointed to by the specified Debug Directory entry and interprets them as CodeView.
        /// </summary>
        /// <exception cref="ArgumentException"><paramref name="entry"/> is not a CodeView entry.</exception>
        /// <exception cref="BadImageFormatException">Bad format of the data.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        public unsafe CodeViewDebugDirectoryData ReadCodeViewDebugDirectoryData(DebugDirectoryEntry entry)
        {
            if (entry.Type != DebugDirectoryEntryType.CodeView)
            {
                throw new ArgumentException(SR.NotCodeViewEntry, nameof(entry));
            }

            using (AbstractMemoryBlock block = _peImage.GetMemoryBlock(entry.DataPointer, entry.DataSize))
            {
                var reader = new BlobReader(block.Pointer, block.Size);

                if (reader.ReadByte() != (byte)'R' ||
                    reader.ReadByte() != (byte)'S' ||
                    reader.ReadByte() != (byte)'D' ||
                    reader.ReadByte() != (byte)'S')
                {
                    throw new BadImageFormatException(SR.UnexpectedCodeViewDataSignature);
                }

                Guid guid = reader.ReadGuid();
                int age = reader.ReadInt32();
                string path = reader.ReadUtf8NullTerminated();

                // path may be padded with NULs
                while (reader.RemainingBytes > 0)
                {
                    if (reader.ReadByte() != 0)
                    {
                        throw new BadImageFormatException(SR.InvalidPathPadding);
                    }
                }

                return new CodeViewDebugDirectoryData(guid, age, path);
            }
        }
        public static MethodBodyBlock Create(BlobReader reader)
        {
            int startOffset = reader.Offset;
            int ilSize;

            // Error need to check if the Memory Block is empty. This is false for all the calls...
            byte headByte = reader.ReadByte();

            if ((headByte & ILFormatMask) == ILTinyFormat)
            {
                // tiny IL can't have locals so technically this shouldn't matter,
                // but false is consistent with other metadata readers and helps
                // for use cases involving comparing our output with theirs.
                const bool initLocalsForTinyIL = false;

                ilSize = headByte >> ILTinyFormatSizeShift;
                return(new MethodBodyBlock(
                           initLocalsForTinyIL,
                           8,
                           default(StandaloneSignatureHandle),
                           reader.GetMemoryBlockAt(0, ilSize),
                           ImmutableArray <ExceptionRegion> .Empty,
                           1 + ilSize // header + IL
                           ));
            }

            if ((headByte & ILFormatMask) != ILFatFormat)
            {
                throw new BadImageFormatException(SR.Format(SR.InvalidMethodHeader1, headByte));
            }

            // FatILFormat
            byte headByte2 = reader.ReadByte();

            if ((headByte2 >> ILFatFormatHeaderSizeShift) != ILFatFormatHeaderSize)
            {
                throw new BadImageFormatException(SR.Format(SR.InvalidMethodHeader2, headByte, headByte2));
            }

            bool localsInitialized    = (headByte & ILInitLocals) == ILInitLocals;
            bool hasExceptionHandlers = (headByte & ILMoreSects) == ILMoreSects;

            ushort maxStack = reader.ReadUInt16();

            ilSize = reader.ReadInt32();

            int localSignatureToken = reader.ReadInt32();
            StandaloneSignatureHandle localSignatureHandle;

            if (localSignatureToken == 0)
            {
                localSignatureHandle = default(StandaloneSignatureHandle);
            }
            else if ((localSignatureToken & TokenTypeIds.TypeMask) == TokenTypeIds.Signature)
            {
                localSignatureHandle = StandaloneSignatureHandle.FromRowId((int)((uint)localSignatureToken & TokenTypeIds.RIDMask));
            }
            else
            {
                throw new BadImageFormatException(SR.Format(SR.InvalidLocalSignatureToken, unchecked ((uint)localSignatureToken)));
            }

            var ilBlock = reader.GetMemoryBlockAt(0, ilSize);

            reader.Offset += ilSize;

            ImmutableArray <ExceptionRegion> exceptionHandlers;

            if (hasExceptionHandlers)
            {
                reader.Align(4);
                byte sehHeader = reader.ReadByte();
                if ((sehHeader & SectEHTable) != SectEHTable)
                {
                    throw new BadImageFormatException(SR.Format(SR.InvalidSehHeader, sehHeader));
                }

                bool sehFatFormat = (sehHeader & SectFatFormat) == SectFatFormat;
                int  dataSize     = reader.ReadByte();
                if (sehFatFormat)
                {
                    dataSize         += reader.ReadUInt16() << 8;
                    exceptionHandlers = ReadFatExceptionHandlers(ref reader, dataSize / 24);
                }
                else
                {
                    reader.Offset    += 2; // skip over reserved field
                    exceptionHandlers = ReadSmallExceptionHandlers(ref reader, dataSize / 12);
                }
            }
            else
            {
                exceptionHandlers = ImmutableArray <ExceptionRegion> .Empty;
            }

            return(new MethodBodyBlock(
                       localsInitialized,
                       maxStack,
                       localSignatureHandle,
                       ilBlock,
                       exceptionHandlers,
                       reader.Offset - startOffset));
        }
Esempio n. 30
0
        private Property HandleProperty(Cts.Ecma.EcmaModule module, Ecma.PropertyDefinitionHandle property)
        {
            Ecma.MetadataReader reader = module.MetadataReader;

            Ecma.PropertyDefinition propDef = reader.GetPropertyDefinition(property);

            Ecma.PropertyAccessors acc          = propDef.GetAccessors();
            Cts.MethodDesc         getterMethod = acc.Getter.IsNil ? null : module.GetMethod(acc.Getter);
            Cts.MethodDesc         setterMethod = acc.Setter.IsNil ? null : module.GetMethod(acc.Setter);

            bool getterHasMetadata = getterMethod != null && _policy.GeneratesMetadata(getterMethod);
            bool setterHasMetadata = setterMethod != null && _policy.GeneratesMetadata(setterMethod);

            // Policy: If neither the getter nor setter have metadata, property doesn't have metadata
            if (!getterHasMetadata && !setterHasMetadata)
            {
                return(null);
            }

            Ecma.BlobReader       sigBlobReader = reader.GetBlobReader(propDef.Signature);
            Cts.PropertySignature sig           = new Cts.Ecma.EcmaSignatureParser(module, sigBlobReader, Cts.NotFoundBehavior.Throw).ParsePropertySignature();

            Property result = new Property
            {
                Name      = HandleString(reader.GetString(propDef.Name)),
                Flags     = propDef.Attributes,
                Signature = new PropertySignature
                {
                    CallingConvention = sig.IsStatic ? CallingConventions.Standard : CallingConventions.HasThis,
                    Type = HandleType(sig.ReturnType)
                },
            };

            result.Signature.Parameters.Capacity = sig.Length;
            for (int i = 0; i < sig.Length; i++)
            {
                result.Signature.Parameters.Add(HandleType(sig[i]));
            }

            if (getterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Getter,
                    Method     = HandleMethodDefinition(getterMethod),
                });
            }

            if (setterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Setter,
                    Method     = HandleMethodDefinition(setterMethod),
                });
            }

            Ecma.ConstantHandle defaultValue = propDef.GetDefaultValue();
            if (!defaultValue.IsNil)
            {
                result.DefaultValue = HandleConstant(module, defaultValue);
            }

            Ecma.CustomAttributeHandleCollection customAttributes = propDef.GetCustomAttributes();
            if (customAttributes.Count > 0)
            {
                result.CustomAttributes = HandleCustomAttributes(module, customAttributes);
            }

            return(result);
        }
        private unsafe static void UncompressLambdaMap(
            ImmutableArray<byte> compressedLambdaMap,
            out int methodOrdinal,
            out ImmutableArray<ClosureDebugInfo> closures,
            out ImmutableArray<LambdaDebugInfo> lambdas)
        {
            methodOrdinal = DebugId.UndefinedOrdinal;
            closures = default(ImmutableArray<ClosureDebugInfo>);
            lambdas = default(ImmutableArray<LambdaDebugInfo>);

            if (compressedLambdaMap.IsDefaultOrEmpty)
            {
                return;
            }

            var closuresBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
            var lambdasBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();

            fixed (byte* blobPtr = &compressedLambdaMap.ToArray()[0])
            {
                var blobReader = new BlobReader(blobPtr, compressedLambdaMap.Length);
                try
                {
                    // Note: integer operations below can't overflow since compressed integers are in range [0, 0x20000000)

                    // [-1, inf)
                    methodOrdinal = blobReader.ReadCompressedInteger() - 1;

                    int syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();

                    int closureCount = blobReader.ReadCompressedInteger();

                    for (int i = 0; i < closureCount; i++)
                    {
                        int syntaxOffset = blobReader.ReadCompressedInteger();

                        var closureId = new DebugId(closuresBuilder.Count, generation: 0);
                        closuresBuilder.Add(new ClosureDebugInfo(syntaxOffset + syntaxOffsetBaseline, closureId));
                    }

                    while (blobReader.RemainingBytes > 0)
                    {
                        int syntaxOffset = blobReader.ReadCompressedInteger();
                        int closureOrdinal = blobReader.ReadCompressedInteger() + LambdaDebugInfo.MinClosureOrdinal;

                        if (closureOrdinal >= closureCount)
                        {
                            throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                        }

                        var lambdaId = new DebugId(lambdasBuilder.Count, generation: 0);
                        lambdasBuilder.Add(new LambdaDebugInfo(syntaxOffset + syntaxOffsetBaseline, lambdaId, closureOrdinal));
                    }
                }
                catch (BadImageFormatException)
                {
                    throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                }
            }

            closures = closuresBuilder.ToImmutableAndFree();
            lambdas = lambdasBuilder.ToImmutableAndFree();
        }
Esempio n. 32
0
        private void ReadMetadataTableHeader(ref BlobReader memReader, out uint[] metadataTableRowCounts)
        {
            if (memReader.RemainingBytes < MetadataStreamConstants.SizeOfMetadataTableHeader)
            {
                throw new BadImageFormatException(MetadataResources.MetadataTableHeaderTooSmall);
            }

            this.MetadataTableHeader.Reserved = memReader.ReadUInt32();
            this.MetadataTableHeader.MajorVersion = memReader.ReadByte();
            this.MetadataTableHeader.MinorVersion = memReader.ReadByte();
            this.MetadataTableHeader.HeapSizeFlags = (HeapSizeFlag)memReader.ReadByte();
            this.MetadataTableHeader.RowId = memReader.ReadByte();
            this.MetadataTableHeader.ValidTables = (TableMask)memReader.ReadUInt64();
            this.MetadataTableHeader.SortedTables = (TableMask)memReader.ReadUInt64();
            ulong presentTables = (ulong)this.MetadataTableHeader.ValidTables;

            // According to ECMA-335, MajorVersion and MinorVersion have fixed values and,
            // based on recommendation in 24.1 Fixed fields: When writing these fields it
            // is best that they be set to the value indicated, on reading they should be ignored.?
            // we will not be checking version values. We will continue checking that the set of
            // present tables is within the set we understand.
            ulong validTables = (ulong)TableMask.V2_0_TablesMask;

            if ((presentTables & ~validTables) != 0)
            {
                throw new BadImageFormatException(string.Format(MetadataResources.UnknownTables, presentTables));
            }

            if (this.metadataStreamKind == MetadataStreamKind.Compressed)
            {
                // In general Ptr tables and EnC tables are not allowed in a compressed stream.
                // However when asked for a snapshot of the current metadata after an EnC change has been applied
                // the CLR includes the EnCLog table into the snapshot. We need to be able to read the image,
                // so we'll allow the table here but pretend it's empty later.
                if ((presentTables & (ulong)(TableMask.PtrTables | TableMask.EnCMap)) != 0)
                {
                    throw new BadImageFormatException(MetadataResources.IllegalTablesInCompressedMetadataStream);
                }
            }

            int numberOfTables = this.MetadataTableHeader.GetNumberOfTablesPresent();
            if (memReader.RemainingBytes < numberOfTables * sizeof(int))
            {
                throw new BadImageFormatException(MetadataResources.TableRowCountSpaceTooSmall);
            }

            var rowCounts = new uint[numberOfTables];
            for (int i = 0; i < rowCounts.Length; i++)
            {
                rowCounts[i] = memReader.ReadUInt32();
            }

            metadataTableRowCounts = rowCounts;
        }
Esempio n. 33
0
        private Property HandleProperty(Cts.Ecma.EcmaModule module, Ecma.PropertyDefinitionHandle property)
        {
            Ecma.MetadataReader reader = module.MetadataReader;

            Ecma.PropertyDefinition propDef = reader.GetPropertyDefinition(property);

            Ecma.PropertyAccessors acc          = propDef.GetAccessors();
            Cts.MethodDesc         getterMethod = acc.Getter.IsNil ? null : module.GetMethod(acc.Getter);
            Cts.MethodDesc         setterMethod = acc.Setter.IsNil ? null : module.GetMethod(acc.Setter);

            bool getterHasMetadata = getterMethod != null && _policy.GeneratesMetadata(getterMethod);
            bool setterHasMetadata = setterMethod != null && _policy.GeneratesMetadata(setterMethod);

            // Policy: If neither the getter nor setter have metadata, property doesn't have metadata
            if (!getterHasMetadata && !setterHasMetadata)
            {
                return(null);
            }

            Ecma.BlobReader       sigBlobReader = reader.GetBlobReader(propDef.Signature);
            Cts.PropertySignature sig           = new Cts.Ecma.EcmaSignatureParser(module, sigBlobReader).ParsePropertySignature();

            List <ParameterTypeSignature> parameters;

            if (sig.Length == 0)
            {
                parameters = null;
            }
            else
            {
                parameters = new List <ParameterTypeSignature>(sig.Length);
                for (int i = 0; i < parameters.Count; i++)
                {
                    parameters.Add(HandleParameterTypeSignature(sig[i]));
                }
            }

            Property result = new Property
            {
                Name      = HandleString(reader.GetString(propDef.Name)),
                Flags     = propDef.Attributes,
                Signature = new PropertySignature
                {
                    CallingConvention = sig.IsStatic ? CallingConventions.Standard : CallingConventions.HasThis,
                    // TODO: CustomModifiers
                    Type       = HandleType(sig.ReturnType),
                    Parameters = parameters,
                },
            };

            if (getterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Getter,
                    Method     = HandleMethodDefinition(getterMethod),
                });
            }

            if (setterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Setter,
                    Method     = HandleMethodDefinition(setterMethod),
                });
            }

            // TODO: DefaultValue
            // TODO: CustomAttributes

            return(result);
        }
Esempio n. 34
0
        /// <summary>
        /// Creates a metadata reader from the metadata stored at the given memory location.
        /// </summary>
        /// <remarks>
        /// The memory is owned by the caller and it must be kept memory alive and unmodified throughout the lifetime of the <see cref="MetadataReader"/>.
        /// Use <see cref="PEReaderExtensions.GetMetadataReader(PortableExecutable.PEReader, MetadataReaderOptions, MetadataStringDecoder)"/> to obtain 
        /// metadata from a PE image.
        /// </remarks>
        public unsafe MetadataReader(byte* metadata, int length, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
        {
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            if (metadata == null)
            {
                throw new ArgumentNullException("metadata");
            }

            if (utf8Decoder == null)
            {
                utf8Decoder = MetadataStringDecoder.DefaultUTF8;
            }

            if (!(utf8Decoder.Encoding is UTF8Encoding))
            {
                throw new ArgumentException(MetadataResources.MetadataStringDecoderEncodingMustBeUtf8, "utf8Decoder");
            }

            if (!BitConverter.IsLittleEndian)
            {
                throw new PlatformNotSupportedException(MetadataResources.LitteEndianArchitectureRequired);
            }

            this.Block = new MemoryBlock(metadata, length);

            this.options = options;
            this.utf8Decoder = utf8Decoder;

            BlobReader memReader = new BlobReader(this.Block);

            this.ReadMetadataHeader(ref memReader);

            // storage header and stream headers:
            MemoryBlock metadataTableStream;
            var streamHeaders = this.ReadStreamHeaders(ref memReader);
            this.InitializeStreamReaders(ref this.Block, streamHeaders, out metadataTableStream);

            memReader = new BlobReader(metadataTableStream);

            uint[] metadataTableRowCounts;
            this.ReadMetadataTableHeader(ref memReader, out metadataTableRowCounts);
            this.InitializeTableReaders(memReader.GetMemoryBlockAt(0, memReader.RemainingBytes), metadataTableRowCounts);

            // This previously could occur in obfuscated assemblies but a check was added to prevent
            // it getting to this point
            Debug.Assert(this.AssemblyTable.NumberOfRows <= 1);

            // Although the specification states that the module table will have exactly one row,
            // the native metadata reader would successfully read files containing more than one row.
            // Such files exist in the wild and may be produced by obfuscators.
            if (this.ModuleTable.NumberOfRows < 1)
            {
                throw new BadImageFormatException(string.Format(MetadataResources.ModuleTableInvalidNumberOfRows, this.ModuleTable.NumberOfRows));
            }

            //  read
            this.namespaceCache = new NamespaceCache(this);

            if (this.metadataKind != MetadataKind.Ecma335)
            {
                this.WinMDMscorlibRef = FindMscorlibAssemblyRefNoProjection();
            }
        }
Esempio n. 35
0
        /// <summary>
        /// Looks like this function reads beginning of the header described in
        /// ECMA-335 24.2.1 Metadata root
        /// </summary>
        private void ReadMetadataHeader(ref BlobReader memReader, out string versionString)
        {
            if (memReader.RemainingBytes < COR20Constants.MinimumSizeofMetadataHeader)
            {
                throw new BadImageFormatException(SR.MetadataHeaderTooSmall);
            }

            uint signature = memReader.ReadUInt32();
            if (signature != COR20Constants.COR20MetadataSignature)
            {
                throw new BadImageFormatException(SR.MetadataSignature);
            }

            // major version
            memReader.ReadUInt16();

            // minor version
            memReader.ReadUInt16();

            // reserved:
            memReader.ReadUInt32();

            int versionStringSize = memReader.ReadInt32();
            if (memReader.RemainingBytes < versionStringSize)
            {
                throw new BadImageFormatException(SR.NotEnoughSpaceForVersionString);
            }

            int numberOfBytesRead;
            versionString = memReader.GetMemoryBlockAt(0, versionStringSize).PeekUtf8NullTerminated(0, null, UTF8Decoder, out numberOfBytesRead, '\0');
            memReader.SkipBytes(versionStringSize);
        }
Esempio n. 36
0
        private object ReadAndTranslateValue(ref BlobReader sigReader, SignatureTypeCode typeCode, out bool isEnumTypeCode)
        {
            switch (typeCode)
            {
                case SignatureTypeCode.Boolean:
                    isEnumTypeCode = true;
                    return (short)(sigReader.ReadBoolean() ? 1 : 0);

                case SignatureTypeCode.Char:
                    isEnumTypeCode = true;
                    return (ushort)sigReader.ReadChar();

                case SignatureTypeCode.SByte:
                    isEnumTypeCode = true;
                    return (short)sigReader.ReadSByte();

                case SignatureTypeCode.Byte:
                    isEnumTypeCode = true;
                    return (short)sigReader.ReadByte();

                case SignatureTypeCode.Int16:
                    isEnumTypeCode = true;
                    return sigReader.ReadInt16();

                case SignatureTypeCode.UInt16:
                    isEnumTypeCode = true;
                    return sigReader.ReadUInt16();

                case SignatureTypeCode.Int32:
                    isEnumTypeCode = true;
                    return sigReader.ReadInt32();

                case SignatureTypeCode.UInt32:
                    isEnumTypeCode = true;
                    return sigReader.ReadUInt32();

                case SignatureTypeCode.Int64:
                    isEnumTypeCode = true;
                    return sigReader.ReadInt64();

                case SignatureTypeCode.UInt64:
                    isEnumTypeCode = true;
                    return sigReader.ReadUInt64();

                case SignatureTypeCode.Single:
                    isEnumTypeCode = false;
                    return sigReader.ReadSingle();

                case SignatureTypeCode.Double:
                    isEnumTypeCode = false;
                    return sigReader.ReadDouble();

                case SignatureTypeCode.String:
                    isEnumTypeCode = false;

                    if (sigReader.RemainingBytes == 1)
                    {
                        if (sigReader.ReadByte() != 0xff)
                        {
                            throw new BadImageFormatException();
                        }

                        return NullReferenceValue;
                    }

                    if (sigReader.RemainingBytes % 2 != 0)
                    {
                        throw new BadImageFormatException();
                    }

                    return sigReader.ReadUTF16(sigReader.RemainingBytes);

                case SignatureTypeCode.Object:
                    // null reference
                    isEnumTypeCode = false;
                    return NullReferenceValue;

                default:
                    throw new BadImageFormatException();
            }
        }
Esempio n. 37
0
        private void ReadMetadataTableHeader(ref BlobReader reader, out HeapSizes heapSizes, out int[] metadataTableRowCounts, out TableMask sortedTables)
        {
            if (reader.RemainingBytes < MetadataStreamConstants.SizeOfMetadataTableHeader)
            {
                throw new BadImageFormatException(SR.MetadataTableHeaderTooSmall);
            }

            // reserved (shall be ignored):
            reader.ReadUInt32();

            // major version (shall be ignored):
            reader.ReadByte();

            // minor version (shall be ignored):
            reader.ReadByte();

            // heap sizes:
            heapSizes = (HeapSizes)reader.ReadByte();

            // reserved (shall be ignored):
            reader.ReadByte();

            ulong presentTables = reader.ReadUInt64();
            sortedTables = (TableMask)reader.ReadUInt64();

            // According to ECMA-335, MajorVersion and MinorVersion have fixed values and, 
            // based on recommendation in 24.1 Fixed fields: When writing these fields it 
            // is best that they be set to the value indicated, on reading they should be ignored.
            // We will not be checking version values. We will continue checking that the set of 
            // present tables is within the set we understand.

            ulong validTables = (ulong)(TableMask.TypeSystemTables | TableMask.DebugTables);

            if ((presentTables & ~validTables) != 0)
            {
                throw new BadImageFormatException(SR.Format(SR.UnknownTables, presentTables));
            }

            if (_metadataStreamKind == MetadataStreamKind.Compressed)
            {
                // In general Ptr tables and EnC tables are not allowed in a compressed stream.
                // However when asked for a snapshot of the current metadata after an EnC change has been applied 
                // the CLR includes the EnCLog table into the snapshot. We need to be able to read the image,
                // so we'll allow the table here but pretend it's empty later.
                if ((presentTables & (ulong)(TableMask.PtrTables | TableMask.EnCMap)) != 0)
                {
                    throw new BadImageFormatException(SR.IllegalTablesInCompressedMetadataStream);
                }
            }

            metadataTableRowCounts = ReadMetadataTableRowCounts(ref reader, presentTables);

            if ((heapSizes & HeapSizes.ExtraData) == HeapSizes.ExtraData)
            {
                // Skip "extra data" used by some obfuscators. Although it is not mentioned in the CLI spec,
                // it is honored by the native metadata reader.
                reader.ReadUInt32();
            }
        }