示例#1
0
 private static String ReadSysString(Stream stream, SysStringContainer sysStrings, Boolean[] streamWidths, Byte[] tmpArray)
 {
     return(sysStrings.GetString((Int32)stream.ReadHeapIndex(streamWidths[SYS_STR_WIDTH_INDEX], tmpArray)));
 }
示例#2
0
        internal MetaDataReader(Stream stream, out String versionStr)
        {
            var mdRoot = stream.Position;

            // Prepare variables
            var utf8     = MetaDataConstants.SYS_STRING_ENCODING;
            var tmpArray = new Byte[8];

            // Skip signature, major & minor version, and reserved
            stream.SeekFromCurrent(12);

            // Read version string
            var versionStrByteLen = stream.ReadU32(tmpArray);

            versionStr = stream.ReadZeroTerminatedString(versionStrByteLen, utf8);

            // Skip flags
            stream.SeekFromCurrent(2);

            // Amount of streams
            var amountOfStreams = stream.ReadU16(tmpArray);

            // Stream headers
            var streamDic = new Dictionary <String, Tuple <UInt32, UInt32> >();

            //var totalRead = 12 // Sig, major & minor version, reserved
            //   + versionStrByteLen // Version string
            //   + 4; // Flags, amount of streams
            for (var i = 0; i < amountOfStreams; ++i)
            {
                var offset = stream.ReadU32(tmpArray);
                var size   = stream.ReadU32(tmpArray);
                //UInt32 streamStringBytesLen;
                streamDic.Add(stream.ReadAlignedASCIIString(32), Tuple.Create(offset, size));
                //totalRead += streamStringBytesLen + 8;
            }

            // Read all streams except table stream
            SysStringContainer sysStrings = null;
            GUIDContainer      guids      = null;
            BLOBContainer      blobs      = null;

            foreach (var kvp in streamDic)
            {
                stream.SeekFromBegin(mdRoot + kvp.Value.Item1);
                switch (kvp.Key)
                {
                case Consts.SYS_STRING_STREAM_NAME:
                    sysStrings = new SysStringContainer(stream, kvp.Value.Item2);
                    break;

                case Consts.USER_STRING_STREAM_NAME:
                    this.userStrings = new UserStringContainer(stream, kvp.Value.Item2);
                    break;

                case Consts.GUID_STREAM_NAME:
                    guids = new GUIDContainer(stream, kvp.Value.Item2);
                    break;

                case Consts.BLOB_STREAM_NAME:
                    blobs = new BLOBContainer(stream, kvp.Value.Item2);
                    break;
                }
            }

            // Read table stream
            stream.SeekFromBegin(mdRoot + streamDic[Consts.TABLE_STREAM_NAME].Item1
                                 + 6 // Skip reserved + major & minor versions
                                 );

            // Stream index sizes
            var b            = stream.ReadByteFromStream();
            var streamWidths = new Boolean[MAX_WIDTH_INDEX];

            streamWidths[SYS_STR_WIDTH_INDEX] = (b & WIDE_SYS_STRING_FLAG) != 0;
            streamWidths[GUID_WIDTH_INDEX]    = (b & WIDE_GUID_FLAG) != 0;
            streamWidths[BLOB_WIDTH_INDEX]    = (b & WIDE_BLOB_FLAG) != 0;

            stream.SeekFromCurrent(1); // Skip reserved

            // Present tables
            var presentTableMask = stream.ReadU64(tmpArray);

            stream.SeekFromCurrent(8); // Skip sorted

            // Table row count
            var tableSizes = Enumerable.Range(0, TablesUtils.AMOUNT_OF_TABLES)
                             .Select(
                val =>
            {
                UInt32 size;
                if (((UInt32)(presentTableMask >> val)) % 2 == 1)
                {
                    size = stream.ReadU32(tmpArray);
                }
                else
                {
                    size = 0;
                }
                return(size);
            }).ToArray();

            // Read actual tables
            var tRefSizes = MetaDataConstants.GetCodedTableIndexSizes(tableSizes);

            foreach (var curTable in Enumerable.Range(0, TablesUtils.AMOUNT_OF_TABLES))
            {
                switch ((Tables)curTable)
                {
                // VS2012 evaluates positional arguments from left to right, so creating Tuple inside lambda should work correctly
                // This is not so in VS2010 ( see http://msdn.microsoft.com/en-us/library/hh678682.aspx )
                case Tables.Module:
                    ReadTable(ref this.module, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadGUID(stream, guids, streamWidths, tmpArray),
                                  ReadGUID(stream, guids, streamWidths, tmpArray),
                                  ReadGUID(stream, guids, streamWidths, tmpArray))
                              );
                    break;

                case Tables.TypeRef:
                    ReadTable(ref this.typeRef, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.ResolutionScope, tRefSizes, tmpArray, false),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.TypeDef:
                    ReadTable(ref this.typeDef, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (TypeAttributes)stream.ReadU32(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray, false),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.MethodDef, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.Field:
                    ReadTable(ref this.field, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (FieldAttributes)stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.MethodDef:
                    ReadTable(ref this.methodDef, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU32(tmpArray),
                                  (MethodImplAttributes)stream.ReadU16(tmpArray),
                                  (MethodAttributes)stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Parameter, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.Parameter:
                    ReadTable(ref this.param, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (ParameterAttributes)stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.InterfaceImpl:
                    ReadTable(ref this.interfaceImpl, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.MemberRef:
                    ReadTable(ref this.memberRef, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MemberRefParent, tRefSizes, tmpArray).Value,
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.Constant:
                    ReadTable(ref this.constant, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU16(tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasConstant, tRefSizes, tmpArray).Value,
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.CustomAttribute:
                    ReadTable(ref this.customAttribute, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasCustomAttribute, tRefSizes, tmpArray).Value,
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.CustomAttributeType, tRefSizes, tmpArray).Value,
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.FieldMarshal:
                    ReadTable(ref this.fieldMarshal, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasFieldMarshal, tRefSizes, tmpArray).Value,
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.DeclSecurity:
                    ReadTable(ref this.declSecurity, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU16(tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasDeclSecurity, tRefSizes, tmpArray).Value,
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.ClassLayout:
                    ReadTable(ref this.classLayout, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU32(tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.FieldLayout:
                    ReadTable(ref this.fieldLayout, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU32(tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.StandaloneSignature:
                    ReadTable(ref this.standaloneSig, curTable, tableSizes, () => ReadBLOB(stream, blobs, streamWidths, tmpArray));
                    break;

                case Tables.EventMap:
                    ReadTable(ref this.eventMap, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Event, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.Event:
                    ReadTable(ref this.events, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (EventAttributes)stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.PropertyMap:
                    ReadTable(ref this.propertyMap, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Property, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.Property:
                    ReadTable(ref this.property, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (PropertyAttributes)stream.ReadU16(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.MethodSemantics:
                    ReadTable(ref this.methodSemantics, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (MethodSemanticsAttributes)stream.ReadU16(tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.MethodDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasSemantics, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.MethodImpl:
                    ReadTable(ref this.methodImpl, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value,
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.ModuleRef:
                    ReadTable(ref this.moduleRef, curTable, tableSizes, () => ReadSysString(stream, sysStrings, streamWidths, tmpArray));
                    break;

                case Tables.TypeSpec:
                    ReadTable(ref this.typeSpec, curTable, tableSizes, () => ReadBLOB(stream, blobs, streamWidths, tmpArray));
                    break;

                case Tables.ImplMap:
                    ReadTable(ref this.implMap, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (PInvokeAttributes)stream.ReadU16(tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MemberForwarded, tRefSizes, tmpArray).Value,
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.ModuleRef, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.FieldRVA:
                    ReadTable(ref this.fieldRVA, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU32(tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.Assembly:
                    ReadTable(ref this.assembly, curTable, tableSizes, () =>
                              Tuples.Create(
                                  (AssemblyHashAlgorithm)stream.ReadU32(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  (AssemblyFlags)stream.ReadU32(tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.AssemblyRef:
                    ReadTable(ref this.assemblyRef, curTable, tableSizes, () =>
                              Tuples.Create(
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  stream.ReadU16(tmpArray),
                                  (AssemblyFlags)stream.ReadU32(tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.File:
                    ReadTable(ref this.file, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (FileAttributes)stream.ReadU32(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.ExportedType:
                    ReadTable(ref this.exportedType, curTable, tableSizes, () =>
                              Tuple.Create(
                                  (TypeAttributes)stream.ReadU32(tmpArray),
                                  stream.ReadU32(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.Implementation, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.ManifestResource:
                    ReadTable(ref this.manifestResource, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU32(tmpArray),
                                  (ManifestResourceAttributes)stream.ReadU32(tmpArray),
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.Implementation, tRefSizes, tmpArray, false)
                                  ));
                    break;

                case Tables.NestedClass:
                    ReadTable(ref this.nestedClass, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray),
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray)
                                  ));
                    break;

                case Tables.GenericParameter:
                    ReadTable(ref this.genericParam, curTable, tableSizes, () =>
                              Tuple.Create(
                                  stream.ReadU16(tmpArray),
                                  (GenericParameterAttributes)stream.ReadU16(tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeOrMethodDef, tRefSizes, tmpArray).Value,
                                  ReadSysString(stream, sysStrings, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.MethodSpec:
                    ReadTable(ref this.methodSpec, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value,
                                  ReadBLOB(stream, blobs, streamWidths, tmpArray)
                                  ));
                    break;

                case Tables.GenericParameterConstraint:
                    ReadTable(ref this.genericParamConstraint, curTable, tableSizes, () =>
                              Tuple.Create(
                                  MetaDataConstants.ReadSimpleTableIndex(stream, Tables.GenericParameter, tableSizes, tmpArray),
                                  MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value
                                  ));
                    break;

                case Tables.FieldPtr:
                case Tables.MethodPtr:
                case Tables.ParameterPtr:
                case Tables.EventPtr:
                case Tables.PropertyPtr:
                case Tables.EncLog:
                case Tables.EncMap:
                case Tables.AssemblyProcessor:
                case Tables.AssemblyOS:
                case Tables.AssemblyRefProcessor:
                case Tables.AssemblyRefOS:
                    // Skip
                    break;

                default:
                    throw new BadImageFormatException("Unknown table: " + curTable);
                }
            }
        }