diff options
Diffstat (limited to 'tools/Sandcastle/Source/CCI/Metadata.cs')
-rw-r--r-- | tools/Sandcastle/Source/CCI/Metadata.cs | 3849 |
1 files changed, 3849 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/Metadata.cs b/tools/Sandcastle/Source/CCI/Metadata.cs new file mode 100644 index 0000000..6272d8a --- /dev/null +++ b/tools/Sandcastle/Source/CCI/Metadata.cs @@ -0,0 +1,3849 @@ +// Copyright © Microsoft Corporation. +// This source file is subject to the Microsoft Permissive License. +// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. +// All other rights reserved. + +using System; +#if FxCop +using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection; +using TypeNodeList = Microsoft.Cci.TypeNodeCollection; +#endif +#if CCINamespace +using Microsoft.Cci; +#else +using System.Compiler; +#endif +using System.Collections; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.Serialization; + +//^ using Microsoft.Contracts; + +/* These classes help with parsing and producing PE files. They are best understood in conjunction with the ECMA 335 Specification + * (Common Language Infrastructure), particularly Partition II. Also see "Inside Microsoft .NET IL Assembler" by Serge Lidin. */ + +#if CCINamespace +namespace Microsoft.Cci.Metadata{ +#else +namespace System.Compiler.Metadata +{ +#endif + internal struct AssemblyRow + { + internal int HashAlgId; + internal int MajorVersion; + internal int MinorVersion; + internal int BuildNumber; + internal int RevisionNumber; + internal int Flags; + internal int PublicKey; + internal int Name; + internal int Culture; + } + internal struct AssemblyRefRow + { + internal int MajorVersion; + internal int MinorVersion; + internal int BuildNumber; + internal int RevisionNumber; + internal int Flags; + internal int PublicKeyOrToken; + internal int Name; + internal int Culture; + internal int HashValue; + internal AssemblyReference AssemblyReference; + } + internal struct ClassLayoutRow + { + internal int PackingSize; + internal int ClassSize; + internal int Parent; + } + internal struct ConstantRow + { + internal int Type; + internal int Parent; + internal int Value; + } + internal struct CustomAttributeRow + { + internal int Parent; + internal int Constructor; + internal int Value; + } + internal struct DeclSecurityRow + { + internal int Action; + internal int Parent; + internal int PermissionSet; + } + internal struct EventMapRow + { + internal int Parent; + internal int EventList; + } + internal struct EventPtrRow + { + internal int Event; + } + internal struct EventRow + { + internal int Flags; + internal int Name; + internal int EventType; + } + internal struct ExportedTypeRow + { + internal int Flags; + internal int TypeDefId; + internal int TypeName; + internal int TypeNamespace; + internal int Implementation; + } + internal struct FieldRow + { + internal int Flags; + internal int Name; + internal int Signature; + internal Field Field; + } + internal struct FieldLayoutRow + { + internal int Offset; + internal int Field; + } + internal struct FieldMarshalRow + { + internal int Parent; + internal int NativeType; + } + internal struct FieldPtrRow + { + internal int Field; + } + internal struct FieldRvaRow + { + internal int RVA; + internal int Field; + internal PESection TargetSection; + } + internal struct FileRow + { + internal int Flags; + internal int Name; + internal int HashValue; + } + internal struct GenericParamRow + { + internal int Number; + internal int Flags; + internal int Owner; + internal int Name; + internal Member GenericParameter; + } + internal struct GenericParamConstraintRow + { + internal int Param; + internal int Constraint; + } + internal struct ImplMapRow + { + internal int MappingFlags; + internal int MemberForwarded; + internal int ImportName; + internal int ImportScope; + } + internal struct InterfaceImplRow + { + internal int Class; + internal int Interface; + } + internal struct ManifestResourceRow + { + internal int Offset; + internal int Flags; + internal int Name; + internal int Implementation; + } + internal struct MemberRefRow + { + internal int Class; + internal int Name; + internal int Signature; + internal Member Member; + internal TypeNodeList VarargTypes; + } + internal struct MethodRow + { + internal int RVA; + internal int ImplFlags; + internal int Flags; + internal int Name; + internal int Signature; + internal int ParamList; + internal Method Method; + } + internal struct MethodImplRow + { + internal int Class; + internal int MethodBody; + internal int MethodDeclaration; + } + internal struct MethodPtrRow + { + internal int Method; + } + internal struct MethodSemanticsRow + { + internal int Semantics; + internal int Method; + internal int Association; + } + internal struct MethodSpecRow + { + internal int Method; + internal int Instantiation; + internal Method InstantiatedMethod; + } + internal struct ModuleRow + { + internal int Generation; + internal int Name; + internal int Mvid; + internal int EncId; + internal int EncBaseId; + } + internal struct ModuleRefRow + { + internal int Name; +#if FxCop + internal ModuleNode Module; +#else + internal Module Module; +#endif + } + internal struct NestedClassRow + { + internal int NestedClass; + internal int EnclosingClass; + } + internal struct ParamRow + { + internal int Flags; + internal int Sequence; + internal int Name; + } + internal struct ParamPtrRow + { + internal int Param; + } + internal struct PropertyRow + { + internal int Flags; + internal int Name; + internal int Signature; + } + internal struct PropertyPtrRow + { + internal int Property; + } + internal struct PropertyMapRow + { + internal int Parent; + internal int PropertyList; + } + internal struct StandAloneSigRow + { + internal int Signature; + } + internal struct TypeDefRow + { + internal int Flags; + internal int Name; + internal int Namespace; + internal int Extends; + internal int FieldList; + internal int MethodList; + internal TypeNode Type; + internal Identifier NamespaceId; + internal int NamespaceKey; + internal int NameKey; + } + internal struct TypeRefRow + { + internal int ResolutionScope; + internal int Name; + internal int Namespace; + internal TypeNode Type; + } + internal struct TypeSpecRow + { + internal int Signature; + internal TypeNode Type; + } + [Serializable] + public sealed class InvalidMetadataException : System.Exception + { + public InvalidMetadataException() { } + public InvalidMetadataException(string message) + : base(message) + { + } + public InvalidMetadataException(string message, Exception innerException) + : base(message, innerException) + { + } + private InvalidMetadataException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } + + internal class CLIHeader + { + internal int cb; + internal ushort majorRuntimeVersion; + internal ushort minorRuntimeVersion; + internal DirectoryEntry metaData; + internal int flags; + internal int entryPointToken; + internal DirectoryEntry resources; + internal DirectoryEntry strongNameSignature; + internal DirectoryEntry codeManagerTable; + internal DirectoryEntry vtableFixups; + internal DirectoryEntry exportAddressTableJumps; + + internal CLIHeader() + { + this.cb = 72; + this.majorRuntimeVersion = 2; + this.minorRuntimeVersion = 5; + // initialization provided by runtime + //this.flags = 0; + //this.entryPointToken = 0; + } + } + internal struct DirectoryEntry + { + internal int virtualAddress; + internal int size; + } + internal class MetadataHeader + { + internal int signature; + internal ushort majorVersion; + internal ushort minorVersion; + internal int reserved; + internal string versionString; + internal int flags; + internal StreamHeader[] streamHeaders; + } + internal class NTHeader + { + internal int signature; + internal ushort machine; + internal ushort numberOfSections; + internal int timeDateStamp; + internal int pointerToSymbolTable; + internal int numberOfSymbols; + internal ushort sizeOfOptionalHeader; + internal ushort characteristics; + internal ushort magic; + internal byte majorLinkerVersion; + internal byte minorLinkerVersion; + internal int sizeOfCode; + internal int sizeOfInitializedData; + internal int sizeOfUninitializedData; + internal int addressOfEntryPoint; + internal int baseOfCode; + internal int baseOfData; + internal long imageBase; + internal int sectionAlignment; + internal int fileAlignment; + internal ushort majorOperatingSystemVersion; + internal ushort minorOperatingSystemVersion; + internal ushort majorImageVersion; + internal ushort minorImageVersion; + internal ushort majorSubsystemVersion; + internal ushort minorSubsystemVersion; + internal int win32VersionValue; + internal int sizeOfImage; + internal int sizeOfHeaders; + internal int checkSum; + internal ushort subsystem; + internal ushort dllCharacteristics; + internal long sizeOfStackReserve; + internal long sizeOfStackCommit; + internal long sizeOfHeapReserve; + internal long sizeOfHeapCommit; + internal int loaderFlags; + internal int numberOfDataDirectories; + internal DirectoryEntry exportTable; + internal DirectoryEntry importTable; + internal DirectoryEntry resourceTable; + internal DirectoryEntry exceptionTable; + internal DirectoryEntry certificateTable; + internal DirectoryEntry baseRelocationTable; + internal DirectoryEntry debugTable; + internal DirectoryEntry copyrightTable; + internal DirectoryEntry globalPointerTable; + internal DirectoryEntry threadLocalStorageTable; + internal DirectoryEntry loadConfigTable; + internal DirectoryEntry boundImportTable; + internal DirectoryEntry importAddressTable; + internal DirectoryEntry delayImportTable; + internal DirectoryEntry cliHeaderTable; + internal DirectoryEntry reserved; + + internal NTHeader() + { + this.signature = 0x00004550; /* "PE\0\0" */ + this.machine = 0x14c; + this.sizeOfOptionalHeader = 224; + this.characteristics = 0x0002 | 0x0004 | 0x008 | 0x0100; + this.magic = 0x10B; + this.majorLinkerVersion = 6; + this.baseOfCode = 0x2000; + this.imageBase = 0x400000; //TODO: make this settable + this.sectionAlignment = 8192; + this.fileAlignment = 512; + this.majorOperatingSystemVersion = 4; + this.majorSubsystemVersion = 4; + this.dllCharacteristics = 0x400; + this.sizeOfStackReserve = 1048576; + this.sizeOfStackCommit = 4096; + this.sizeOfHeapReserve = 1048576; + this.sizeOfHeapCommit = 4096; + this.numberOfDataDirectories = 16; + + // initialization provided by runtime + //this.numberOfSections = 0; + //this.timeDateStamp = 0; + //this.pointerToSymbolTable = 0; + //this.numberOfSymbols = 0; + //this.minorLinkerVersion = 0; + //this.sizeOfCode = 0; + //this.sizeOfInitializedData = 0; + //this.sizeOfUninitializedData = 0; + //this.addressOfEntryPoint = 0; + //this.baseOfData = 0; + //this.minorOperatingSystemVersion = 0; + //this.majorImageVersion = 0; + //this.minorImageVersion = 0; + //this.minorSubsystemVersion = 0; + //this.win32VersionValue = 0; + //this.sizeOfImage = 0; + //this.sizeOfHeaders = 0; + //this.checkSum = 0; + //this.subsystem = 0; + //this.loaderFlags = 0x0; + } + } + internal struct SectionHeader + { + internal string name; + internal int virtualSize; + internal int virtualAddress; + internal int sizeOfRawData; + internal int pointerToRawData; + internal int pointerToRelocations; + internal int pointerToLinenumbers; + internal ushort numberOfRelocations; + internal ushort numberOfLinenumbers; + internal int characteristics; + } + internal class StreamHeader + { + internal int offset; + internal int size; + internal String name; + } + internal class TablesHeader + { + internal int reserved; + internal byte majorVersion; + internal byte minorVersion; + internal byte heapSizes; + internal byte rowId; + internal long maskValid; + internal long maskSorted; + internal int[] countArray; + } + internal enum TableIndices + { + Module = 0x00, + TypeRef = 0x01, + TypeDef = 0x02, + FieldPtr = 0x03, + Field = 0x04, + MethodPtr = 0x05, + Method = 0x06, + ParamPtr = 0x07, + Param = 0x08, + InterfaceImpl = 0x09, + MemberRef = 0x0A, + Constant = 0x0B, + CustomAttribute = 0x0C, + FieldMarshal = 0x0D, + DeclSecurity = 0x0E, + ClassLayout = 0x0F, + FieldLayout = 0x10, + StandAloneSig = 0x11, + EventMap = 0x12, + EventPtr = 0x13, + Event = 0x14, + PropertyMap = 0x15, + PropertyPtr = 0x16, + Property = 0x17, + MethodSemantics = 0x18, + MethodImpl = 0x19, + ModuleRef = 0x1A, + TypeSpec = 0x1B, + ImplMap = 0x1C, + FieldRva = 0x1D, + EncLog = 0x1E, + EncMap = 0x1F, + Assembly = 0x20, + AssemblyProcessor = 0x21, + AssemblyOS = 0x22, + AssemblyRef = 0x23, + AssemblyRefProcessor = 0x24, + AssemblyRefOS = 0x25, + File = 0x26, + ExportedType = 0x27, + ManifestResource = 0x28, + NestedClass = 0x29, + GenericParam = 0x2a, + MethodSpec = 0x2b, + GenericParamConstraint = 0x2c, + Count + } + internal enum ElementType + { + End = 0x00, + Void = 0x01, + Boolean = 0x02, + Char = 0x03, + Int8 = 0x04, + UInt8 = 0x05, + Int16 = 0x06, + UInt16 = 0x07, + Int32 = 0x08, + UInt32 = 0x09, + Int64 = 0x0a, + UInt64 = 0x0b, + Single = 0x0c, + Double = 0x0d, + String = 0x0e, + Pointer = 0x0f, + Reference = 0x10, + ValueType = 0x11, + Class = 0x12, + TypeParameter = 0x13, + Array = 0x14, + GenericTypeInstance = 0x15, + DynamicallyTypedReference = 0x16, + IntPtr = 0x18, + UIntPtr = 0x19, + FunctionPointer = 0x1b, + Object = 0x1c, + SzArray = 0x1d, + MethodParameter = 0x1e, + RequiredModifier = 0x1f, + OptionalModifier = 0x20, + Internal = 0x21, + Modifier = 0x40, + Sentinel = 0x41, + Pinned = 0x45, + Type = 0x50, + BoxedEnum = 0x51, + Enum = 0x55 + } + + unsafe internal class MetadataReader : IDisposable + { +#if !ROTOR + private MemoryMappedFile memmap; +#endif + private MemoryCursor/*!*/ cursor; + internal int entryPointToken; + internal int fileAlignment; + internal ModuleKindFlags moduleKind; + internal PEKindFlags peKind; + internal bool TrackDebugData; + private int mdOffset; + private int resourcesOffset; + private int win32ResourcesOffset; + private SectionHeader[] sectionHeaders; + //^ [SpecPublic] + private StreamHeader identifierStringHeap; + //^ [SpecPublic] + private StreamHeader generalStringHeap; + private StreamHeader blobHeap; + //^ [SpecPublic] + private StreamHeader guidHeap; + private StreamHeader tables; + internal TablesHeader tablesHeader; + internal string targetRuntimeVersion; + internal int linkerMajorVersion; + internal int linkerMinorVersion; + internal int metadataFormatMajorVersion; + internal int metadataFormatMinorVersion; + private int blobRefSize; + private int constantParentRefSize; + private int customAttributeParentRefSize; + private int customAttributeConstructorRefSize; + private int declSecurityParentRefSize; + private int fieldMarshalParentRefSize; + private int guidRefSize; + private int hasSemanticRefSize; + private int implementationRefSize; + private int methodDefOrRefSize; + private int memberRefParentSize; + private int memberForwardedRefSize; + private int typeDefOrRefOrSpecSize; + private int typeDefOrMethodDefSize; + private int resolutionScopeRefSize; + private int stringRefSize; + private int[] tableSize; + private int[] tableRefSize; + private int[] tableOffset; + internal byte[] HashValue; + +#if !ROTOR + internal MetadataReader(string path) + { + MemoryMappedFile memmap = this.memmap = new MemoryMappedFile(path); + try + { + this.cursor = new MemoryCursor(memmap); + //^ base(); + ReadHeader(); + } + catch + { + this.Dispose(); + throw; + } + } +#endif + + internal MetadataReader(byte* buffer, int length) + { + this.cursor = new MemoryCursor(buffer, length); + //^ base(); + ReadHeader(); + } + + public void Dispose() + { +#if !ROTOR + if (this.memmap != null) this.memmap.Dispose(); + this.memmap = null; +#endif + //this.cursor = null; + this.sectionHeaders = null; + this.identifierStringHeap = null; + this.generalStringHeap = null; + this.blobHeap = null; + this.guidHeap = null; + this.tables = null; + this.tablesHeader = null; + this.targetRuntimeVersion = null; + this.tableSize = null; + this.tableRefSize = null; + this.tableOffset = null; + this.HashValue = null; + } + + private AssemblyRow[] assemblyTable; + private AssemblyRefRow[] assemblyRefTable; + private ClassLayoutRow[] classLayoutTable; + private ConstantRow[] constantTable; + private CustomAttributeRow[] customAttributeTable; + private DeclSecurityRow[] declSecurityTable; + private EventMapRow[] eventMapTable; + private EventPtrRow[] eventPtrTable; + private EventRow[] eventTable; + private ExportedTypeRow[] exportedTypeTable; + private FieldRow[] fieldTable; + private FieldLayoutRow[] fieldLayoutTable; + private FieldMarshalRow[] fieldMarshalTable; + private FieldPtrRow[] fieldPtrTable; + private FieldRvaRow[] fieldRvaTable; + private FileRow[] fileTable; + private GenericParamRow[] genericParamTable; + private GenericParamConstraintRow[] genericParamConstraintTable; + private ImplMapRow[] implMapTable; + private InterfaceImplRow[] interfaceImplTable; + private ManifestResourceRow[] manifestResourceTable; + private MemberRefRow[] memberRefTable; + private MethodRow[] methodTable; + private MethodPtrRow[] methodPtrTable; + private MethodImplRow[] methodImplTable; + private MethodSemanticsRow[] methodSemanticsTable; + private MethodSpecRow[] methodSpecTable; + private ModuleRow[] moduleTable; + private ModuleRefRow[] moduleRefTable; + private NestedClassRow[] nestedClassTable; + private ParamRow[] paramTable; + private ParamPtrRow[] paramPtrTable; + private PropertyRow[] propertyTable; + private PropertyMapRow[] propertyMapTable; + private PropertyPtrRow[] propertyPtrTable; + private StandAloneSigRow[] standAloneSigTable; + private TypeDefRow[] typeDefTable; + private TypeRefRow[] typeRefTable; + private TypeSpecRow[] typeSpecTable; + + internal AssemblyRow[]/*!*/ AssemblyTable + { + get { if (this.assemblyTable == null) this.ReadAssemblyTable(); return this.assemblyTable; } + } + internal AssemblyRefRow[]/*!*/ AssemblyRefTable + { + get { if (this.assemblyRefTable == null) this.ReadAssemblyRefTable(); return this.assemblyRefTable; } + } + internal ClassLayoutRow[]/*!*/ ClassLayoutTable + { + get { if (this.classLayoutTable == null) this.ReadClassLayoutTable(); return this.classLayoutTable; } + } + internal ConstantRow[]/*!*/ ConstantTable + { + get { if (this.constantTable == null) this.ReadConstantTable(); return this.constantTable; } + } + internal CustomAttributeRow[]/*!*/ CustomAttributeTable + { + get { if (this.customAttributeTable == null) this.ReadCustomAttributeTable(); return this.customAttributeTable; } + } + internal DeclSecurityRow[]/*!*/ DeclSecurityTable + { + get { if (this.declSecurityTable == null) this.ReadDeclSecurityTable(); return this.declSecurityTable; } + } + internal EventMapRow[]/*!*/ EventMapTable + { + get { if (this.eventMapTable == null) this.ReadEventMapTable(); return this.eventMapTable; } + } + internal EventPtrRow[]/*!*/ EventPtrTable + { + get { if (this.eventPtrTable == null) this.ReadEventPtrTable(); return this.eventPtrTable; } + } + internal EventRow[]/*!*/ EventTable + { + get { if (this.eventTable == null) this.ReadEventTable(); return this.eventTable; } + } + internal ExportedTypeRow[]/*!*/ ExportedTypeTable + { + get { if (this.exportedTypeTable == null) this.ReadExportedTypeTable(); return this.exportedTypeTable; } + } + internal FieldRow[]/*!*/ FieldTable + { + get { if (this.fieldTable == null) this.ReadFieldTable(); return this.fieldTable; } + } + internal FieldLayoutRow[]/*!*/ FieldLayoutTable + { + get { if (this.fieldLayoutTable == null) this.ReadFieldLayoutTable(); return this.fieldLayoutTable; } + } + internal FieldMarshalRow[]/*!*/ FieldMarshalTable + { + get { if (this.fieldMarshalTable == null) this.ReadFieldMarshalTable(); return this.fieldMarshalTable; } + } + internal FieldPtrRow[]/*!*/ FieldPtrTable + { + get { if (this.fieldPtrTable == null) this.ReadFieldPtrTable(); return this.fieldPtrTable; } + } + internal FieldRvaRow[]/*!*/ FieldRvaTable + { + get { if (this.fieldRvaTable == null) this.ReadFieldRvaTable(); return this.fieldRvaTable; } + } + internal FileRow[]/*!*/ FileTable + { + get { if (this.fileTable == null) this.ReadFileTable(); return this.fileTable; } + } + internal GenericParamRow[]/*!*/ GenericParamTable + { + get { if (this.genericParamTable == null) this.ReadGenericParamTable(); return this.genericParamTable; } + } + internal GenericParamConstraintRow[]/*!*/ GenericParamConstraintTable + { + get { if (this.genericParamConstraintTable == null) this.ReadGenericParamConstraintTable(); return this.genericParamConstraintTable; } + } + internal ImplMapRow[]/*!*/ ImplMapTable + { + get { if (this.implMapTable == null) this.ReadImplMapTable(); return this.implMapTable; } + } + internal InterfaceImplRow[]/*!*/ InterfaceImplTable + { + get { if (this.interfaceImplTable == null) this.ReadInterfaceImplTable(); return this.interfaceImplTable; } + } + internal ManifestResourceRow[]/*!*/ ManifestResourceTable + { + get { if (this.manifestResourceTable == null) this.ReadManifestResourceTable(); return this.manifestResourceTable; } + } + internal MemberRefRow[]/*!*/ MemberRefTable + { + get { if (this.memberRefTable == null) this.ReadMemberRefTable(); return this.memberRefTable; } + } + internal MethodRow[]/*!*/ MethodTable + { + get { if (this.methodTable == null) this.ReadMethodTable(); return this.methodTable; } + } + internal MethodImplRow[]/*!*/ MethodImplTable + { + get { if (this.methodImplTable == null) this.ReadMethodImplTable(); return this.methodImplTable; } + } + internal MethodPtrRow[]/*!*/ MethodPtrTable + { + get { if (this.methodPtrTable == null) this.ReadMethodPtrTable(); return this.methodPtrTable; } + } + internal MethodSemanticsRow[]/*!*/ MethodSemanticsTable + { + get { if (this.methodSemanticsTable == null) this.ReadMethodSemanticsTable(); return this.methodSemanticsTable; } + } + internal MethodSpecRow[]/*!*/ MethodSpecTable + { + get { if (this.methodSpecTable == null) this.ReadMethodSpecTable(); return this.methodSpecTable; } + } + internal ModuleRow[]/*!*/ ModuleTable + { + get { if (this.moduleTable == null) this.ReadModuleTable(); return this.moduleTable; } + } + internal ModuleRefRow[]/*!*/ ModuleRefTable + { + get { if (this.moduleRefTable == null) this.ReadModuleRefTable(); return this.moduleRefTable; } + } + internal NestedClassRow[]/*!*/ NestedClassTable + { + get { if (this.nestedClassTable == null) this.ReadNestedClassTable(); return this.nestedClassTable; } + } + internal ParamRow[]/*!*/ ParamTable + { + get { if (this.paramTable == null) this.ReadParamTable(); return this.paramTable; } + } + internal ParamPtrRow[]/*!*/ ParamPtrTable + { + get { if (this.paramPtrTable == null) this.ReadParamPtrTable(); return this.paramPtrTable; } + } + internal PropertyRow[]/*!*/ PropertyTable + { + get { if (this.propertyTable == null) this.ReadPropertyTable(); return this.propertyTable; } + } + internal PropertyMapRow[]/*!*/ PropertyMapTable + { + get { if (this.propertyMapTable == null) this.ReadPropertyMapTable(); return this.propertyMapTable; } + } + internal PropertyPtrRow[]/*!*/ PropertyPtrTable + { + get { if (this.propertyPtrTable == null) this.ReadPropertyPtrTable(); return this.propertyPtrTable; } + } + internal StandAloneSigRow[]/*!*/ StandAloneSigTable + { + get { if (this.standAloneSigTable == null) this.ReadStandAloneSigTable(); return this.standAloneSigTable; } + } + internal TypeDefRow[]/*!*/ TypeDefTable + { + get { if (this.typeDefTable == null) this.ReadTypeDefTable(); return this.typeDefTable; } + } + internal TypeRefRow[]/*!*/ TypeRefTable + { + get { if (this.typeRefTable == null) this.ReadTypeRefTable(); return this.typeRefTable; } + } + internal TypeSpecRow[]/*!*/ TypeSpecTable + { + get { if (this.typeSpecTable == null) this.ReadTypeSpecTable(); return this.typeSpecTable; } + } + + internal void SetCurrentPosition(int pos) + { + this.cursor.Position = pos; + } + internal void AlignTo32BitBoundary() + { + this.cursor.Align(4); + } + internal void Skip(int bytes) + { + this.cursor.SkipByte(bytes); + } + internal byte[]/*!*/ GetBlob(int blobIndex) + { + MemoryCursor c = this.cursor; + c.Position = PositionOfBlob(blobIndex); + return c.ReadBytes(c.ReadCompressedInt()); + } + internal MemoryCursor/*!*/ GetBlobCursor(int blobIndex) + { + MemoryCursor c = this.cursor; + c.Position = PositionOfBlob(blobIndex); + c.ReadCompressedInt(); + return new MemoryCursor(c); + } + internal MemoryCursor/*!*/ GetBlobCursor(int blobIndex, out int blobLength) + { + MemoryCursor c = this.cursor; + c.Position = PositionOfBlob(blobIndex); + blobLength = c.ReadCompressedInt(); + return new MemoryCursor(c); + } + internal System.Guid GetGuid(int guidIndex) + //^ requires this.guidHeap != null; + { + int guidOffset = guidIndex * 16; + if (guidOffset < 16 || this.guidHeap.size < guidOffset) + throw new System.ArgumentOutOfRangeException("guidIndex", ExceptionStrings.BadGuidHeapIndex); + MemoryCursor c = this.cursor; + c.Position = this.mdOffset + this.guidHeap.offset + guidOffset - 16; + return new System.Guid(c.ReadBytes(16)); + } + internal Identifier/*!*/ GetIdentifier(int stringHeapIndex) + //^ requires this.identifierStringHeap != null; + { + int position = this.mdOffset + this.identifierStringHeap.offset + stringHeapIndex; + MemoryCursor c = this.cursor; + return Identifier.For(c.GetBuffer(), position/*, c.KeepAlive*/); + } + internal byte GetMethodBodyHeaderByte(int RVA) + { + MemoryCursor c = this.cursor; + c.Position = this.RvaToOffset(RVA); + return c.ReadByte(); + } + internal MemoryCursor/*!*/ GetNewCursor() + { + return new MemoryCursor(this.cursor); + } + internal MemoryCursor/*!*/ GetNewCursor(int RVA, out PESection targetSection) + { + MemoryCursor c = new MemoryCursor(this.cursor); + c.Position = this.RvaToOffset(RVA, out targetSection); + return c; + } + internal byte GetByte() + { + MemoryCursor c = this.cursor; + return c.ReadByte(); + } + internal int GetCurrentPosition() + { + return this.cursor.Position; + } + internal int GetInt32() + { + MemoryCursor c = this.cursor; + return c.ReadInt32(); + } + internal short GetInt16() + { + MemoryCursor c = this.cursor; + return c.ReadInt16(); + } + internal ushort GetUInt16() + { + MemoryCursor c = this.cursor; + return c.ReadUInt16(); + } + internal int GetSignatureLength(int blobIndex) + { + MemoryCursor c = this.cursor; + c.Position = this.PositionOfBlob(blobIndex); + return c.ReadCompressedInt(); + } + internal string/*!*/ GetString(int stringHeapIndex) + //^ requires this.identifierStringHeap != null; + { + if (stringHeapIndex < 0 || this.identifierStringHeap.size <= stringHeapIndex) + throw new System.ArgumentOutOfRangeException("stringHeapIndex", ExceptionStrings.BadStringHeapIndex); + MemoryCursor c = this.cursor; + c.Position = this.mdOffset + this.identifierStringHeap.offset + stringHeapIndex; + return c.ReadUTF8(); + } + internal string/*!*/ GetUserString(int stringHeapIndex) + //^ requires this.generalStringHeap != null; + { + if (stringHeapIndex < 0 || this.generalStringHeap.size <= stringHeapIndex) + throw new System.ArgumentOutOfRangeException("stringHeapIndex", ExceptionStrings.BadUserStringHeapIndex); + MemoryCursor c = this.cursor; + c.Position = this.mdOffset + this.generalStringHeap.offset + stringHeapIndex; + int strLength = c.ReadCompressedInt(); + return c.ReadUTF16(strLength / 2); + } + internal string/*!*/ GetBlobString(int blobIndex) + { + MemoryCursor c = this.cursor; + c.Position = this.PositionOfBlob(blobIndex); + int blobLength = c.ReadCompressedInt(); + return c.ReadUTF16(blobLength / 2); + } + internal object GetValueFromBlob(int type, int blobIndex) + { + MemoryCursor c = this.cursor; + c.Position = this.PositionOfBlob(blobIndex); + int blobLength = c.ReadCompressedInt(); + switch ((ElementType)type) + { + case ElementType.Boolean: return c.ReadBoolean(); + case ElementType.Char: return (char)c.ReadUInt16(); + case ElementType.Double: return c.ReadDouble(); + case ElementType.Single: return c.ReadSingle(); + case ElementType.Int16: return c.ReadInt16(); + case ElementType.Int32: return c.ReadInt32(); + case ElementType.Int64: return c.ReadInt64(); + case ElementType.Int8: return c.ReadSByte(); + case ElementType.UInt16: return c.ReadUInt16(); + case ElementType.UInt32: return c.ReadUInt32(); + case ElementType.UInt64: return c.ReadUInt64(); + case ElementType.UInt8: return c.ReadByte(); + case ElementType.Class: return null; + case ElementType.String: return c.ReadUTF16(blobLength / 2); + } + throw new InvalidMetadataException(ExceptionStrings.UnknownConstantType); + } + internal byte[] GetResourceData(int resourceOffset) + { + this.cursor.Position = this.resourcesOffset + resourceOffset; + int length = this.cursor.ReadInt32(); + return this.cursor.ReadBytes(length); + } + private int PositionOfBlob(int blobIndex) + //^ requires this.blobHeap != null; + { + if (blobIndex < 0 || this.blobHeap.size <= blobIndex) + throw new System.ArgumentOutOfRangeException("blobIndex", ExceptionStrings.BadBlobHeapIndex); + return this.mdOffset + this.blobHeap.offset + blobIndex; + } + private void ReadHeader() + { //TODO: break up this method + MemoryCursor c = this.cursor; + c.Position = 0; + + ReadDOSHeader(c); + NTHeader ntHeader = ReadNTHeader(c); + this.linkerMajorVersion = ntHeader.majorLinkerVersion; + this.linkerMinorVersion = ntHeader.minorLinkerVersion; + this.fileAlignment = ntHeader.fileAlignment; + if ((ntHeader.characteristics & 0x2000) != 0) + this.moduleKind = ModuleKindFlags.DynamicallyLinkedLibrary; + else + this.moduleKind = ntHeader.subsystem == 0x3 ? ModuleKindFlags.ConsoleApplication : ModuleKindFlags.WindowsApplication; + + int sectionCount = ntHeader.numberOfSections; + SectionHeader[] sectionHeaders = this.sectionHeaders = new SectionHeader[sectionCount]; + int resourceSectionIndex = -1; + for (int i = 0; i < sectionCount; i++) + { + sectionHeaders[i] = ReadSectionHeader(c); + if (sectionHeaders[i].name == ".rsrc") resourceSectionIndex = i; + } + if (resourceSectionIndex >= 0) + this.win32ResourcesOffset = sectionHeaders[resourceSectionIndex].pointerToRawData; + else + this.win32ResourcesOffset = -1; + + DirectoryEntry de = ntHeader.cliHeaderTable; + int cliHeaderOffset = this.RvaToOffset(de.virtualAddress); + c.Position = cliHeaderOffset; + + CLIHeader cliHeader = ReadCLIHeader(c); + this.entryPointToken = cliHeader.entryPointToken; + if ((cliHeader.flags & 1) != 0) + this.peKind = PEKindFlags.ILonly; + if ((cliHeader.flags & 0x10) != 0) + this.entryPointToken = 0; //Native entry point. Ignore. + switch (ntHeader.machine) + { + case 0x0200: + this.peKind |= PEKindFlags.Requires64bits; + break; + case 0x8664: + this.peKind |= PEKindFlags.Requires64bits | PEKindFlags.AMD; + break; + default: + if (ntHeader.magic == 0x20B) //Optional header magic for PE32+ + this.peKind |= PEKindFlags.Requires64bits; + else if ((cliHeader.flags & 2) != 0) + this.peKind |= PEKindFlags.Requires32bits; + break; + } + this.TrackDebugData = (cliHeader.flags & 0x10000) != 0; + if (cliHeader.resources.size > 0) + this.resourcesOffset = this.RvaToOffset(cliHeader.resources.virtualAddress); + + int snSize = cliHeader.strongNameSignature.size; + if (snSize > 0) + { + long hashOffset = this.RvaToOffset(cliHeader.strongNameSignature.virtualAddress); + c.Position = (int)hashOffset; + this.HashValue = c.ReadBytes(snSize); + bool zeroHash = true; + for (int i = 0; i < snSize; i++) if (this.HashValue[i] != 0) zeroHash = false; + if (zeroHash) this.HashValue = null; //partially signed assembly + } + + long mdOffset = this.mdOffset = this.RvaToOffset(cliHeader.metaData.virtualAddress); + c.Position = (int)mdOffset; + MetadataHeader mdHeader = ReadMetadataHeader(c); + this.targetRuntimeVersion = mdHeader.versionString; + + foreach (StreamHeader sheader in mdHeader.streamHeaders) + { + //^ assume sheader != null; + switch (sheader.name) + { + case "#Strings": this.identifierStringHeap = sheader; continue; + case "#US": this.generalStringHeap = sheader; continue; + case "#Blob": this.blobHeap = sheader; continue; + case "#GUID": this.guidHeap = sheader; continue; + case "#~": this.tables = sheader; continue; + case "#-": this.tables = sheader; continue; + default: continue; + } + } + if (this.tables == null) throw new InvalidMetadataException(ExceptionStrings.NoMetadataStream); + c.Position = (int)(mdOffset + this.tables.offset); + TablesHeader tablesHeader = this.tablesHeader = ReadTablesHeader(c); + this.metadataFormatMajorVersion = tablesHeader.majorVersion; + this.metadataFormatMinorVersion = tablesHeader.minorVersion; + + int[] tableSize = this.tableSize = new int[(int)TableIndices.Count]; + int[] tableRefSize = this.tableRefSize = new int[(int)TableIndices.Count]; + long valid = tablesHeader.maskValid; + int[] countArray = tablesHeader.countArray; + //^ assume countArray != null; + for (int i = 0, j = 0; i < (int)TableIndices.Count; i++) + { + if (valid % 2 == 1) + { + int m = tableSize[i] = countArray[j++]; + tableRefSize[i] = m < 0x10000 ? 2 : 4; + } + else + tableRefSize[i] = 2; + valid /= 2; + } + int blobRefSize = this.blobRefSize = ((tablesHeader.heapSizes & 0x04) == 0 ? 2 : 4); + int constantParentRefSize = this.constantParentRefSize = + tableSize[(int)TableIndices.Param] < 0x4000 && + tableSize[(int)TableIndices.Field] < 0x4000 && + tableSize[(int)TableIndices.Property] < 0x4000 ? 2 : 4; + int customAttributeParentRefSize = 0; + if (this.metadataFormatMajorVersion > 1 || this.metadataFormatMinorVersion > 0) + { + customAttributeParentRefSize = this.customAttributeParentRefSize = + tableSize[(int)TableIndices.Method] < 0x0800 && + tableSize[(int)TableIndices.Field] < 0x0800 && + tableSize[(int)TableIndices.TypeRef] < 0x0800 && + tableSize[(int)TableIndices.TypeDef] < 0x0800 && + tableSize[(int)TableIndices.Param] < 0x0800 && + tableSize[(int)TableIndices.InterfaceImpl] < 0x0800 && + tableSize[(int)TableIndices.MemberRef] < 0x0800 && + tableSize[(int)TableIndices.Module] < 0x0800 && + tableSize[(int)TableIndices.DeclSecurity] < 0x0800 && + tableSize[(int)TableIndices.Property] < 0x0800 && + tableSize[(int)TableIndices.Event] < 0x0800 && + tableSize[(int)TableIndices.StandAloneSig] < 0x0800 && + tableSize[(int)TableIndices.ModuleRef] < 0x0800 && + tableSize[(int)TableIndices.TypeSpec] < 0x0800 && + tableSize[(int)TableIndices.Assembly] < 0x0800 && + tableSize[(int)TableIndices.File] < 0x0800 && + tableSize[(int)TableIndices.ExportedType] < 0x0800 && + tableSize[(int)TableIndices.ManifestResource] < 0x0800 && + tableSize[(int)TableIndices.GenericParam] < 0x0800 && + tableSize[(int)TableIndices.MethodSpec] < 0x0800 && + tableSize[(int)TableIndices.GenericParamConstraint] < 0x0800 ? 2 : 4; + } + else + { + customAttributeParentRefSize = this.customAttributeParentRefSize = + tableSize[(int)TableIndices.Method] < 0x0800 && + tableSize[(int)TableIndices.Field] < 0x0800 && + tableSize[(int)TableIndices.TypeRef] < 0x0800 && + tableSize[(int)TableIndices.TypeDef] < 0x0800 && + tableSize[(int)TableIndices.Param] < 0x0800 && + tableSize[(int)TableIndices.InterfaceImpl] < 0x0800 && + tableSize[(int)TableIndices.MemberRef] < 0x0800 && + tableSize[(int)TableIndices.Module] < 0x0800 && + tableSize[(int)TableIndices.DeclSecurity] < 0x0800 && + tableSize[(int)TableIndices.Property] < 0x0800 && + tableSize[(int)TableIndices.Event] < 0x0800 && + tableSize[(int)TableIndices.StandAloneSig] < 0x0800 && + tableSize[(int)TableIndices.ModuleRef] < 0x0800 && + tableSize[(int)TableIndices.TypeSpec] < 0x0800 && + tableSize[(int)TableIndices.Assembly] < 0x0800 && + tableSize[(int)TableIndices.File] < 0x0800 && + tableSize[(int)TableIndices.ExportedType] < 0x0800 && + tableSize[(int)TableIndices.ManifestResource] < 0x0800 ? 2 : 4; + } + int customAttributeConstructorRefSize = this.customAttributeConstructorRefSize = + tableSize[(int)TableIndices.Method] < 0x2000 && + tableSize[(int)TableIndices.MemberRef] < 0x2000 ? 2 : 4; + int declSecurityParentRefSize = this.declSecurityParentRefSize = + tableSize[(int)TableIndices.TypeDef] < 0x4000 && + tableSize[(int)TableIndices.Method] < 0x4000 && + tableSize[(int)TableIndices.Assembly] < 0x4000 ? 2 : 4; + int fieldMarshalParentRefSize = this.fieldMarshalParentRefSize = + tableSize[(int)TableIndices.Field] < 0x8000 && + tableSize[(int)TableIndices.Param] < 0x8000 ? 2 : 4; + int guidRefSize = this.guidRefSize = ((tablesHeader.heapSizes & 0x02) == 0 ? 2 : 4); + int hasSemanticRefSize = this.hasSemanticRefSize = + tableSize[(int)TableIndices.Event] < 0x8000 && + tableSize[(int)TableIndices.Property] < 0x8000 ? 2 : 4; + int implementationRefSize = this.implementationRefSize = + tableSize[(int)TableIndices.File] < 0x4000 && + tableSize[(int)TableIndices.AssemblyRef] < 0x4000 && + tableSize[(int)TableIndices.ExportedType] < 0x4000 ? 2 : 4; + int methodDefOrRefSize = this.methodDefOrRefSize = + tableSize[(int)TableIndices.Method] < 0x8000 && + tableSize[(int)TableIndices.MemberRef] < 0x8000 ? 2 : 4; + int memberRefParentSize = this.memberRefParentSize = + tableSize[(int)TableIndices.TypeDef] < 0x2000 && + tableSize[(int)TableIndices.TypeRef] < 0x2000 && + tableSize[(int)TableIndices.ModuleRef] < 0x2000 && + tableSize[(int)TableIndices.Method] < 0x2000 && + tableSize[(int)TableIndices.TypeSpec] < 0x2000 ? 2 : 4; + int memberForwardedRefSize = this.memberForwardedRefSize = + tableSize[(int)TableIndices.Field] < 0x8000 && + tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4; + int typeDefOrMethodDefSize = this.typeDefOrMethodDefSize = + tableSize[(int)TableIndices.TypeDef] < 0x8000 && + tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4; + int typeDefOrRefOrSpecSize = this.typeDefOrRefOrSpecSize = + tableSize[(int)TableIndices.TypeDef] < 0x4000 && + tableSize[(int)TableIndices.TypeRef] < 0x4000 && + tableSize[(int)TableIndices.TypeSpec] < 0x4000 ? 2 : 4; + int resolutionScopeRefSize = this.resolutionScopeRefSize = + tableSize[(int)TableIndices.Module] < 0x4000 && + tableSize[(int)TableIndices.ModuleRef] < 0x4000 && + tableSize[(int)TableIndices.AssemblyRef] < 0x4000 && + tableSize[(int)TableIndices.TypeRef] < 0x4000 ? 2 : 4; + int stringRefSize = this.stringRefSize = ((tablesHeader.heapSizes & 0x01) == 0 ? 2 : 4); + + int[] tableOffset = this.tableOffset = new int[(int)TableIndices.Count]; + int offset = this.mdOffset + this.tables.offset + 24 + countArray.Length * 4; + for (int i = 0; i < (int)TableIndices.Count; i++) + { + int m = tableSize[i]; + if (m == 0) continue; + tableOffset[i] = offset; + switch ((TableIndices)i) + { + case TableIndices.Module: offset += m * (2 + stringRefSize + 3 * guidRefSize); break; + case TableIndices.TypeRef: offset += m * (resolutionScopeRefSize + 2 * stringRefSize); break; + case TableIndices.TypeDef: offset += m * (4 + 2 * stringRefSize + typeDefOrRefOrSpecSize + tableRefSize[(int)TableIndices.Field] + tableRefSize[(int)TableIndices.Method]); break; + case TableIndices.FieldPtr: offset += m * (tableRefSize[(int)TableIndices.Field]); break; + case TableIndices.Field: offset += m * (2 + stringRefSize + blobRefSize); break; + case TableIndices.MethodPtr: offset += m * (tableRefSize[(int)TableIndices.Method]); break; + case TableIndices.Method: offset += m * (8 + stringRefSize + blobRefSize + tableRefSize[(int)TableIndices.Param]); break; + case TableIndices.ParamPtr: offset += m * (tableRefSize[(int)TableIndices.Param]); break; + case TableIndices.Param: offset += m * (4 + stringRefSize); break; + case TableIndices.InterfaceImpl: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + typeDefOrRefOrSpecSize); break; + case TableIndices.MemberRef: offset += m * (memberRefParentSize + stringRefSize + blobRefSize); break; + case TableIndices.Constant: offset += m * (2 + constantParentRefSize + blobRefSize); break; + case TableIndices.CustomAttribute: offset += m * (customAttributeParentRefSize + customAttributeConstructorRefSize + blobRefSize); break; + case TableIndices.FieldMarshal: offset += m * (fieldMarshalParentRefSize + blobRefSize); break; + case TableIndices.DeclSecurity: offset += m * (2 + declSecurityParentRefSize + blobRefSize); break; + case TableIndices.ClassLayout: offset += m * (6 + tableRefSize[(int)TableIndices.TypeDef]); break; + case TableIndices.FieldLayout: offset += m * (4 + tableRefSize[(int)TableIndices.Field]); break; + case TableIndices.StandAloneSig: offset += m * (blobRefSize); break; + case TableIndices.EventMap: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Event]); break; + case TableIndices.EventPtr: offset += m * (tableRefSize[(int)TableIndices.Event]); break; + case TableIndices.Event: offset += m * (2 + stringRefSize + typeDefOrRefOrSpecSize); break; + case TableIndices.PropertyMap: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Property]); break; + case TableIndices.PropertyPtr: offset += m * (tableRefSize[(int)TableIndices.Property]); break; + case TableIndices.Property: offset += m * (2 + stringRefSize + blobRefSize); break; + case TableIndices.MethodSemantics: offset += m * (2 + tableRefSize[(int)TableIndices.Method] + hasSemanticRefSize); break; + case TableIndices.MethodImpl: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + 2 * methodDefOrRefSize); break; + case TableIndices.ModuleRef: offset += m * (stringRefSize); break; + case TableIndices.TypeSpec: offset += m * (blobRefSize); break; + case TableIndices.ImplMap: offset += m * (2 + memberForwardedRefSize + stringRefSize + tableRefSize[(int)TableIndices.ModuleRef]); break; + case TableIndices.FieldRva: offset += m * (4 + tableRefSize[(int)TableIndices.Field]); break; + case TableIndices.EncLog: throw new InvalidMetadataException(ExceptionStrings.ENCLogTableEncountered); + case TableIndices.EncMap: throw new InvalidMetadataException(ExceptionStrings.ENCMapTableEncountered); + case TableIndices.Assembly: offset += m * (16 + blobRefSize + 2 * stringRefSize); break; + case TableIndices.AssemblyProcessor: offset += m * (4); break; + case TableIndices.AssemblyOS: offset += m * (12); break; + case TableIndices.AssemblyRef: offset += m * (12 + 2 * blobRefSize + 2 * stringRefSize); break; + case TableIndices.AssemblyRefProcessor: offset += m * (4 + tableRefSize[(int)TableIndices.AssemblyRef]); break; + case TableIndices.AssemblyRefOS: offset += m * (12 + tableRefSize[(int)TableIndices.AssemblyRef]); break; + case TableIndices.File: offset += m * (4 + stringRefSize + blobRefSize); break; + case TableIndices.ExportedType: offset += m * (8 + 2 * stringRefSize + implementationRefSize); break; + case TableIndices.ManifestResource: offset += m * (8 + stringRefSize + implementationRefSize); break; + case TableIndices.NestedClass: offset += m * (2 * tableRefSize[(int)TableIndices.TypeDef]); break; + case TableIndices.GenericParam: + if (this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 0) + offset += m * (6 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize); + else if (this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 1) + offset += m * (4 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize); + else + offset += m * (4 + typeDefOrMethodDefSize + stringRefSize); + break; + case TableIndices.MethodSpec: offset += m * (methodDefOrRefSize + blobRefSize); break; + case TableIndices.GenericParamConstraint: offset += m * (tableRefSize[(int)TableIndices.GenericParam] + typeDefOrRefOrSpecSize); break; + default: throw new InvalidMetadataException(ExceptionStrings.UnsupportedTableEncountered); + } + } + } + internal Win32ResourceList ReadWin32Resources() + { + Win32ResourceList rs = new Win32ResourceList(); + int startPos = this.win32ResourcesOffset; + if (startPos < 0) return rs; + MemoryCursor c = this.cursor; + c.Position = startPos; + int sizeOfTypeDirectory = ReadWin32ResourceDirectoryHeader(c); + for (int i = 0; i < sizeOfTypeDirectory; i++) + { + string TypeName = null; + int TypeID = c.ReadInt32(); + if (TypeID < 0) + { + MemoryCursor nac = new MemoryCursor(c); + nac.Position = startPos + (TypeID & 0x7FFFFFFF); + int strLength = nac.ReadUInt16(); + TypeName = nac.ReadUTF16(strLength); + } + int offset = c.ReadInt32(); + if (offset >= 0) + rs.Add(this.ReadWin32ResourceDataEntry(c, startPos + offset, TypeName, TypeID, null, 0, 0)); + else + { + MemoryCursor nc = new MemoryCursor(c); + nc.Position = startPos + (offset & 0x7FFFFFFF); + int sizeOfNameDirectory = ReadWin32ResourceDirectoryHeader(nc); + for (int j = 0; j < sizeOfNameDirectory; j++) + { + string Name = null; + int ID = nc.ReadInt32(); + if (ID < 0) + { + MemoryCursor nac = new MemoryCursor(c); + int strLength = nac.ReadUInt16(); + Name = nac.ReadUTF16(strLength); + } + offset = nc.ReadInt32(); + if (offset >= 0) + rs.Add(this.ReadWin32ResourceDataEntry(c, startPos + offset, TypeName, TypeID, Name, ID, 0)); + else + { + MemoryCursor lc = new MemoryCursor(c); + lc.Position = startPos + (offset & 0x7FFFFFFF); + int sizeOfLanguageDirectory = ReadWin32ResourceDirectoryHeader(lc); + for (int k = 0; k < sizeOfLanguageDirectory; k++) + { + int LanguageID = lc.ReadInt32(); + offset = lc.ReadInt32(); + rs.Add(this.ReadWin32ResourceDataEntry(c, startPos + offset, TypeName, TypeID, Name, ID, LanguageID)); + } + } + } + } + } + return rs; + } + private static int ReadWin32ResourceDirectoryHeader(MemoryCursor/*!*/ c) + { + c.ReadInt32(); //Characteristics + c.ReadInt32(); //TimeDate stamp + c.ReadInt32(); //Version + int numberOfNamedEntries = c.ReadUInt16(); + int numberOfIdEntries = c.ReadUInt16(); + return numberOfNamedEntries + numberOfIdEntries; + } + private Win32Resource ReadWin32ResourceDataEntry(MemoryCursor/*!*/ c, int position, + string TypeName, int TypeID, string Name, int ID, int LanguageID) + { + Win32Resource rsrc = new Win32Resource(); + rsrc.TypeName = TypeName; + rsrc.TypeId = TypeID; + rsrc.Name = Name; + rsrc.Id = ID; + rsrc.LanguageId = LanguageID; + c = new MemoryCursor(c); + c.Position = position; + int dataRVA = c.ReadInt32(); + int dataSize = c.ReadInt32(); + rsrc.CodePage = c.ReadInt32(); + c.Position = this.RvaToOffset(dataRVA); + rsrc.Data = c.ReadBytes(dataSize); + return rsrc; + } + private void ReadAssemblyTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Assembly]; + AssemblyRow[] result = this.assemblyTable = new AssemblyRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Assembly]; + for (int i = 0; i < n; i++) + { + AssemblyRow row; + row.HashAlgId = c.ReadInt32(); + row.MajorVersion = c.ReadUInt16(); + row.MinorVersion = c.ReadUInt16(); + row.BuildNumber = c.ReadUInt16(); + row.RevisionNumber = c.ReadUInt16(); + row.Flags = c.ReadInt32(); + row.PublicKey = c.ReadReference(this.blobRefSize); + row.Name = c.ReadReference(this.stringRefSize); + row.Culture = c.ReadReference(this.stringRefSize); + result[i] = row; + } + } + private void ReadAssemblyRefTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.AssemblyRef]; + AssemblyRefRow[] result = this.assemblyRefTable = new AssemblyRefRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.AssemblyRef]; + for (int i = 0; i < n; i++) + { + AssemblyRefRow row; + row.MajorVersion = c.ReadUInt16(); + row.MinorVersion = c.ReadUInt16(); + row.BuildNumber = c.ReadUInt16(); + row.RevisionNumber = c.ReadUInt16(); + row.Flags = c.ReadInt32(); + row.PublicKeyOrToken = c.ReadReference(this.blobRefSize); + row.Name = c.ReadReference(this.stringRefSize); + row.Culture = c.ReadReference(this.stringRefSize); + row.HashValue = c.ReadReference(this.blobRefSize); + row.AssemblyReference = null; + result[i] = row; + } + } + private void ReadClassLayoutTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.ClassLayout]; + ClassLayoutRow[] result = this.classLayoutTable = new ClassLayoutRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ClassLayout]; + for (int i = 0; i < n; i++) + { + ClassLayoutRow row; + row.PackingSize = c.ReadUInt16(); + row.ClassSize = c.ReadInt32(); + row.Parent = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + result[i] = row; + } + } + private void ReadConstantTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Constant]; + ConstantRow[] result = this.constantTable = new ConstantRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Constant]; + for (int i = 0; i < n; i++) + { + ConstantRow row; + row.Type = c.ReadByte(); + c.ReadByte(); + row.Parent = c.ReadReference(this.constantParentRefSize); + row.Value = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadCustomAttributeTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.CustomAttribute]; + CustomAttributeRow[] result = this.customAttributeTable = new CustomAttributeRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.CustomAttribute]; + for (int i = 0; i < n; i++) + { + CustomAttributeRow row; + row.Parent = c.ReadReference(this.customAttributeParentRefSize); + row.Constructor = c.ReadReference(this.customAttributeConstructorRefSize); + row.Value = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadDeclSecurityTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.DeclSecurity]; + DeclSecurityRow[] result = this.declSecurityTable = new DeclSecurityRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.DeclSecurity]; + for (int i = 0; i < n; i++) + { + DeclSecurityRow row; + row.Action = c.ReadUInt16(); + row.Parent = c.ReadReference(this.declSecurityParentRefSize); + row.PermissionSet = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadEventMapTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.EventMap]; + EventMapRow[] result = this.eventMapTable = new EventMapRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.EventMap]; + for (int i = 0; i < n; i++) + { + EventMapRow row; + row.Parent = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + row.EventList = c.ReadReference(this.tableRefSize[(int)TableIndices.Event]); + result[i] = row; + } + } + private void ReadEventPtrTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.EventPtr]; + EventPtrRow[] result = this.eventPtrTable = new EventPtrRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.EventPtr]; + for (int i = 0; i < n; i++) + { + EventPtrRow row; + row.Event = c.ReadReference(this.tableRefSize[(int)TableIndices.Event]); + result[i] = row; + } + } + private void ReadEventTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Event]; + EventRow[] result = this.eventTable = new EventRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Event]; + for (int i = 0; i < n; i++) + { + EventRow row; + row.Flags = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + row.EventType = c.ReadReference(this.typeDefOrRefOrSpecSize); + result[i] = row; + } + } + private void ReadExportedTypeTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.ExportedType]; + ExportedTypeRow[] result = this.exportedTypeTable = new ExportedTypeRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ExportedType]; + for (int i = 0; i < n; i++) + { + ExportedTypeRow row; + row.Flags = c.ReadInt32(); + row.TypeDefId = c.ReadInt32(); + row.TypeName = c.ReadReference(this.stringRefSize); + row.TypeNamespace = c.ReadReference(this.stringRefSize); + row.Implementation = c.ReadReference(this.implementationRefSize); + result[i] = row; + } + } + private void ReadFieldTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Field]; + FieldRow[] result = this.fieldTable = new FieldRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Field]; + for (int i = 0; i < n; i++) + { + FieldRow row; + row.Flags = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + row.Signature = c.ReadReference(this.blobRefSize); + row.Field = null; + result[i] = row; + } + } + private void ReadFieldLayoutTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.FieldLayout]; + FieldLayoutRow[] result = this.fieldLayoutTable = new FieldLayoutRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.FieldLayout]; + for (int i = 0; i < n; i++) + { + FieldLayoutRow row; + row.Offset = c.ReadInt32(); + row.Field = c.ReadReference(this.tableRefSize[(int)TableIndices.Field]); + result[i] = row; + } + } + private void ReadFieldMarshalTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.FieldMarshal]; + FieldMarshalRow[] result = this.fieldMarshalTable = new FieldMarshalRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.FieldMarshal]; + for (int i = 0; i < n; i++) + { + FieldMarshalRow row; + row.Parent = c.ReadReference(this.fieldMarshalParentRefSize); + row.NativeType = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadFieldPtrTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.FieldPtr]; + FieldPtrRow[] result = this.fieldPtrTable = new FieldPtrRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.FieldPtr]; + for (int i = 0; i < n; i++) + { + FieldPtrRow row; + row.Field = c.ReadReference(this.tableRefSize[(int)TableIndices.Field]); + result[i] = row; + } + } + private void ReadFieldRvaTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.FieldRva]; + FieldRvaRow[] result = this.fieldRvaTable = new FieldRvaRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.FieldRva]; + for (int i = 0; i < n; i++) + { + FieldRvaRow row; + row.RVA = c.ReadInt32(); + row.Field = c.ReadReference(this.tableRefSize[(int)TableIndices.Field]); + row.TargetSection = 0; //Ignored on reading + result[i] = row; + } + } + private void ReadFileTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.File]; + FileRow[] result = this.fileTable = new FileRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.File]; + for (int i = 0; i < n; i++) + { + FileRow row; + row.Flags = c.ReadInt32(); + row.Name = c.ReadReference(this.stringRefSize); + row.HashValue = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadGenericParamTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.GenericParam]; + GenericParamRow[] result = this.genericParamTable = new GenericParamRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.GenericParam]; + bool reallyOldGenericsFileFormat = this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 0; + bool oldGenericsFileFormat = this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 1; + for (int i = 0; i < n; i++) + { + GenericParamRow row; + row.Number = c.ReadUInt16(); + row.Flags = c.ReadUInt16(); + row.Owner = c.ReadReference(this.typeDefOrMethodDefSize); + row.Name = c.ReadReference(this.stringRefSize); + row.GenericParameter = null; + if (oldGenericsFileFormat) c.ReadReference(this.typeDefOrRefOrSpecSize); + if (reallyOldGenericsFileFormat) c.ReadInt16(); + result[i] = row; + } + } + private void ReadGenericParamConstraintTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.GenericParamConstraint]; + GenericParamConstraintRow[] result = this.genericParamConstraintTable = new GenericParamConstraintRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.GenericParamConstraint]; + for (int i = 0; i < n; i++) + { + GenericParamConstraintRow row; + row.Param = c.ReadReference(this.tableRefSize[(int)TableIndices.GenericParam]); + row.Constraint = c.ReadReference(this.typeDefOrRefOrSpecSize); + result[i] = row; + } + } + private void ReadImplMapTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.ImplMap]; + ImplMapRow[] result = this.implMapTable = new ImplMapRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ImplMap]; + for (int i = 0; i < n; i++) + { + ImplMapRow row; + row.MappingFlags = c.ReadUInt16(); + row.MemberForwarded = c.ReadReference(this.memberForwardedRefSize); + row.ImportName = c.ReadReference(this.stringRefSize); + row.ImportScope = c.ReadReference(this.tableRefSize[(int)TableIndices.ModuleRef]); + result[i] = row; + } + } + private void ReadInterfaceImplTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.InterfaceImpl]; + InterfaceImplRow[] result = this.interfaceImplTable = new InterfaceImplRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.InterfaceImpl]; + for (int i = 0; i < n; i++) + { + InterfaceImplRow row; + row.Class = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + row.Interface = c.ReadReference(this.typeDefOrRefOrSpecSize); + result[i] = row; + } + } + private void ReadManifestResourceTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.ManifestResource]; + ManifestResourceRow[] result = this.manifestResourceTable = new ManifestResourceRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ManifestResource]; + for (int i = 0; i < n; i++) + { + ManifestResourceRow row; + row.Offset = c.ReadInt32(); + row.Flags = c.ReadInt32(); + row.Name = c.ReadReference(this.stringRefSize); + row.Implementation = c.ReadReference(this.implementationRefSize); + result[i] = row; + } + } + private void ReadMemberRefTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.MemberRef]; + MemberRefRow[] result = this.memberRefTable = new MemberRefRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.MemberRef]; + for (int i = 0; i < n; i++) + { + MemberRefRow row; + row.Class = c.ReadReference(this.memberRefParentSize); + row.Name = c.ReadReference(this.stringRefSize); + row.Signature = c.ReadReference(this.blobRefSize); + row.Member = null; + row.VarargTypes = null; + result[i] = row; + } + } + private void ReadMethodTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.Method]; + MethodRow[] result = this.methodTable = new MethodRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Method]; + for (int i = 0; i < n; i++) + { + MethodRow row; + row.RVA = c.ReadInt32(); + row.ImplFlags = c.ReadUInt16(); + row.Flags = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + row.Signature = c.ReadReference(this.blobRefSize); + row.ParamList = c.ReadReference(this.tableRefSize[(int)TableIndices.Param]); + row.Method = null; + result[i] = row; + } + } + private void ReadMethodImplTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.MethodImpl]; + MethodImplRow[] result = this.methodImplTable = new MethodImplRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.MethodImpl]; + for (int i = 0; i < n; i++) + { + MethodImplRow row; + row.Class = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + row.MethodBody = c.ReadReference(this.methodDefOrRefSize); + row.MethodDeclaration = c.ReadReference(this.methodDefOrRefSize); + result[i] = row; + } + } + private void ReadMethodPtrTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.MethodPtr]; + MethodPtrRow[] result = this.methodPtrTable = new MethodPtrRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.MethodPtr]; + for (int i = 0; i < n; i++) + { + MethodPtrRow row; + row.Method = c.ReadReference(this.tableRefSize[(int)TableIndices.Method]); + result[i] = row; + } + } + private void ReadMethodSemanticsTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.MethodSemantics]; + MethodSemanticsRow[] result = this.methodSemanticsTable = new MethodSemanticsRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.MethodSemantics]; + for (int i = 0; i < n; i++) + { + MethodSemanticsRow row; + row.Semantics = c.ReadUInt16(); + row.Method = c.ReadReference(this.tableRefSize[(int)TableIndices.Method]); + row.Association = c.ReadReference(this.hasSemanticRefSize); + result[i] = row; + } + } + private void ReadMethodSpecTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.MethodSpec]; + MethodSpecRow[] result = this.methodSpecTable = new MethodSpecRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.MethodSpec]; + for (int i = 0; i < n; i++) + { + MethodSpecRow row; + row.Method = c.ReadReference(this.methodDefOrRefSize); + row.Instantiation = c.ReadReference(this.blobRefSize); + row.InstantiatedMethod = null; + result[i] = row; + } + } + private void ReadModuleTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Module]; + ModuleRow[] result = this.moduleTable = new ModuleRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Module]; + for (int i = 0; i < n; i++) + { + ModuleRow row; + row.Generation = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + row.Mvid = c.ReadReference(this.guidRefSize); + row.EncId = c.ReadReference(this.guidRefSize); + row.EncBaseId = c.ReadReference(this.guidRefSize); + result[i] = row; + } + } + private void ReadModuleRefTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.ModuleRef]; + ModuleRefRow[] result = this.moduleRefTable = new ModuleRefRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ModuleRef]; + for (int i = 0; i < n; i++) + { + ModuleRefRow row; + row.Name = c.ReadReference(this.stringRefSize); + row.Module = null; + result[i] = row; + } + } + private void ReadNestedClassTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.NestedClass]; + NestedClassRow[] result = this.nestedClassTable = new NestedClassRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.NestedClass]; + for (int i = 0; i < n; i++) + { + NestedClassRow row; + row.NestedClass = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + row.EnclosingClass = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + result[i] = row; + } + } + private void ReadParamTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Param]; + ParamRow[] result = this.paramTable = new ParamRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Param]; + for (int i = 0; i < n; i++) + { + ParamRow row; + row.Flags = c.ReadUInt16(); + row.Sequence = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + result[i] = row; + } + } + private void ReadParamPtrTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.ParamPtr]; + ParamPtrRow[] result = this.paramPtrTable = new ParamPtrRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.ParamPtr]; + for (int i = 0; i < n; i++) + { + ParamPtrRow row; + row.Param = c.ReadReference(this.tableRefSize[(int)TableIndices.Param]); + result[i] = row; + } + } + private void ReadPropertyTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.Property]; + PropertyRow[] result = this.propertyTable = new PropertyRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.Property]; + for (int i = 0; i < n; i++) + { + PropertyRow row; + row.Flags = c.ReadUInt16(); + row.Name = c.ReadReference(this.stringRefSize); + row.Signature = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadPropertyMapTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.PropertyMap]; + PropertyMapRow[] result = this.propertyMapTable = new PropertyMapRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.PropertyMap]; + for (int i = 0; i < n; i++) + { + PropertyMapRow row; + row.Parent = c.ReadReference(this.tableRefSize[(int)TableIndices.TypeDef]); + row.PropertyList = c.ReadReference(this.tableRefSize[(int)TableIndices.Property]); + result[i] = row; + } + } + private void ReadPropertyPtrTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.PropertyPtr]; + PropertyPtrRow[] result = this.propertyPtrTable = new PropertyPtrRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.PropertyPtr]; + for (int i = 0; i < n; i++) + { + PropertyPtrRow row; + row.Property = c.ReadReference(this.tableRefSize[(int)TableIndices.Property]); + result[i] = row; + } + } + private void ReadStandAloneSigTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.StandAloneSig]; + StandAloneSigRow[] result = this.standAloneSigTable = new StandAloneSigRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.StandAloneSig]; + for (int i = 0; i < n; i++) + { + StandAloneSigRow row; + row.Signature = c.ReadReference(this.blobRefSize); + result[i] = row; + } + } + private void ReadTypeDefTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.TypeDef]; + TypeDefRow[] result = this.typeDefTable = new TypeDefRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.TypeDef]; + for (int i = 0; i < n; i++) + { + TypeDefRow row; + row.Flags = c.ReadInt32(); + row.Name = c.ReadReference(this.stringRefSize); + row.Namespace = c.ReadReference(this.stringRefSize); + row.Extends = c.ReadReference(this.typeDefOrRefOrSpecSize); + row.FieldList = c.ReadReference(this.tableRefSize[(int)TableIndices.Field]); + row.MethodList = c.ReadReference(this.tableRefSize[(int)TableIndices.Method]); + row.Type = null; + row.NameKey = 0; + row.NamespaceId = null; + row.NamespaceKey = 0; + result[i] = row; + } + for (int i = 0; i < n; i++) + { + result[i].NameKey = this.GetIdentifier(result[i].Name).UniqueIdKey; + result[i].NamespaceId = this.GetIdentifier(result[i].Namespace); + //^ assume result[i].NamespaceId != null; + result[i].NamespaceKey = result[i].NamespaceId.UniqueIdKey; + } + } + private void ReadTypeRefTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.TypeRef]; + TypeRefRow[] result = this.typeRefTable = new TypeRefRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.TypeRef]; + for (int i = 0; i < n; i++) + { + TypeRefRow row; + row.ResolutionScope = c.ReadReference(this.resolutionScopeRefSize); + row.Name = c.ReadReference(this.stringRefSize); + row.Namespace = c.ReadReference(this.stringRefSize); + row.Type = null; + result[i] = row; + } + } + private void ReadTypeSpecTable() + //^ requires this.tableSize != null; + //^ requires this.tableOffset != null; + { + int n = this.tableSize[(int)TableIndices.TypeSpec]; + TypeSpecRow[] result = this.typeSpecTable = new TypeSpecRow[n]; + if (n == 0) return; + MemoryCursor c = this.cursor; + c.Position = this.tableOffset[(int)TableIndices.TypeSpec]; + for (int i = 0; i < n; i++) + { + TypeSpecRow row; + row.Signature = c.ReadReference(this.blobRefSize); + row.Type = null; + result[i] = row; + } + } + internal int GetOffsetToEndOfSection(int virtualAddress) + { + foreach (SectionHeader section in this.sectionHeaders) + if (virtualAddress >= section.virtualAddress && virtualAddress < section.virtualAddress + section.sizeOfRawData) + return (section.sizeOfRawData - (virtualAddress - section.virtualAddress)); + return -1; + } + internal bool NoOffsetFor(int virtualAddress) + { + foreach (SectionHeader section in this.sectionHeaders) + if (virtualAddress >= section.virtualAddress && virtualAddress < section.virtualAddress + section.sizeOfRawData) + return false; + return true; + } + private int RvaToOffset(int virtualAddress) + { + foreach (SectionHeader section in this.sectionHeaders) + if (virtualAddress >= section.virtualAddress && virtualAddress < section.virtualAddress + section.sizeOfRawData) + return (virtualAddress - section.virtualAddress + section.pointerToRawData); + throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.UnknownVirtualAddress, virtualAddress)); + } + private int RvaToOffset(int virtualAddress, out PESection targetSection) + { + foreach (SectionHeader section in this.sectionHeaders) + if (virtualAddress >= section.virtualAddress && virtualAddress < section.virtualAddress + section.sizeOfRawData) + { + if (section.name == ".tls") targetSection = PESection.TLS; + else if (section.name == ".sdata") targetSection = PESection.SData; + else targetSection = PESection.Text; + return (virtualAddress - section.virtualAddress + section.pointerToRawData); + } + throw new InvalidMetadataException(String.Format( + CultureInfo.CurrentCulture, ExceptionStrings.UnknownVirtualAddress, +virtualAddress)); + } + private static CLIHeader/*!*/ ReadCLIHeader(MemoryCursor/*!*/ c) + { + CLIHeader header = new CLIHeader(); + header.cb = c.Int32(0); c.SkipInt32(1); + header.majorRuntimeVersion = c.UInt16(0); + header.minorRuntimeVersion = c.UInt16(1); c.SkipUInt16(2); + header.metaData = ReadDirectoryEntry(c); + header.flags = c.Int32(0); + header.entryPointToken = c.Int32(1); c.SkipInt32(2); + header.resources = ReadDirectoryEntry(c); + header.strongNameSignature = ReadDirectoryEntry(c); + header.codeManagerTable = ReadDirectoryEntry(c); + header.vtableFixups = ReadDirectoryEntry(c); + header.exportAddressTableJumps = ReadDirectoryEntry(c); + if (header.majorRuntimeVersion < 2) + throw new InvalidMetadataException(ExceptionStrings.BadCLIHeader); + return header; + } + private static DirectoryEntry ReadDirectoryEntry(MemoryCursor/*!*/ c) + { + DirectoryEntry entry = new DirectoryEntry(); + entry.virtualAddress = c.Int32(0); + entry.size = c.Int32(1); c.SkipInt32(2); + return entry; + } + internal static void ReadDOSHeader(MemoryCursor/*!*/ c) + { + c.Position = 0; + int magicNumber = c.UInt16(0); + if (magicNumber != 0x5a4d) throw new InvalidMetadataException(ExceptionStrings.BadMagicNumber); + c.Position = 0x3c; + int ntHeaderOffset = c.Int32(0); + c.Position = ntHeaderOffset; + } + private static MetadataHeader/*!*/ ReadMetadataHeader(MemoryCursor/*!*/ c) + { + MetadataHeader header = new MetadataHeader(); + header.signature = c.ReadInt32(); + if (header.signature != 0x424a5342) + throw new InvalidMetadataException(ExceptionStrings.BadMetadataHeaderSignature); + header.majorVersion = c.ReadUInt16(); + header.minorVersion = c.ReadUInt16(); + header.reserved = c.ReadInt32(); + int len = c.ReadInt32(); + header.versionString = c.ReadASCII(len); + while (len++ % 4 != 0) c.ReadByte(); + header.flags = c.ReadUInt16(); + int n = c.ReadUInt16(); + StreamHeader[] streamHeaders = header.streamHeaders = new StreamHeader[n]; + for (int i = 0; i < n; i++) + streamHeaders[i] = ReadStreamHeader(c); + return header; + } + internal static NTHeader/*!*/ ReadNTHeader(MemoryCursor/*!*/ c) + { + NTHeader header = new NTHeader(); + header.signature = c.ReadInt32(); + header.machine = c.ReadUInt16(); + header.numberOfSections = c.ReadUInt16(); + header.timeDateStamp = c.ReadInt32(); + header.pointerToSymbolTable = c.ReadInt32(); + header.numberOfSymbols = c.ReadInt32(); + header.sizeOfOptionalHeader = c.ReadUInt16(); + header.characteristics = c.ReadUInt16(); + header.magic = c.ReadUInt16(); + header.majorLinkerVersion = c.ReadByte(); + header.minorLinkerVersion = c.ReadByte(); + header.sizeOfCode = c.ReadInt32(); + header.sizeOfInitializedData = c.ReadInt32(); + header.sizeOfUninitializedData = c.ReadInt32(); + header.addressOfEntryPoint = c.ReadInt32(); + header.baseOfCode = c.ReadInt32(); + if (header.magic == 0x10B) + { + header.baseOfData = c.ReadInt32(); + header.imageBase = c.ReadInt32(); + } + else + { + header.baseOfData = 0; + header.imageBase = c.ReadInt64(); + } + header.sectionAlignment = c.ReadInt32(); + header.fileAlignment = c.ReadInt32(); + header.majorOperatingSystemVersion = c.ReadUInt16(); + header.minorOperatingSystemVersion = c.ReadUInt16(); + header.majorImageVersion = c.ReadUInt16(); + header.minorImageVersion = c.ReadUInt16(); + header.majorSubsystemVersion = c.ReadUInt16(); + header.minorSubsystemVersion = c.ReadUInt16(); + header.win32VersionValue = c.ReadInt32(); + header.sizeOfImage = c.ReadInt32(); + header.sizeOfHeaders = c.ReadInt32(); + header.checkSum = c.ReadInt32(); + header.subsystem = c.ReadUInt16(); + header.dllCharacteristics = c.ReadUInt16(); + if (header.magic == 0x10B) + { + header.sizeOfStackReserve = c.ReadInt32(); + header.sizeOfStackCommit = c.ReadInt32(); + header.sizeOfHeapReserve = c.ReadInt32(); + header.sizeOfHeapCommit = c.ReadInt32(); + } + else + { + header.sizeOfStackReserve = c.ReadInt64(); + header.sizeOfStackCommit = c.ReadInt64(); + header.sizeOfHeapReserve = c.ReadInt64(); + header.sizeOfHeapCommit = c.ReadInt64(); + } + header.loaderFlags = c.ReadInt32(); + header.numberOfDataDirectories = c.ReadInt32(); + + // Verify that the header signature and magic number are valid + if (header.signature != 0x00004550 /* "PE\0\0" */) + throw new InvalidMetadataException(ExceptionStrings.BadCOFFHeaderSignature); + if (header.magic != 0x010B && header.magic != 0x020B) + throw new InvalidMetadataException(ExceptionStrings.BadPEHeaderMagicNumber); + + //Read the data directories + header.exportTable = ReadDirectoryEntry(c); + header.importTable = ReadDirectoryEntry(c); + header.resourceTable = ReadDirectoryEntry(c); + header.exceptionTable = ReadDirectoryEntry(c); + header.certificateTable = ReadDirectoryEntry(c); + header.baseRelocationTable = ReadDirectoryEntry(c); + header.debugTable = ReadDirectoryEntry(c); + header.copyrightTable = ReadDirectoryEntry(c); + header.globalPointerTable = ReadDirectoryEntry(c); + header.threadLocalStorageTable = ReadDirectoryEntry(c); + header.loadConfigTable = ReadDirectoryEntry(c); + header.boundImportTable = ReadDirectoryEntry(c); + header.importAddressTable = ReadDirectoryEntry(c); + header.delayImportTable = ReadDirectoryEntry(c); + header.cliHeaderTable = ReadDirectoryEntry(c); + header.reserved = ReadDirectoryEntry(c); + + return header; + } + internal static SectionHeader ReadSectionHeader(MemoryCursor/*!*/ c) + { + SectionHeader header = new SectionHeader(); + header.name = c.ReadASCII(8); + header.virtualSize = c.Int32(0); + header.virtualAddress = c.Int32(1); + header.sizeOfRawData = c.Int32(2); + header.pointerToRawData = c.Int32(3); + header.pointerToRelocations = c.Int32(4); + header.pointerToLinenumbers = c.Int32(5); c.SkipInt32(6); + header.numberOfRelocations = c.UInt16(0); + header.numberOfLinenumbers = c.UInt16(1); c.SkipInt16(2); + header.characteristics = c.Int32(0); c.SkipInt32(1); + return header; + } + private static StreamHeader ReadStreamHeader(MemoryCursor/*!*/ c) + { + StreamHeader header = new StreamHeader(); + header.offset = c.ReadInt32(); + header.size = c.ReadInt32(); + header.name = c.ReadASCII(); + int n = header.name.Length + 1; + c.Position += (4 - (n % 4)) % 4; + return header; + } + private static TablesHeader/*!*/ ReadTablesHeader(MemoryCursor/*!*/ c) + { + TablesHeader header = new TablesHeader(); + header.reserved = c.ReadInt32(); // Must be zero + header.majorVersion = c.ReadByte(); // Must be one + header.minorVersion = c.ReadByte(); // Must be zero + header.heapSizes = c.ReadByte(); // Bits for heap sizes + header.rowId = c.ReadByte(); // log-base-2 of largest rowId + header.maskValid = c.ReadInt64(); // Present table counts + header.maskSorted = c.ReadInt64(); // Sorted tables + int n = 0; + ulong mask = (ulong)header.maskValid; + while (mask != 0) + { + if (mask % 2 == 1) n++; + mask /= 2; + } + int[] countArray = header.countArray = new int[n]; + for (int i = 0; i < n; i++) + countArray[i] = c.ReadInt32(); + return header; + } + } +#if !NoWriter + internal class MetadataWriter + { + internal MemoryStream StringHeap; + internal MemoryStream BlobHeap; + internal MemoryStream UserstringHeap; + internal MemoryStream ResourceDataHeap; + internal MemoryStream SdataHeap; + internal MemoryStream TlsHeap; + internal Guid[] GuidHeap; + internal MemoryStream MethodBodiesHeap; + internal Win32ResourceList Win32Resources; + internal AssemblyRow[] assemblyTable; + internal AssemblyRefRow[] assemblyRefTable; + internal ClassLayoutRow[] classLayoutTable; + internal ConstantRow[] constantTable; + internal CustomAttributeRow[] customAttributeTable; + internal DeclSecurityRow[] declSecurityTable; + internal EventMapRow[] eventMapTable; + internal EventRow[] eventTable; + internal ExportedTypeRow[] exportedTypeTable = null; + internal FieldRow[] fieldTable; + internal FieldLayoutRow[] fieldLayoutTable; + internal FieldMarshalRow[] fieldMarshalTable = null; + internal FieldRvaRow[] fieldRvaTable = null; + internal FileRow[] fileTable; + internal GenericParamRow[] genericParamTable; + internal GenericParamConstraintRow[] genericParamConstraintTable; + internal ImplMapRow[] implMapTable; + internal InterfaceImplRow[] interfaceImplTable; + internal ManifestResourceRow[] manifestResourceTable = null; + internal MemberRefRow[] memberRefTable; + internal MethodRow[] methodTable; + internal MethodImplRow[] methodImplTable; + internal MethodSemanticsRow[] methodSemanticsTable; + internal MethodSpecRow[] methodSpecTable; + internal ModuleRow[] moduleTable; + internal ModuleRefRow[] moduleRefTable; + internal NestedClassRow[] nestedClassTable; + internal ParamRow[] paramTable; + internal PropertyRow[] propertyTable; + internal PropertyMapRow[] propertyMapTable; + internal StandAloneSigRow[] standAloneSigTable; + internal TypeDefRow[] typeDefTable; + internal TypeRefRow[] typeRefTable; + internal TypeSpecRow[] typeSpecTable; + internal int entryPointToken; + internal int fileAlignment; + internal ModuleKindFlags moduleKind; + internal PEKindFlags peKind; + internal bool TrackDebugData; + internal bool UseGenerics = false; + internal byte[] PublicKey; + + private int blobRefSize; + private int constantParentRefSize; + private int customAttributeParentRefSize; + private int customAttributeConstructorRefSize; + private int declSecurityParentRefSize; + private int fieldMarshalParentRefSize; + private int guidRefSize; + private int hasSemanticRefSize; + private int implementationRefSize; + private int methodDefOrRefSize; + private int memberRefParentSize; + private int memberForwardedRefSize; + private int typeDefOrMethodDefSize; + private int typeDefOrRefOrSpecSize; + private int resolutionScopeRefSize; + private int stringRefSize; +#if !ROTOR + private ISymUnmanagedWriter symWriter; +#endif + private int[] tableRefSize; + private int[] tableSize; + private long validMask; + +#if !ROTOR + internal MetadataWriter(ISymUnmanagedWriter symWriter) + { + this.symWriter = symWriter; + } +#else + internal MetadataWriter(){ + } +#endif + + private void SerializeMetadata(BinaryWriter/*!*/ writer, int virtualAddressBase, Fixup/*!*/ sdataFixup, Fixup/*!*/ tlsFixup) + //^ requires this.MethodBodiesHeap != null; + //^ requires this.ResourceDataHeap != null; + //^ requires this.StringHeap != null; + //^ requires this.UserstringHeap != null; + //^ requires this.BlobHeap != null; + //^ requires this.GuidHeap != null; + //^ requires TargetPlatform.TargetRuntimeVersion != null; + { + int tableOffset = 0; + tableOffset += (int)this.MethodBodiesHeap.Length; + this.MethodBodiesHeap.WriteTo(writer.BaseStream); + while (tableOffset % 4 != 0) { writer.Write((byte)0); tableOffset++; } + if (this.PublicKey != null && 0 < this.PublicKey.Length) + { + this.cliHeader.strongNameSignature.virtualAddress = virtualAddressBase + 72 + tableOffset; + int keysize = this.PublicKey.Length - 32; + if (keysize < 128) keysize = 128; + this.cliHeader.strongNameSignature.size = keysize; + tableOffset += keysize; + writer.BaseStream.Position += keysize; + } + if (this.ResourceDataHeap.Length > 0) + { + this.cliHeader.resources.virtualAddress = virtualAddressBase + 72 + tableOffset; + this.ResourceDataHeap.WriteTo(writer.BaseStream); + int sizeOfResources = (int)this.ResourceDataHeap.Length; + while (sizeOfResources % 4 != 0) { writer.Write((byte)0); sizeOfResources++; } + this.cliHeader.resources.size = sizeOfResources; + tableOffset += sizeOfResources; + } + this.cliHeader.metaData.virtualAddress = virtualAddressBase + 72 + tableOffset; + int startPos = (int)writer.BaseStream.Position; + writer.Write((int)0x424a5342); //Magic signature + writer.Write((short)1); //Major version + writer.Write((short)1); //Minor version + writer.Write((int)0); //Reserved + writer.Write((int)12); // version must be 12 chars + char[] version = new char[12]; + char[] aversion = TargetPlatform.TargetRuntimeVersion.ToCharArray(); + Array.Copy(aversion, 0, version, 0, Math.Min(12, aversion.Length)); + writer.Write(version); + writer.Write((short)0); //flags + writer.Write((short)5); //number of streams + int offsetFromStartOfMetadata = 108; + writer.Write((int)offsetFromStartOfMetadata); + int cbStringHeapPad = 0; + offsetFromStartOfMetadata += (int)this.StringHeap.Length; + while (offsetFromStartOfMetadata % 4 != 0) + { + offsetFromStartOfMetadata++; + cbStringHeapPad++; + } + writer.Write((int)this.StringHeap.Length + cbStringHeapPad); + writer.Write(new char[] { '#', 'S', 't', 'r', 'i', 'n', 'g', 's', '\0', '\0', '\0', '\0' }); + + writer.Write((int)offsetFromStartOfMetadata); + offsetFromStartOfMetadata += (int)this.UserstringHeap.Length; + int cbUserStringHeapPad = 0; + while (offsetFromStartOfMetadata % 4 != 0) + { + offsetFromStartOfMetadata++; + cbUserStringHeapPad++; + } + + writer.Write((int)this.UserstringHeap.Length + cbUserStringHeapPad); + writer.Write(new char[] { '#', 'U', 'S', '\0' }); + + writer.Write((int)offsetFromStartOfMetadata); + writer.Write((int)this.BlobHeap.Length); + writer.Write(new char[] { '#', 'B', 'l', 'o', 'b', '\0', '\0', '\0' }); + offsetFromStartOfMetadata += (int)this.BlobHeap.Length; + while (offsetFromStartOfMetadata % 4 != 0) offsetFromStartOfMetadata++; + writer.Write((int)offsetFromStartOfMetadata); + writer.Write((int)this.GuidHeap.Length * 16); + writer.Write(new char[] { '#', 'G', 'U', 'I', 'D', '\0', '\0', '\0' }); + offsetFromStartOfMetadata += this.GuidHeap.Length * 16; + writer.Write((int)offsetFromStartOfMetadata); + int tabsL = this.TablesLength(); + writer.Write((int)tabsL); + writer.Write(new char[] { '#', '~', '\0', '\0' }); + this.StringHeap.WriteTo(writer.BaseStream); + int p = (int)this.StringHeap.Length;// +cbStringHeapPad; + while (p % 4 != 0) { writer.Write((byte)0); p++; } + this.UserstringHeap.WriteTo(writer.BaseStream); + p = (int)this.UserstringHeap.Length;// +cbUserStringHeapPad; + while (p % 4 != 0) { writer.Write((byte)0); p++; } + this.BlobHeap.WriteTo(writer.BaseStream); + p = (int)this.BlobHeap.Length; + while (p % 4 != 0) { writer.Write((byte)0); p++; } + for (int i = 0, n = this.GuidHeap.Length; i < n; i++) + writer.Write(this.GuidHeap[i].ToByteArray()); + this.SerializeTables(writer, virtualAddressBase + 72, sdataFixup, tlsFixup); + this.cliHeader.metaData.size = ((int)writer.BaseStream.Position) - startPos; + } +#if !ROTOR + private unsafe void WriteReferenceToPDBFile(BinaryWriter/*!*/ writer, int virtualAddressBase, int fileBase) + //^ requires this.symWriter != null; + { + int startPos = writer.BaseStream.Position; + this.ntHeader.debugTable.virtualAddress = startPos - fileBase + virtualAddressBase; + this.ntHeader.debugTable.size = 28; + ImageDebugDirectory debugDir = new ImageDebugDirectory(true); + uint pcData = 0; + this.symWriter.GetDebugInfo(ref debugDir, 0, out pcData, IntPtr.Zero); + byte[] data = new byte[pcData]; + fixed (byte* pb = data) + { + this.symWriter.GetDebugInfo(ref debugDir, pcData, out pcData, (IntPtr)pb); + } + writer.Write((int)debugDir.Characteristics); + writer.Write(this.ntHeader.timeDateStamp); + writer.Write((ushort)debugDir.MajorVersion); + writer.Write((ushort)debugDir.MinorVersion); + writer.Write((int)debugDir.Type); + writer.Write((int)debugDir.SizeOfData); + writer.Write((int)startPos + 28 - fileBase + virtualAddressBase); //AddressOfRawData + writer.Write((int)startPos + 28); //PointerToRawData + writer.Write((byte[])data); + } +#endif + private void SerializeTables(BinaryWriter/*!*/ writer, int mbRVAOffset, Fixup/*!*/ sdataFixup, Fixup/*!*/ tlsFixup) + //^ requires this.StringHeap != null; + //^ requires this.GuidHeap != null; + //^ requires this.BlobHeap != null; + //^ requires this.tableSize != null; + //^ requires this.tableRefSize != null; + { + writer.Write((int)0); //Reserved + writer.Write((byte)TargetPlatform.MajorVersion); + writer.Write((byte)TargetPlatform.MinorVersion); + byte heapSizes = 0; + if (this.StringHeap.Length >= 0x10000) heapSizes |= 0x01; + if (this.GuidHeap.Length >= 0x10000) heapSizes |= 0x02; + if (this.BlobHeap.Length >= 0x10000) heapSizes |= 0x04; + writer.Write(heapSizes); + writer.Write((byte)0); //Reserved + writer.Write(this.validMask); //Tables that are present + if (this.UseGenerics) + writer.Write((long)0x16003301fa00); //Tables that are sorted + else + writer.Write((long)0x02003301fa00); //Tables that are sorted + int[] tableSize = this.tableSize; + for (int i = 0, n = 0; i < (int)TableIndices.Count; i++) + if ((n = tableSize[i]) > 0) writer.Write(n); + if (this.moduleTable != null) this.SerializeModuleTable(writer); + if (this.typeRefTable != null) this.SerializeTypeRefTable(writer); + if (this.typeDefTable != null) this.SerializeTypeDefTable(writer); + if (this.fieldTable != null) this.SerializeFieldTable(writer); + if (this.methodTable != null) this.SerializeMethodTable(writer, mbRVAOffset); + if (this.paramTable != null) this.SerializeParamTable(writer); + if (this.interfaceImplTable != null) this.SerializeInterfaceImplTable(writer); + if (this.memberRefTable != null) this.SerializeMemberRefTable(writer); + if (this.constantTable != null) this.SerializeConstantTable(writer); + if (this.customAttributeTable != null) this.SerializeCustomAttributeTable(writer); + if (this.fieldMarshalTable != null) this.SerializeFieldMarshalTable(writer); + if (this.declSecurityTable != null) this.SerializeDeclSecurityTable(writer); + if (this.classLayoutTable != null) this.SerializeClassLayoutTable(writer); + if (this.fieldLayoutTable != null) this.SerializeFieldLayoutTable(writer); + if (this.standAloneSigTable != null) this.SerializeStandAloneSigTable(writer); + if (this.eventMapTable != null) this.SerializeEventMapTable(writer); + if (this.eventTable != null) this.SerializeEventTable(writer); + if (this.propertyMapTable != null) this.SerializePropertyMapTable(writer); + if (this.propertyTable != null) this.SerializePropertyTable(writer); + if (this.methodSemanticsTable != null) this.SerializeMethodSemanticsTable(writer); + if (this.methodImplTable != null) this.SerializeMethodImplTable(writer); + if (this.moduleRefTable != null) this.SerializeModuleRefTable(writer); + if (this.typeSpecTable != null) this.SerializeTypeSpecTable(writer); + if (this.implMapTable != null) this.SerializeImplMapTable(writer); + if (this.fieldRvaTable != null) this.SerializeFieldRvaTable(writer, mbRVAOffset, sdataFixup, tlsFixup); + if (this.assemblyTable != null) this.SerializeAssemblyTable(writer); + if (this.assemblyRefTable != null) this.SerializeAssemblyRefTable(writer); + if (this.fileTable != null) this.SerializeFileTable(writer); + if (this.exportedTypeTable != null) this.SerializeExportedTypeTable(writer); + if (this.manifestResourceTable != null) this.SerializeManifestResourceTable(writer); + if (this.nestedClassTable != null) this.SerializeNestedClassTable(writer); + if (this.genericParamTable != null) this.SerializeGenericParamTable(writer); + if (this.methodSpecTable != null) this.SerializeMethodSpecTable(writer); + if (this.genericParamConstraintTable != null) this.SerializeGenericParamConstraintTable(writer); + } + private void SerializeAssemblyTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.assemblyTable != null; + { + int n = this.tableSize[(int)TableIndices.Assembly]; + for (int i = 0; i < n; i++) + { + AssemblyRow row = this.assemblyTable[i]; + writer.Write((int)row.HashAlgId); + writer.Write((short)row.MajorVersion); + writer.Write((short)row.MinorVersion); + writer.Write((short)row.BuildNumber); + writer.Write((short)row.RevisionNumber); + writer.Write((int)row.Flags); + this.WriteReference(writer, row.PublicKey, this.blobRefSize); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Culture, this.stringRefSize); + } + } + private void SerializeAssemblyRefTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.assemblyRefTable != null; + { + int n = this.tableSize[(int)TableIndices.AssemblyRef]; + for (int i = 0; i < n; i++) + { + AssemblyRefRow row = this.assemblyRefTable[i]; + writer.Write((short)row.MajorVersion); + writer.Write((short)row.MinorVersion); + writer.Write((short)row.BuildNumber); + writer.Write((short)row.RevisionNumber); + writer.Write((int)row.Flags); + this.WriteReference(writer, row.PublicKeyOrToken, this.blobRefSize); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Culture, this.stringRefSize); + this.WriteReference(writer, row.HashValue, this.blobRefSize); + } + } + private void SerializeClassLayoutTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.classLayoutTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.ClassLayout]; + for (int i = 0; i < n; i++) + { + ClassLayoutRow row = this.classLayoutTable[i]; + writer.Write((short)row.PackingSize); + writer.Write((int)row.ClassSize); + this.WriteReference(writer, row.Parent, this.tableRefSize[(int)TableIndices.TypeDef]); + } + } + private void SerializeConstantTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.constantTable != null; + { + int n = this.tableSize[(int)TableIndices.Constant]; + for (int i = 0; i < n; i++) + { + ConstantRow row = this.constantTable[i]; + writer.Write((byte)row.Type); + writer.Write((byte)0); + this.WriteReference(writer, row.Parent, this.constantParentRefSize); + this.WriteReference(writer, row.Value, this.blobRefSize); + } + } + private void SerializeCustomAttributeTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.customAttributeTable != null; + { + int n = this.tableSize[(int)TableIndices.CustomAttribute]; + for (int i = 0; i < n; i++) + { + CustomAttributeRow row = this.customAttributeTable[i]; + this.WriteReference(writer, row.Parent, this.customAttributeParentRefSize); + this.WriteReference(writer, row.Constructor, this.customAttributeConstructorRefSize); + this.WriteReference(writer, row.Value, this.blobRefSize); + } + } + private void SerializeDeclSecurityTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.declSecurityTable != null; + { + int n = this.tableSize[(int)TableIndices.DeclSecurity]; + for (int i = 0; i < n; i++) + { + DeclSecurityRow row = this.declSecurityTable[i]; + writer.Write((short)row.Action); + this.WriteReference(writer, row.Parent, this.declSecurityParentRefSize); + this.WriteReference(writer, row.PermissionSet, this.blobRefSize); + } + } + private void SerializeEventMapTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.eventMapTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.EventMap]; + for (int i = 0; i < n; i++) + { + EventMapRow row = this.eventMapTable[i]; + this.WriteReference(writer, row.Parent, this.tableRefSize[(int)TableIndices.TypeDef]); + this.WriteReference(writer, row.EventList, this.tableRefSize[(int)TableIndices.Event]); + } + } + private void SerializeEventTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.eventTable != null; + { + int n = this.tableSize[(int)TableIndices.Event]; + for (int i = 0; i < n; i++) + { + EventRow row = this.eventTable[i]; + writer.Write((short)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.EventType, this.typeDefOrRefOrSpecSize); + } + } + private void SerializeExportedTypeTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.exportedTypeTable != null; + { + int n = this.tableSize[(int)TableIndices.ExportedType]; + for (int i = 0; i < n; i++) + { + ExportedTypeRow row = this.exportedTypeTable[i]; + writer.Write((int)row.Flags); + writer.Write((int)row.TypeDefId); + this.WriteReference(writer, row.TypeName, this.stringRefSize); + this.WriteReference(writer, row.TypeNamespace, this.stringRefSize); + this.WriteReference(writer, row.Implementation, this.implementationRefSize); + } + } + private void SerializeFieldTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.fieldTable != null; + { + int n = this.tableSize[(int)TableIndices.Field]; + for (int i = 0; i < n; i++) + { + FieldRow row = this.fieldTable[i]; + writer.Write((short)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Signature, this.blobRefSize); + } + } + private void SerializeFieldLayoutTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.fieldLayoutTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.FieldLayout]; + for (int i = 0; i < n; i++) + { + FieldLayoutRow row = this.fieldLayoutTable[i]; + writer.Write((int)row.Offset); + this.WriteReference(writer, row.Field, this.tableRefSize[(int)TableIndices.Field]); + } + } + + private void SerializeFieldMarshalTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.fieldMarshalTable != null; + { + int n = this.tableSize[(int)TableIndices.FieldMarshal]; + for (int i = 0; i < n; i++) + { + FieldMarshalRow row = this.fieldMarshalTable[i]; + this.WriteReference(writer, row.Parent, this.fieldMarshalParentRefSize); + this.WriteReference(writer, row.NativeType, this.blobRefSize); + } + } + private void SerializeFieldRvaTable(BinaryWriter/*!*/ writer, int mbRVAOffset, Fixup/*!*/ sdataFixup, Fixup/*!*/ tlsFixup) + //^ requires this.tableSize != null; + //^ requires this.fieldRvaTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.FieldRva]; + for (int i = 0; i < n; i++) + { + FieldRvaRow row = this.fieldRvaTable[i]; + switch (row.TargetSection) + { + case PESection.SData: + case PESection.TLS: + Fixup fixup = new Fixup(); + fixup.fixupLocation = writer.BaseStream.Position; + fixup.addressOfNextInstruction = row.RVA; + if (row.TargetSection == PESection.SData) + { + sdataFixup.nextFixUp = fixup; + sdataFixup = fixup; + } + else + { + sdataFixup.nextFixUp = fixup; + sdataFixup = fixup; + } + writer.Write((int)0); + break; + case PESection.Text: + writer.Write((int)row.RVA + mbRVAOffset); + break; + } + this.WriteReference(writer, row.Field, this.tableRefSize[(int)TableIndices.Field]); + } + } + private void SerializeFileTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.fileTable != null; + { + int n = this.tableSize[(int)TableIndices.File]; + for (int i = 0; i < n; i++) + { + FileRow row = this.fileTable[i]; + writer.Write((int)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.HashValue, this.blobRefSize); + } + } + private void SerializeGenericParamTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.genericParamTable != null; + { + int n = this.tableSize[(int)TableIndices.GenericParam]; + bool reallyOldGenericsFileFormat = TargetPlatform.MajorVersion == 1 && TargetPlatform.MinorVersion == 0; + bool oldGenericsFileFormat = TargetPlatform.MajorVersion == 1 && TargetPlatform.MinorVersion == 1; + for (int i = 0; i < n; i++) + { + GenericParamRow row = this.genericParamTable[i]; + writer.Write((short)row.Number); + writer.Write((short)row.Flags); + this.WriteReference(writer, row.Owner, this.typeDefOrMethodDefSize); + this.WriteReference(writer, row.Name, this.stringRefSize); + if (oldGenericsFileFormat) this.WriteReference(writer, 0, this.typeDefOrRefOrSpecSize); + if (reallyOldGenericsFileFormat) writer.Write((short)0); + } + } + private void SerializeGenericParamConstraintTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.genericParamConstraintTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.GenericParamConstraint]; + for (int i = 0; i < n; i++) + { + GenericParamConstraintRow row = this.genericParamConstraintTable[i]; + this.WriteReference(writer, row.Param, this.tableRefSize[(int)TableIndices.GenericParam]); + this.WriteReference(writer, row.Constraint, this.typeDefOrRefOrSpecSize); + } + } + private void SerializeImplMapTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.implMapTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.ImplMap]; + for (int i = 0; i < n; i++) + { + ImplMapRow row = this.implMapTable[i]; + writer.Write((short)row.MappingFlags); + this.WriteReference(writer, row.MemberForwarded, this.memberForwardedRefSize); + this.WriteReference(writer, row.ImportName, this.stringRefSize); + this.WriteReference(writer, row.ImportScope, this.tableRefSize[(int)TableIndices.ModuleRef]); + } + } + private void SerializeInterfaceImplTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.interfaceImplTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.InterfaceImpl]; + for (int i = 0; i < n; i++) + { + InterfaceImplRow row = this.interfaceImplTable[i]; + this.WriteReference(writer, row.Class, this.tableRefSize[(int)TableIndices.TypeDef]); + this.WriteReference(writer, row.Interface, this.typeDefOrRefOrSpecSize); + } + } + private void SerializeManifestResourceTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.manifestResourceTable != null; + { + int n = this.tableSize[(int)TableIndices.ManifestResource]; + for (int i = 0; i < n; i++) + { + ManifestResourceRow row = this.manifestResourceTable[i]; + writer.Write((int)row.Offset); + writer.Write((int)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Implementation, this.implementationRefSize); + } + } + private void SerializeMemberRefTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.memberRefTable != null; + { + int n = this.tableSize[(int)TableIndices.MemberRef]; + for (int i = 0; i < n; i++) + { + MemberRefRow row = this.memberRefTable[i]; + this.WriteReference(writer, row.Class, this.memberRefParentSize); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Signature, this.blobRefSize); + } + } + private void SerializeMethodTable(BinaryWriter/*!*/ writer, int mbRVAOffset) + //^ requires this.tableSize != null; + //^ requires this.methodTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.Method]; + int pn = this.paramTable == null ? 1 : this.paramTable.Length + 1; + for (int i = n - 1; i >= 0; i--) + { + MethodRow row = this.methodTable[i]; + if (row.ParamList != 0) pn = row.ParamList; else this.methodTable[i].ParamList = pn; + } + for (int i = 0; i < n; i++) + { + MethodRow row = this.methodTable[i]; + if (row.RVA < 0) + writer.Write((int)0); + else + writer.Write((int)row.RVA + mbRVAOffset); + writer.Write((short)row.ImplFlags); + writer.Write((short)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Signature, this.blobRefSize); + this.WriteReference(writer, row.ParamList, this.tableRefSize[(int)TableIndices.Param]); + } + } + private void SerializeMethodImplTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.methodImplTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.MethodImpl]; + for (int i = 0; i < n; i++) + { + MethodImplRow row = this.methodImplTable[i]; + this.WriteReference(writer, row.Class, this.tableRefSize[(int)TableIndices.TypeDef]); + this.WriteReference(writer, row.MethodBody, this.methodDefOrRefSize); + this.WriteReference(writer, row.MethodDeclaration, this.methodDefOrRefSize); + } + } + private void SerializeMethodSemanticsTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.methodSemanticsTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.MethodSemantics]; + for (int i = 0; i < n; i++) + { + MethodSemanticsRow row = this.methodSemanticsTable[i]; + writer.Write((short)row.Semantics); + this.WriteReference(writer, row.Method, this.tableRefSize[(int)TableIndices.Method]); + this.WriteReference(writer, row.Association, this.hasSemanticRefSize); + } + } + private void SerializeMethodSpecTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.assemblyTable != null; + //^ requires this.methodSpecTable != null; + { + int n = this.tableSize[(int)TableIndices.MethodSpec]; + for (int i = 0; i < n; i++) + { + MethodSpecRow row = this.methodSpecTable[i]; + this.WriteReference(writer, row.Method, this.methodDefOrRefSize); + this.WriteReference(writer, row.Instantiation, this.blobRefSize); + } + } + private void SerializeModuleTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.moduleTable != null; + { + int n = this.tableSize[(int)TableIndices.Module]; + for (int i = 0; i < n; i++) + { + ModuleRow row = this.moduleTable[i]; + writer.Write((short)row.Generation); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Mvid, this.guidRefSize); + this.WriteReference(writer, row.EncId, this.guidRefSize); + this.WriteReference(writer, row.EncBaseId, this.guidRefSize); + } + } + private void SerializeModuleRefTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.moduleRefTable != null; + { + int n = this.tableSize[(int)TableIndices.ModuleRef]; + for (int i = 0; i < n; i++) + { + ModuleRefRow row = this.moduleRefTable[i]; + this.WriteReference(writer, row.Name, this.stringRefSize); + } + } + private void SerializeNestedClassTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.nestedClassTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.NestedClass]; + for (int i = 0; i < n; i++) + { + NestedClassRow row = this.nestedClassTable[i]; + this.WriteReference(writer, row.NestedClass, this.tableRefSize[(int)TableIndices.TypeDef]); + this.WriteReference(writer, row.EnclosingClass, this.tableRefSize[(int)TableIndices.TypeDef]); + } + } + private void SerializeParamTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.paramTable != null; + { + int n = this.tableSize[(int)TableIndices.Param]; + for (int i = 0; i < n; i++) + { + ParamRow row = this.paramTable[i]; + writer.Write((short)row.Flags); + writer.Write((short)row.Sequence); + this.WriteReference(writer, row.Name, this.stringRefSize); + } + } + private void SerializePropertyTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.propertyTable != null; + { + int n = this.tableSize[(int)TableIndices.Property]; + for (int i = 0; i < n; i++) + { + PropertyRow row = this.propertyTable[i]; + writer.Write((short)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Signature, this.blobRefSize); + } + } + private void SerializePropertyMapTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.propertyMapTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.PropertyMap]; + for (int i = 0; i < n; i++) + { + PropertyMapRow row = this.propertyMapTable[i]; + this.WriteReference(writer, row.Parent, this.tableRefSize[(int)TableIndices.TypeDef]); + this.WriteReference(writer, row.PropertyList, this.tableRefSize[(int)TableIndices.Property]); + } + } + private void SerializeStandAloneSigTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.assemblyTable != null; + //^ requires this.standAloneSigTable != null; + { + int n = this.tableSize[(int)TableIndices.StandAloneSig]; + for (int i = 0; i < n; i++) + { + StandAloneSigRow row = this.standAloneSigTable[i]; + this.WriteReference(writer, row.Signature, this.blobRefSize); + } + } + private void SerializeTypeDefTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.typeDefTable != null; + //^ requires this.tableRefSize != null; + { + int n = this.tableSize[(int)TableIndices.TypeDef]; + int fn = this.fieldTable == null ? 1 : this.fieldTable.Length + 1; + int mn = this.methodTable == null ? 1 : this.methodTable.Length + 1; + for (int i = n - 1; i >= 0; i--) + { + TypeDefRow row = this.typeDefTable[i]; + if (row.FieldList != 0) fn = row.FieldList; else this.typeDefTable[i].FieldList = fn; + if (row.MethodList != 0) mn = row.MethodList; else this.typeDefTable[i].MethodList = mn; + } + for (int i = 0; i < n; i++) + { + TypeDefRow row = this.typeDefTable[i]; + writer.Write((int)row.Flags); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Namespace, this.stringRefSize); + this.WriteReference(writer, row.Extends, this.typeDefOrRefOrSpecSize); + this.WriteReference(writer, row.FieldList, this.tableRefSize[(int)TableIndices.Field]); + this.WriteReference(writer, row.MethodList, this.tableRefSize[(int)TableIndices.Method]); + } + } + private void SerializeTypeRefTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.typeRefTable != null; + { + int n = this.tableSize[(int)TableIndices.TypeRef]; + for (int i = 0; i < n; i++) + { + TypeRefRow row = this.typeRefTable[i]; + this.WriteReference(writer, row.ResolutionScope, this.resolutionScopeRefSize); + this.WriteReference(writer, row.Name, this.stringRefSize); + this.WriteReference(writer, row.Namespace, this.stringRefSize); + } + } + private void SerializeTypeSpecTable(BinaryWriter/*!*/ writer) + //^ requires this.tableSize != null; + //^ requires this.typeSpecTable != null; + { + int n = this.tableSize[(int)TableIndices.TypeSpec]; + for (int i = 0; i < n; i++) + { + TypeSpecRow row = this.typeSpecTable[i]; + this.WriteReference(writer, row.Signature, this.blobRefSize); + } + } + private int TablesLength() + //^ requires this.BlobHeap != null; + //^ requires this.GuidHeap != null; + //^ requires this.StringHeap != null; + { + int[] tableSize = this.tableSize = new int[(int)TableIndices.Count]; + int[] tableRefSize = this.tableRefSize = new int[(int)TableIndices.Count]; + int tableCount = 0; + long validMask = 0; + for (int i = 0; i < (int)TableIndices.Count; i++) + { + int j = 0; + switch ((TableIndices)i) + { + case TableIndices.Module: if (this.moduleTable != null) j = this.moduleTable.Length; break; + case TableIndices.TypeRef: if (this.typeRefTable != null) j = this.typeRefTable.Length; break; + case TableIndices.TypeDef: if (this.typeDefTable != null) j = this.typeDefTable.Length; break; + case TableIndices.Field: if (this.fieldTable != null) j = this.fieldTable.Length; break; + case TableIndices.Method: if (this.methodTable != null) j = this.methodTable.Length; break; + case TableIndices.Param: if (this.paramTable != null) j = this.paramTable.Length; break; + case TableIndices.InterfaceImpl: if (this.interfaceImplTable != null) j = this.interfaceImplTable.Length; break; + case TableIndices.MemberRef: if (this.memberRefTable != null) j = this.memberRefTable.Length; break; + case TableIndices.Constant: if (this.constantTable != null) j = this.constantTable.Length; break; + case TableIndices.CustomAttribute: if (this.customAttributeTable != null) j = this.customAttributeTable.Length; break; + case TableIndices.FieldMarshal: if (this.fieldMarshalTable != null) j = this.fieldMarshalTable.Length; break; + case TableIndices.DeclSecurity: if (this.declSecurityTable != null) j = this.declSecurityTable.Length; break; + case TableIndices.ClassLayout: if (this.classLayoutTable != null) j = this.classLayoutTable.Length; break; + case TableIndices.FieldLayout: if (this.fieldLayoutTable != null) j = this.fieldLayoutTable.Length; break; + case TableIndices.StandAloneSig: if (this.standAloneSigTable != null) j = this.standAloneSigTable.Length; break; + case TableIndices.EventMap: if (this.eventMapTable != null) j = this.eventMapTable.Length; break; + case TableIndices.Event: if (this.eventTable != null) j = this.eventTable.Length; break; + case TableIndices.PropertyMap: if (this.propertyMapTable != null) j = this.propertyMapTable.Length; break; + case TableIndices.Property: if (this.propertyTable != null) j = this.propertyTable.Length; break; + case TableIndices.MethodSemantics: if (this.methodSemanticsTable != null) j = this.methodSemanticsTable.Length; break; + case TableIndices.MethodImpl: if (this.methodImplTable != null) j = this.methodImplTable.Length; break; + case TableIndices.ModuleRef: if (this.moduleRefTable != null) j = this.moduleRefTable.Length; break; + case TableIndices.TypeSpec: if (this.typeSpecTable != null) j = this.typeSpecTable.Length; break; + case TableIndices.ImplMap: if (this.implMapTable != null) j = this.implMapTable.Length; break; + case TableIndices.FieldRva: if (this.fieldRvaTable != null) j = this.fieldRvaTable.Length; break; + case TableIndices.Assembly: if (this.assemblyTable != null) j = this.assemblyTable.Length; break; + case TableIndices.AssemblyRef: if (this.assemblyRefTable != null) j = this.assemblyRefTable.Length; break; + case TableIndices.File: if (this.fileTable != null) j = this.fileTable.Length; break; + case TableIndices.ExportedType: if (this.exportedTypeTable != null) j = this.exportedTypeTable.Length; break; + case TableIndices.ManifestResource: if (this.manifestResourceTable != null) j = this.manifestResourceTable.Length; break; + case TableIndices.NestedClass: if (this.nestedClassTable != null) j = this.nestedClassTable.Length; break; + case TableIndices.GenericParam: if (this.genericParamTable != null) j = this.genericParamTable.Length; break; + case TableIndices.MethodSpec: if (this.methodSpecTable != null) j = this.methodSpecTable.Length; break; + case TableIndices.GenericParamConstraint: if (this.genericParamConstraintTable != null) j = this.genericParamConstraintTable.Length; break; + } + tableSize[i] = j; + if (j > 0) + { + tableCount++; + validMask |= 1L << i; + } + } + this.validMask = validMask; + + for (int i = 0; i < (int)TableIndices.Count; i++) + tableRefSize[i] = tableSize[i] < 0x10000 ? 2 : 4; + int blobRefSize = this.blobRefSize = this.BlobHeap.Length < 0x10000 ? 2 : 4; + int constantParentRefSize = this.constantParentRefSize = + tableSize[(int)TableIndices.Param] < 0x4000 && + tableSize[(int)TableIndices.Field] < 0x4000 && + tableSize[(int)TableIndices.Property] < 0x4000 ? 2 : 4; + int customAttributeParentRefSize = this.customAttributeParentRefSize = + tableSize[(int)TableIndices.Method] < 0x0800 && + tableSize[(int)TableIndices.Field] < 0x0800 && + tableSize[(int)TableIndices.TypeRef] < 0x0800 && + tableSize[(int)TableIndices.TypeDef] < 0x0800 && + tableSize[(int)TableIndices.Param] < 0x0800 && + tableSize[(int)TableIndices.InterfaceImpl] < 0x0800 && + tableSize[(int)TableIndices.MemberRef] < 0x0800 && + tableSize[(int)TableIndices.Module] < 0x0800 && + tableSize[(int)TableIndices.DeclSecurity] < 0x0800 && + tableSize[(int)TableIndices.Property] < 0x0800 && + tableSize[(int)TableIndices.Event] < 0x0800 && + tableSize[(int)TableIndices.StandAloneSig] < 0x0800 && + tableSize[(int)TableIndices.ModuleRef] < 0x0800 && + tableSize[(int)TableIndices.TypeSpec] < 0x0800 && + tableSize[(int)TableIndices.Assembly] < 0x0800 && + tableSize[(int)TableIndices.File] < 0x0800 && + tableSize[(int)TableIndices.ExportedType] < 0x0800 && + tableSize[(int)TableIndices.ManifestResource] < 0x0800 && + tableSize[(int)TableIndices.GenericParam] < 0x0800 && + tableSize[(int)TableIndices.MethodSpec] < 0x0800 && + tableSize[(int)TableIndices.GenericParamConstraint] < 0x0800 ? 2 : 4; + int customAttributeConstructorRefSize = this.customAttributeConstructorRefSize = + tableSize[(int)TableIndices.Method] < 0x2000 && + tableSize[(int)TableIndices.MemberRef] < 0x2000 ? 2 : 4; + int declSecurityParentRefSize = this.declSecurityParentRefSize = + tableSize[(int)TableIndices.TypeDef] < 0x4000 && + tableSize[(int)TableIndices.Method] < 0x4000 && + tableSize[(int)TableIndices.Assembly] < 0x4000 ? 2 : 4; + int fieldMarshalParentRefSize = this.fieldMarshalParentRefSize = + tableSize[(int)TableIndices.Field] < 0x8000 && + tableSize[(int)TableIndices.Param] < 0x8000 ? 2 : 4; + int guidRefSize = this.guidRefSize = this.GuidHeap.Length < 0x10000 ? 2 : 4; + int hasSemanticRefSize = this.hasSemanticRefSize = + tableSize[(int)TableIndices.Event] < 0x8000 && + tableSize[(int)TableIndices.Property] < 0x8000 ? 2 : 4; + int implementationRefSize = this.implementationRefSize = + tableSize[(int)TableIndices.File] < 0x4000 && + tableSize[(int)TableIndices.AssemblyRef] < 0x4000 && + tableSize[(int)TableIndices.ExportedType] < 0x4000 ? 2 : 4; + int methodDefOrRefSize = this.methodDefOrRefSize = + tableSize[(int)TableIndices.Method] < 0x8000 && + tableSize[(int)TableIndices.MemberRef] < 0x8000 ? 2 : 4; + int memberRefParentSize = this.memberRefParentSize = + tableSize[(int)TableIndices.TypeDef] < 0x2000 && + tableSize[(int)TableIndices.TypeRef] < 0x2000 && + tableSize[(int)TableIndices.ModuleRef] < 0x2000 && + tableSize[(int)TableIndices.Method] < 0x2000 && + tableSize[(int)TableIndices.TypeSpec] < 0x2000 ? 2 : 4; + int memberForwardedRefSize = this.memberForwardedRefSize = + tableSize[(int)TableIndices.Field] < 0x8000 && + tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4; + int typeDefOrMethodDefSize = this.typeDefOrMethodDefSize = + tableSize[(int)TableIndices.TypeDef] < 0x8000 && + tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4; + int typeDefOrRefOrSpecSize = this.typeDefOrRefOrSpecSize = + tableSize[(int)TableIndices.TypeDef] < 0x4000 && + tableSize[(int)TableIndices.TypeRef] < 0x4000 && + tableSize[(int)TableIndices.TypeSpec] < 0x4000 ? 2 : 4; + int resolutionScopeRefSize = this.resolutionScopeRefSize = + tableSize[(int)TableIndices.Module] < 0x4000 && + tableSize[(int)TableIndices.ModuleRef] < 0x4000 && + tableSize[(int)TableIndices.AssemblyRef] < 0x4000 && + tableSize[(int)TableIndices.TypeRef] < 0x4000 ? 2 : 4; + int stringRefSize = this.stringRefSize = this.StringHeap.Length < 0x10000 ? 2 : 4; + + int length = 0; + for (int i = 0; i < (int)TableIndices.Count; i++) + { + int m = tableSize[i]; + if (m == 0) continue; + switch ((TableIndices)i) + { + case TableIndices.Module: length += m * (2 + stringRefSize + 3 * guidRefSize); break; + case TableIndices.TypeRef: length += m * (resolutionScopeRefSize + 2 * stringRefSize); break; + case TableIndices.TypeDef: length += m * (4 + 2 * stringRefSize + typeDefOrRefOrSpecSize + tableRefSize[(int)TableIndices.Field] + tableRefSize[(int)TableIndices.Method]); break; + case TableIndices.Field: length += m * (2 + stringRefSize + blobRefSize); break; + case TableIndices.Method: length += m * (8 + stringRefSize + blobRefSize + tableRefSize[(int)TableIndices.Param]); break; + case TableIndices.Param: length += m * (4 + stringRefSize); break; + case TableIndices.InterfaceImpl: length += m * (tableRefSize[(int)TableIndices.TypeDef] + typeDefOrRefOrSpecSize); break; + case TableIndices.MemberRef: length += m * (memberRefParentSize + stringRefSize + blobRefSize); break; + case TableIndices.Constant: length += m * (2 + constantParentRefSize + blobRefSize); break; + case TableIndices.CustomAttribute: length += m * (customAttributeParentRefSize + customAttributeConstructorRefSize + blobRefSize); break; + case TableIndices.FieldMarshal: length += m * (fieldMarshalParentRefSize + blobRefSize); break; + case TableIndices.DeclSecurity: length += m * (2 + declSecurityParentRefSize + blobRefSize); break; + case TableIndices.ClassLayout: length += m * (6 + tableRefSize[(int)TableIndices.TypeDef]); break; + case TableIndices.FieldLayout: length += m * (4 + tableRefSize[(int)TableIndices.Field]); break; + case TableIndices.StandAloneSig: length += m * (blobRefSize); break; + case TableIndices.EventMap: length += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Event]); break; + case TableIndices.Event: length += m * (2 + stringRefSize + typeDefOrRefOrSpecSize); break; + case TableIndices.PropertyMap: length += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Property]); break; + case TableIndices.Property: length += m * (2 + stringRefSize + blobRefSize); break; + case TableIndices.MethodSemantics: length += m * (2 + tableRefSize[(int)TableIndices.Method] + hasSemanticRefSize); break; + case TableIndices.MethodImpl: length += m * (tableRefSize[(int)TableIndices.TypeDef] + 2 * methodDefOrRefSize); break; + case TableIndices.ModuleRef: length += m * (stringRefSize); break; + case TableIndices.TypeSpec: length += m * (blobRefSize); break; + case TableIndices.ImplMap: length += m * (2 + memberForwardedRefSize + stringRefSize + tableRefSize[(int)TableIndices.ModuleRef]); break; + case TableIndices.FieldRva: length += m * (4 + tableRefSize[(int)TableIndices.Field]); break; + case TableIndices.EncLog: throw new InvalidMetadataException(ExceptionStrings.ENCLogTableEncountered); + case TableIndices.EncMap: throw new InvalidMetadataException(ExceptionStrings.ENCMapTableEncountered); + case TableIndices.Assembly: length += m * (16 + blobRefSize + 2 * stringRefSize); break; + case TableIndices.AssemblyRef: length += m * (12 + 2 * blobRefSize + 2 * stringRefSize); break; + case TableIndices.File: length += m * (4 + stringRefSize + blobRefSize); break; + case TableIndices.ExportedType: length += m * (8 + 2 * stringRefSize + implementationRefSize); break; + case TableIndices.ManifestResource: length += m * (8 + stringRefSize + implementationRefSize); break; + case TableIndices.NestedClass: length += m * (2 * tableRefSize[(int)TableIndices.TypeDef]); break; + case TableIndices.GenericParam: + if (TargetPlatform.MajorVersion == 1 && TargetPlatform.MinorVersion == 0) + length += m * (6 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize); + else if (TargetPlatform.MajorVersion == 1 && TargetPlatform.MinorVersion == 1) + length += m * (4 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize); + else + length += m * (4 + typeDefOrMethodDefSize + stringRefSize); + break; + case TableIndices.MethodSpec: length += m * (methodDefOrRefSize + blobRefSize); break; + case TableIndices.GenericParamConstraint: length += m * (tableRefSize[(int)TableIndices.GenericParam] + typeDefOrRefOrSpecSize); break; + } + } + length += 24 + (tableCount * 4); + return length; + } + + private NTHeader/*!*/ ntHeader = new NTHeader(); + private CLIHeader/*!*/ cliHeader = new CLIHeader(); + private SectionHeader[] sectionHeaders; + + internal void WritePE(BinaryWriter/*!*/ writer) + //^ requires this.SdataHeap != null; + //^ requires this.TlsHeap != null; + { + this.cliHeader.entryPointToken = this.entryPointToken; + switch (this.moduleKind) + { + case ModuleKindFlags.ConsoleApplication: + this.ntHeader.subsystem = 3; + break; + case ModuleKindFlags.DynamicallyLinkedLibrary: + this.ntHeader.characteristics |= 0x2000; + this.ntHeader.subsystem = 3; + break; + case ModuleKindFlags.WindowsApplication: + this.ntHeader.subsystem = 2; + break; + } + int numSectionHeaders = 2; + if (this.SdataHeap.Length > 0) numSectionHeaders++; + if (this.TlsHeap.Length > 0) numSectionHeaders++; + if (this.Win32Resources != null && this.Win32Resources.Count > 0) numSectionHeaders++; + this.sectionHeaders = new SectionHeader[numSectionHeaders]; + this.ntHeader.numberOfSections = (ushort)numSectionHeaders; + this.ntHeader.timeDateStamp = (int)((DateTime.Now.ToUniversalTime() - NineteenSeventy).TotalSeconds); + + //Write out .text section for meta data tables, method bodies, address tables and entry point stub + Fixup sdataFixup = new Fixup(); + Fixup tlsFixup = new Fixup(); + SectionHeader textSection = new SectionHeader(); + textSection.name = ".text"; + textSection.virtualAddress = 8192; + int sizeOfPeHeaders = 376 + 40 * numSectionHeaders; + textSection.pointerToRawData = ((int)Math.Ceiling(sizeOfPeHeaders / (double)this.fileAlignment)) * this.fileAlignment; + textSection.characteristics = 0x60000020; + writer.BaseStream.Position = textSection.pointerToRawData + 72; //Leave 72 bytes for CLI header + this.SerializeMetadata(writer, textSection.virtualAddress, sdataFixup, tlsFixup); + int RVAofEntryPointJumpTarget = this.WriteImportTableAndEntryPointStub(writer, ref textSection); +#if !ROTOR + if (this.symWriter != null) this.WriteReferenceToPDBFile(writer, textSection.virtualAddress, textSection.pointerToRawData); +#endif + int len = textSection.virtualSize = ((int)writer.BaseStream.Position) - textSection.pointerToRawData; + textSection.sizeOfRawData = ((int)Math.Ceiling(len / (double)this.fileAlignment)) * this.fileAlignment; + this.sectionHeaders[0] = textSection; + writer.BaseStream.Position = textSection.pointerToRawData; + this.ntHeader.cliHeaderTable.virtualAddress = textSection.virtualAddress; + this.ntHeader.cliHeaderTable.size = 72; + WriteCLIHeader(writer); //Write CLI header last so that forward pointers can be filled in first + + int sectionHeaderIndex = 1; + SectionHeader previousSection = textSection; + int n = this.ntHeader.sectionAlignment; + int m = this.fileAlignment; + + if (this.SdataHeap.Length > 0) + { + SectionHeader sdataSection = new SectionHeader(); + sdataSection.name = ".sdata"; + int vaddr = sdataSection.virtualAddress = previousSection.virtualAddress + n * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)n); + sdataSection.virtualSize = this.SdataHeap.Length; + sdataSection.pointerToRawData = previousSection.pointerToRawData + m * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)m); + sdataSection.characteristics = unchecked((int)0xC0000040); + writer.BaseStream.Position = sdataSection.pointerToRawData; + this.SdataHeap.WriteTo(writer.BaseStream); + len = sdataSection.virtualSize = ((int)writer.BaseStream.Position) - sdataSection.pointerToRawData; + writer.BaseStream.Position += m - (len % this.fileAlignment) - 1; + writer.Write((byte)0); + sdataSection.sizeOfRawData = ((int)Math.Ceiling(len / (double)this.fileAlignment)) * this.fileAlignment; + sdataFixup = sdataFixup.nextFixUp; //Skip over dummy header + while (sdataFixup != null) + { + writer.BaseStream.Position = sdataFixup.fixupLocation; + writer.Write((int)(vaddr + sdataFixup.addressOfNextInstruction)); + sdataFixup = sdataFixup.nextFixUp; + } + this.sectionHeaders[sectionHeaderIndex++] = sdataSection; + previousSection = sdataSection; + } + + if (this.TlsHeap.Length > 0) + { + SectionHeader tlsSection = new SectionHeader(); + tlsSection.name = ".tls"; + int vaddr = tlsSection.virtualAddress = previousSection.virtualAddress + n * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)n); + tlsSection.virtualSize = this.SdataHeap.Length; + tlsSection.pointerToRawData = previousSection.pointerToRawData + m * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)m); + tlsSection.characteristics = unchecked((int)0xC0000040); + writer.BaseStream.Position = tlsSection.pointerToRawData; + this.TlsHeap.WriteTo(writer.BaseStream); + len = tlsSection.virtualSize = ((int)writer.BaseStream.Position) - tlsSection.pointerToRawData; + writer.BaseStream.Position += m - (len % this.fileAlignment) - 1; + writer.Write((byte)0); + tlsSection.sizeOfRawData = ((int)Math.Ceiling(len / (double)this.fileAlignment)) * this.fileAlignment; + tlsFixup = tlsFixup.nextFixUp; //Skip over dummy header + while (tlsFixup != null) + { + writer.BaseStream.Position = tlsFixup.fixupLocation; + writer.Write((int)(vaddr + tlsFixup.addressOfNextInstruction)); + tlsFixup = tlsFixup.nextFixUp; + } + this.sectionHeaders[sectionHeaderIndex++] = tlsSection; + previousSection = tlsSection; + } + + if (this.Win32Resources != null && this.Win32Resources.Count > 0) + { + SectionHeader rsrcSection = new SectionHeader(); + rsrcSection.name = ".rsrc"; + rsrcSection.virtualAddress = previousSection.virtualAddress + n * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)n); + rsrcSection.pointerToRawData = previousSection.pointerToRawData + m * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)m); + rsrcSection.characteristics = 0x40000040; + writer.BaseStream.Position = rsrcSection.pointerToRawData; + this.WriteWin32Resources(writer, rsrcSection.virtualAddress); + len = rsrcSection.virtualSize = ((int)writer.BaseStream.Position) - rsrcSection.pointerToRawData; + writer.BaseStream.Position += m - (len % this.fileAlignment) - 1; + writer.Write((byte)0); + rsrcSection.sizeOfRawData = ((int)Math.Ceiling(len / (double)this.fileAlignment)) * this.fileAlignment; + this.sectionHeaders[sectionHeaderIndex++] = rsrcSection; + this.ntHeader.resourceTable.virtualAddress = rsrcSection.virtualAddress; + this.ntHeader.resourceTable.size = rsrcSection.virtualSize; + this.ntHeader.sizeOfInitializedData += rsrcSection.sizeOfRawData; + previousSection = rsrcSection; + } + + //Write out .reloc section for entry point stub relocation table + SectionHeader relocSection = new SectionHeader(); + relocSection.name = ".reloc"; + relocSection.virtualAddress = previousSection.virtualAddress + n * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)n); + relocSection.virtualSize = 12; + relocSection.pointerToRawData = previousSection.pointerToRawData + m * (int)Math.Ceiling(previousSection.sizeOfRawData / (double)m); + relocSection.sizeOfRawData = m; + relocSection.characteristics = 0x42000040; + writer.BaseStream.Position = relocSection.pointerToRawData; + writer.Write((int)((RVAofEntryPointJumpTarget / 4096) * 4096)); //Page RVA + writer.Write((int)12); + int offsetWithinPage = RVAofEntryPointJumpTarget % 4096; + short s = (short)(3 << 12 | offsetWithinPage); + writer.Write(s); + writer.Write((short)0); //next chunk's RVA + writer.BaseStream.Position += m - 13; + writer.Write((byte)0); + this.sectionHeaders[sectionHeaderIndex] = relocSection; + this.ntHeader.baseRelocationTable.virtualAddress = relocSection.virtualAddress; + this.ntHeader.baseRelocationTable.size = relocSection.virtualSize; + this.ntHeader.sizeOfInitializedData += relocSection.sizeOfRawData; + + //Write PE headers. Do this last because forward pointers are filled in by preceding code + writer.BaseStream.Position = 0; + writer.Write(dosHeader); + WriteNTHeader(writer); + WriteSectionHeaders(writer); + } + private class Directory + { + internal string Name; + internal int ID; + internal int NumberOfNamedEntries; + internal int NumberOfIdEntries; + internal ArrayList/*!*/ Entries; + internal Directory(string Name, int ID) + { + this.Name = Name; + this.ID = ID; + this.Entries = new ArrayList(); + //^ base(); + } + } + private void WriteWin32Resources(BinaryWriter/*!*/ writer, int virtualAddressBase) + //^ requires this.Win32Resources != null; + { + Win32ResourceList rsrcs = this.Win32Resources; + BinaryWriter dataHeap = new BinaryWriter(new MemoryStream(), System.Text.Encoding.Unicode); + //Construct a tree of array lists to represent the directory and make it easier to compute offsets + Directory TypeDirectory = new Directory("", 0); + Directory NameDirectory = null; + Directory LanguageDirectory = null; + int lastTypeID = int.MinValue; + string lastTypeName = null; + int lastID = int.MinValue; + string lastName = null; + int sizeOfDirectoryTree = 16; + for (int i = 0, n = rsrcs.Count; i < n; i++) + { + Win32Resource r = rsrcs[i]; + bool typeDifferent = (r.TypeId < 0 && r.TypeName != lastTypeName) || r.TypeId > lastTypeID; + if (typeDifferent) + { + lastTypeID = r.TypeId; + lastTypeName = r.TypeName; + if (lastTypeID < 0) TypeDirectory.NumberOfNamedEntries++; else TypeDirectory.NumberOfIdEntries++; + sizeOfDirectoryTree += 24; + TypeDirectory.Entries.Add(NameDirectory = new Directory(lastTypeName, lastTypeID)); + } + //^ assume NameDirectory != null; + if (typeDifferent || (r.Id < 0 && r.Name != lastName) || r.Id > lastID) + { + lastID = r.Id; + lastName = r.Name; + if (lastID < 0) NameDirectory.NumberOfNamedEntries++; else NameDirectory.NumberOfIdEntries++; + sizeOfDirectoryTree += 24; + NameDirectory.Entries.Add(LanguageDirectory = new Directory(lastName, lastID)); + } + //^ assume LanguageDirectory != null; + LanguageDirectory.NumberOfIdEntries++; + sizeOfDirectoryTree += 8; + LanguageDirectory.Entries.Add(r); + continue; + } + this.WriteDirectory(TypeDirectory, writer, 0, 0, sizeOfDirectoryTree, virtualAddressBase, dataHeap); + dataHeap.BaseStream.WriteTo(writer.BaseStream); + } + private void WriteDirectory(Directory/*!*/ directory, BinaryWriter/*!*/ writer, int offset, int level, int sizeOfDirectoryTree, + int virtualAddressBase, BinaryWriter/*!*/ dataHeap) + { + writer.Write((int)0); //Characteristics + writer.Write((int)0); //Timestamp + writer.Write((int)0); //Version + writer.Write((short)directory.NumberOfNamedEntries); + writer.Write((short)directory.NumberOfIdEntries); + int n = directory.Entries.Count; + int k = offset + 16 + n * 8; + for (int i = 0; i < n; i++) + { + int id = int.MinValue; + string name = null; + int nOff = dataHeap.BaseStream.Position + sizeOfDirectoryTree; + int dOff = k; + Directory subDir = directory.Entries[i] as Directory; + if (subDir != null) + { + id = subDir.ID; + name = subDir.Name; + if (level == 0) + k += this.SizeOfDirectory(subDir); + else + k += 16 + 8 * subDir.Entries.Count; + } + else + { + Win32Resource r = (Win32Resource)directory.Entries[i]; + id = level == 0 ? r.TypeId : level == 1 ? r.Id : r.LanguageId; + name = level == 0 ? r.TypeName : level == 1 ? r.Name : null; + dataHeap.Write((int)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataHeap.BaseStream.Position)); + dataHeap.Write((int)r.Data.Length); + dataHeap.Write((int)r.CodePage); + dataHeap.Write((int)0); + dataHeap.Write(r.Data); + } + if (id >= 0) + writer.Write(id); + else + { + if (name == null) name = ""; + writer.Write(((uint)nOff) | 0x80000000); + dataHeap.Write((ushort)name.Length); + dataHeap.Write(name.ToCharArray()); //REVIEW: what happens if the name contains chars that do not fit into a single utf8 code point? + } + if (subDir != null) + writer.Write(((uint)dOff) | 0x80000000); + else + writer.Write(nOff); + } + k = offset + 16 + n * 8; + for (int i = 0; i < n; i++) + { + Directory subDir = directory.Entries[i] as Directory; + if (subDir != null) + { + this.WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataHeap); + if (level == 0) + k += this.SizeOfDirectory(subDir); + else + k += 16 + 8 * subDir.Entries.Count; + } + } + } + private int SizeOfDirectory(Directory/*!*/ directory) + { + int n = directory.Entries.Count; + int size = 16 + 8 * n; + for (int i = 0; i < n; i++) + { + Directory subDir = directory.Entries[i] as Directory; + if (subDir != null) + size += 16 + 8 * subDir.Entries.Count; + } + return size; + } + private static readonly byte[] dosHeader = new byte[]{ + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, + 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, + 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, + 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + static readonly DateTime NineteenSeventy = new DateTime(1970, 1, 1).ToUniversalTime(); + private void WriteNTHeader(BinaryWriter/*!*/ writer) + //^ requires this.sectionHeaders != null; + { + NTHeader ntHeader = this.ntHeader; + writer.Write(ntHeader.signature); + if ((this.peKind & PEKindFlags.Requires64bits) == 0) + { + ntHeader.magic = 0x10B; //PE32 + ntHeader.machine = 0x014c; //I386 + } + else + { + ntHeader.characteristics &= 0xFEFF; //Not 32-bit + ntHeader.characteristics |= 0x0020; //Can handle >2gb addresses + ntHeader.magic = 0x20B; //PE32+ + if ((this.peKind & PEKindFlags.AMD) != 0) + ntHeader.machine = 0x8664; //AMD64 + else + ntHeader.machine = 0x0200; //IA64 + ntHeader.sizeOfOptionalHeader += 16; + } + writer.Write(ntHeader.machine); + writer.Write(ntHeader.numberOfSections); + writer.Write(ntHeader.timeDateStamp); + writer.Write(ntHeader.pointerToSymbolTable); + writer.Write(ntHeader.numberOfSymbols); + writer.Write(ntHeader.sizeOfOptionalHeader); + writer.Write(ntHeader.characteristics); + writer.Write(ntHeader.magic); + writer.Write((byte)TargetPlatform.LinkerMajorVersion); + writer.Write((byte)TargetPlatform.LinkerMinorVersion); + writer.Write(this.sectionHeaders[0].sizeOfRawData); //sizeOfCode + writer.Write(ntHeader.sizeOfInitializedData); + writer.Write(ntHeader.sizeOfUninitializedData); + writer.Write(ntHeader.addressOfEntryPoint); + writer.Write(this.sectionHeaders[0].virtualAddress); //baseOfCode + if (ntHeader.magic == 0x10B) + { + if (this.sectionHeaders.Length > 1) + writer.Write(this.sectionHeaders[1].virtualAddress); //baseOfData + else + writer.Write((int)0); + writer.Write((int)ntHeader.imageBase); + } + else + { + writer.Write(ntHeader.imageBase); + } + writer.Write(ntHeader.sectionAlignment); + writer.Write(this.fileAlignment); + writer.Write(ntHeader.majorOperatingSystemVersion); + writer.Write(ntHeader.minorOperatingSystemVersion); + writer.Write(ntHeader.majorImageVersion); + writer.Write(ntHeader.minorImageVersion); + writer.Write(ntHeader.majorSubsystemVersion); + writer.Write(ntHeader.minorSubsystemVersion); + writer.Write(ntHeader.win32VersionValue); + int sectionPages = (int)(Math.Ceiling(this.sectionHeaders[this.sectionHeaders.Length - 1].virtualSize / + (double)ntHeader.sectionAlignment) * ntHeader.sectionAlignment); + writer.Write(this.sectionHeaders[this.sectionHeaders.Length - 1].virtualAddress + sectionPages); //sizeOfImage + writer.Write(this.sectionHeaders[0].pointerToRawData); //sizeOfHeaders + writer.Write(ntHeader.checkSum); + writer.Write(ntHeader.subsystem); + writer.Write(ntHeader.dllCharacteristics); + if (ntHeader.magic == 0x10B) + { + writer.Write((int)ntHeader.sizeOfStackReserve); + writer.Write((int)ntHeader.sizeOfStackCommit); + writer.Write((int)ntHeader.sizeOfHeapReserve); + writer.Write((int)ntHeader.sizeOfHeapCommit); + } + else + { + writer.Write(ntHeader.sizeOfStackReserve); + writer.Write(ntHeader.sizeOfStackCommit); + writer.Write(ntHeader.sizeOfHeapReserve); + writer.Write(ntHeader.sizeOfHeapCommit); + } + writer.Write(ntHeader.loaderFlags); + writer.Write(ntHeader.numberOfDataDirectories); + writer.Write(ntHeader.exportTable.virtualAddress); + writer.Write(ntHeader.exportTable.size); + writer.Write(ntHeader.importTable.virtualAddress); + writer.Write(ntHeader.importTable.size); + writer.Write(ntHeader.resourceTable.virtualAddress); + writer.Write(ntHeader.resourceTable.size); + writer.Write(ntHeader.exceptionTable.virtualAddress); + writer.Write(ntHeader.exceptionTable.size); + writer.Write(ntHeader.certificateTable.virtualAddress); + writer.Write(ntHeader.certificateTable.size); + writer.Write(ntHeader.baseRelocationTable.virtualAddress); + writer.Write(ntHeader.baseRelocationTable.size); + writer.Write(ntHeader.debugTable.virtualAddress); + writer.Write(ntHeader.debugTable.size); + writer.Write(ntHeader.copyrightTable.virtualAddress); + writer.Write(ntHeader.copyrightTable.size); + writer.Write(ntHeader.globalPointerTable.virtualAddress); + writer.Write(ntHeader.globalPointerTable.size); + writer.Write(ntHeader.threadLocalStorageTable.virtualAddress); + writer.Write(ntHeader.threadLocalStorageTable.size); + writer.Write(ntHeader.loadConfigTable.virtualAddress); + writer.Write(ntHeader.loadConfigTable.size); + writer.Write(ntHeader.boundImportTable.virtualAddress); + writer.Write(ntHeader.boundImportTable.size); + writer.Write(ntHeader.importAddressTable.virtualAddress); + writer.Write(ntHeader.importAddressTable.size); + writer.Write(ntHeader.delayImportTable.virtualAddress); + writer.Write(ntHeader.delayImportTable.size); + writer.Write(ntHeader.cliHeaderTable.virtualAddress); + writer.Write(ntHeader.cliHeaderTable.size); + writer.Write((long)0); + } + private void WriteSectionHeaders(BinaryWriter/*!*/ writer) + //^ requires this.sectionHeaders != null; + { + SectionHeader[] sectionHeaders = this.sectionHeaders; + for (int i = 0, n = this.sectionHeaders.Length; i < n; i++) + { + SectionHeader hdr = sectionHeaders[i]; + //^ assume hdr.name != null; + for (int j = 0, m = hdr.name.Length; j < 8; j++) + if (j < m) writer.Write(hdr.name[j]); else writer.Write((byte)0); + writer.Write(hdr.virtualSize); + writer.Write(hdr.virtualAddress); + writer.Write(hdr.sizeOfRawData); + writer.Write(hdr.pointerToRawData); + writer.Write(hdr.pointerToRelocations); + writer.Write(hdr.pointerToLinenumbers); + writer.Write(hdr.numberOfRelocations); + writer.Write(hdr.numberOfLinenumbers); + writer.Write(hdr.characteristics); + } + } + private void WriteCLIHeader(BinaryWriter/*!*/ writer) + { + CLIHeader hdr = this.cliHeader; + writer.Write(hdr.cb); + writer.Write((ushort)2); + if (this.UseGenerics) + writer.Write((ushort)5); //Violates the ECMA standard (25.3.3 of Partition II), but apparently necessary + else + writer.Write((ushort)0); + writer.Write(hdr.metaData.virtualAddress); + writer.Write(hdr.metaData.size); + if ((this.peKind & PEKindFlags.Requires32bits) != 0) hdr.flags |= 2; + if ((this.peKind & PEKindFlags.ILonly) != 0) hdr.flags |= 1; + if (this.TrackDebugData) hdr.flags |= 0x10000; + writer.Write(hdr.flags); + writer.Write(hdr.entryPointToken); + writer.Write(hdr.resources.virtualAddress); + writer.Write(hdr.resources.size); + writer.Write(hdr.strongNameSignature.virtualAddress); + writer.Write(hdr.strongNameSignature.size); + writer.Write(hdr.codeManagerTable.virtualAddress); + writer.Write(hdr.codeManagerTable.size); + writer.Write(hdr.vtableFixups.virtualAddress); + writer.Write(hdr.vtableFixups.size); + } + private int WriteImportTableAndEntryPointStub(BinaryWriter/*!*/ writer, ref SectionHeader textSection) + { + bool use32bitAddresses = (this.peKind & PEKindFlags.Requires64bits) == 0; + int pos = (int)writer.BaseStream.Position; + while (pos % 4 != 0) { pos++; writer.Write((byte)0); } + int ITrva = textSection.virtualAddress + pos - textSection.pointerToRawData; + int ITLrva = ITrva + 40; + int rvasize = 12; // size of relocation sections + int hintRva = ITLrva + (use32bitAddresses ? 8 : 16); //position of name of entry point in runtime dll + int nameRva = hintRva + 14; // position of name of runtime dll + int ITArva = nameRva + 14 + // size of name of runtime dll + 4 + // size of entry point code 0000ff25 + rvasize; // size of relocation fixup + + this.ntHeader.addressOfEntryPoint = ITArva - rvasize - 2; + this.ntHeader.importTable.virtualAddress = ITrva; + this.ntHeader.importTable.size = this.ntHeader.addressOfEntryPoint - ITrva - 2; + this.ntHeader.importAddressTable.virtualAddress = ITArva; + this.ntHeader.importAddressTable.size = 8; + //Import table + writer.Write((int)ITLrva); + writer.Write((int)0); + writer.Write((int)0); + writer.Write((int)nameRva); + writer.Write((int)ITArva); + writer.BaseStream.Position += 20; + //Import Lookup table + if (use32bitAddresses) + { + writer.Write((int)hintRva); + writer.Write((int)0); + } + else + { + writer.Write((long)hintRva); + writer.Write((long)0); + } + //Hint table + writer.Write((short)0); //Hint + string entryPointName = this.moduleKind == ModuleKindFlags.DynamicallyLinkedLibrary ? "_CorDllMain" : "_CorExeMain"; + foreach (char ch in entryPointName.ToCharArray()) writer.Write((byte)ch); + writer.Write((byte)0); + //name of CLR runtime dll + foreach (char ch in "mscoree.dll".ToCharArray()) writer.Write((byte)ch); + writer.Write((byte)0); + writer.Write((short)0); + //entry point code, consisting of a jump indirect to _CorXXXMain + writer.Write((short)0); //padding so that address to replace is on a word boundary + writer.Write((byte)0xff); + writer.Write((byte)0x25); + writer.Write((int)ITArva + (int)this.ntHeader.imageBase); //REVIEW: is this OK for 64 bit? + writer.Write((int)0); // relocation fixup must be 12 bytes. + writer.Write((int)0); + //Import Address Table + if (use32bitAddresses) + { + writer.Write((int)hintRva); + writer.Write((int)0); + } + else + { + writer.Write((long)hintRva); + writer.Write((long)0); + } + //Return RVA of the target address of the indirect jump at the entry point + return ITArva - rvasize; + } + private void WriteReference(BinaryWriter/*!*/ writer, int index, int refSize) + { + if (refSize == 2) writer.Write((short)index); else writer.Write(index); + } + } +#endif +} |