internal MetaDataRoot(ref BinaryReader reader, ref byte[] buf, ulong startPos) { uint i, offset; ulong curPos = startPos; Exception toBeThrown; reader.BaseStream.Seek((long)curPos, SeekOrigin.Begin); m_signature = reader.ReadUInt32(); #if DEBUG0 Console.Write("metadata m_signature: "); Console.Write((char)(m_signature & 0xff)); Console.Write((char)((m_signature & 0xff00) >> 8)); Console.Write((char)((m_signature & 0xff0000) >> 16)); Console.WriteLine((char)((m_signature & 0xff000000) >> 24) + Environment.NewLine); #endif if (m_signature != METADATA_SIGNATURE) { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } m_majorVersion = reader.ReadUInt16(); m_minorVersion = reader.ReadUInt16(); m_extraData = reader.ReadUInt32(); m_versionStrLen = reader.ReadUInt32(); curPos += (ulong)16; m_versionStr = Encoding.ASCII.GetString(buf, (int)curPos, (int)m_versionStrLen); curPos += (ulong)m_versionStrLen; reader.BaseStream.Seek(m_versionStrLen, SeekOrigin.Current); m_flags = reader.ReadByte(); m_pad = reader.ReadByte(); m_numStreams = reader.ReadUInt16(); curPos += (ulong)4; // Read each stream header. m_streamHeaders = new StreamHeader[m_numStreams]; for (i = 0; i < m_numStreams; i++) { m_streamHeaders[i].offset = reader.ReadUInt32(); m_streamHeaders[i].size = reader.ReadUInt32(); curPos += 8; // Read the stream name. m_streamHeaders[i].name = ""; for ( ; ; curPos++) { m_streamHeaders[i].name += (char)buf[curPos]; if (buf[curPos] == '\0') { curPos++; break; } } // Read until the length of the stream name is a multiple of 4. offset = (uint)m_streamHeaders[i].name.Length; for ( ; offset % 4 != 0; curPos++, offset++) { } ; reader.BaseStream.Seek(offset, SeekOrigin.Current); } }
internal NTHeader(ref BinaryReader reader) { Exception toBeThrown; m_PESignature = reader.ReadUInt32(); if (m_PESignature != PE_SIGNATURE) { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } // COFF Header m_Machine = reader.ReadUInt16(); m_NumberOfSections = reader.ReadUInt16(); m_TimeDateStamp = reader.ReadUInt32(); m_PointerToSymbolTable = reader.ReadUInt32(); m_NumberOfSymbols = reader.ReadUInt32(); m_OptionalHeaderSize = reader.ReadUInt16(); m_Characteristics = reader.ReadUInt16(); if (m_OptionalHeaderSize == 0) { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } // Optional Header - Standard fields m_Magic = reader.ReadUInt16(); if (m_Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } m_MajorLinkerVersion = reader.ReadByte(); m_MinorLinkerVersion = reader.ReadByte(); m_CodeSize = reader.ReadUInt32(); m_InitializeDataSize = reader.ReadUInt32(); m_UninitializeDataSize = reader.ReadUInt32(); m_EntryPointRVA = reader.ReadUInt32(); m_BaseOfCode = reader.ReadUInt32(); m_BaseOfData = reader.ReadUInt32(); // Optional Header - NT-specific fields m_ImageBase = reader.ReadUInt32(); m_SectionAlignment = reader.ReadUInt32(); m_FileAlignment = reader.ReadUInt32(); m_MajorOperatingSystemVersion = reader.ReadUInt16(); m_MinorOperatingSystemVersion = reader.ReadUInt16(); m_MajorImageVersion = reader.ReadUInt16(); m_MinorImageVersion = reader.ReadUInt16(); m_MajorSubsystemVersion = reader.ReadUInt16(); m_MinorSubsystemVersion = reader.ReadUInt16(); m_Reserved = reader.ReadUInt32(); m_ImageSize = reader.ReadUInt32(); m_HeaderSize = reader.ReadUInt32(); m_FileCheckSum = reader.ReadUInt32(); m_Subsystem = reader.ReadUInt16(); m_DLLFlags = reader.ReadUInt16(); m_StackReserveSize = reader.ReadUInt32(); m_StackCommitSize = reader.ReadUInt32(); m_HeapReserveSize = reader.ReadUInt32(); m_HeapCommitSize = reader.ReadUInt32(); m_LoaderFlags = reader.ReadUInt32(); m_NumberOfDataDirectories = reader.ReadUInt32(); // The number of data directories in the remainder of the optional header is always 16. if (m_NumberOfDataDirectories != 16) { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } // Optional Header - Data directories m_DataDirectory = new ImageDataDirectory[m_NumberOfDataDirectories]; for (int i = 0; i < m_NumberOfDataDirectories; i++) { m_DataDirectory[i].RVA = reader.ReadUInt32(); m_DataDirectory[i].Size = reader.ReadUInt32(); } }
internal MetaDataRoot m_mdr; // MetaData Root table /********************************************************************************************************************* * 1) Parse the MetaData Root table. * * 2) Initialize the various heaps. * * 3) Initialize "m_oldNameHash", "m_classTree", and "m_freeSpaceList". * * 4) Initialize the various BitArrays. * * 5) Set the total numbers of the elements (types, methods, fields, properties, events, and parameters). *********************************************************************************************************************/ internal MetaData(ref byte[] buf) { int i, ptHeapIndex = -1; Exception toBeThrown; m_buffer = buf; // Ok. Now we can build a reader and a writer over the memory m_buffer. MemoryStream memStream = new MemoryStream(m_buffer); BinaryReader reader = new BinaryReader(memStream); BinaryWriter writer = new BinaryWriter(memStream); AllHeaders all = new AllHeaders(ref reader); NTHeader nth = all.m_ntHeader; SectionHeader[] sh = all.m_sectionHeaders; #if DEBUG0 Console.WriteLine("Runtime Header Data Directory"); Console.WriteLine("rva: " + nth.m_DataDirectory[14].RVA + "; size: " + nth.m_DataDirectory[14].Size + Environment.NewLine); Console.WriteLine("offset to MetaData section: " + (long)(nth.m_DataDirectory[14].RVA + 8)); #endif // Read the RVA of the physical MetaData section from the Runtime Header Data Directory. reader.BaseStream.Seek((long)(nth.m_DataDirectory[14].RVA + 8), SeekOrigin.Begin); m_startPos = reader.ReadUInt64(); // Theoretically, startPos can be 64 bit long, but in practice, 32 bits are enough. // TODO : Check the docs. The following assertion will fail. // Debug.Assert((startPos >> 32) == 0); m_startPos = m_startPos & 0xffffffff; // use the least significant 4 bytes as the offset m_mdr = new MetaDataRoot(ref reader, ref m_buffer, m_startPos); // We need to initialize the #Strings heap and the #Blob heap before dealing with the #~ heap. for (i = 0; i < m_mdr.m_numStreams; i++) { if (m_mdr.m_streamHeaders[i].name.Equals("#Strings\0")) { m_strHeap = new StringHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#Blob\0")) { m_blobHeap = new BlobHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#~\0") || m_mdr.m_streamHeaders[i].name.Equals("#-\0")) { ptHeapIndex = i; } } if (ptHeapIndex != -1) { m_heap = new PTHeap(ref reader, ref writer, ref m_strHeap, m_startPos + m_mdr.m_streamHeaders[ptHeapIndex].offset); } else { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } }