public void Dispose() { if(this.memmap != null) this.memmap.Dispose(); this.memmap = null; //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 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 = ModuleKind.DynamicallyLinkedLibrary; else this.moduleKind = ntHeader.subsystem == 0x3 ? ModuleKind.ConsoleApplication : ModuleKind.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); } } }
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; }