/// <summary> /// Reads a version resource from an input stream. /// </summary> /// <param name="reader">The input stream.</param> /// <returns>The parsed version resource.</returns> /// <exception cref="FormatException"> /// Occurs when the input stream does not point to a valid version resource. /// </exception> public static VersionInfoResource FromReader(IBinaryStreamReader reader) { uint start = reader.FileOffset; // Read header. var header = VersionTableEntryHeader.FromReader(reader); if (header.Key != VsVersionInfoKey) { throw new FormatException($"Input stream does not point to a {VsVersionInfoKey} entry."); } var result = new VersionInfoResource(); // Read fixed version info. reader.Align(4); result.FixedVersionInfo = FixedVersionInfo.FromReader(reader); // Read children. while (reader.FileOffset - start < header.Length) { reader.Align(4); result.AddEntry(ReadNextEntry(reader)); } return(result); }
public new static CilRawFatMethodBody FromReader(IBinaryStreamReader reader) { var body = new CilRawFatMethodBody { _header = reader.ReadUInt16(), MaxStack = reader.ReadUInt16() }; int codeSize = reader.ReadInt32(); body.LocalVarSigToken = reader.ReadUInt32(); body.Code = reader.ReadBytes(codeSize); if (body.HasSections) { reader.Align(4); CilExtraSection section; do { section = CilExtraSection.FromReader(reader); body.ExtraSections.Add(section); } while (section.HasMoreSections); } return(body); }
/// <summary> /// Reads a raw method body from the given binary input stream using the fat method body format. /// </summary> /// <param name="errorListener">The object responsible for recording parser errors.</param> /// <param name="reader">The binary input stream to read from.</param> /// <returns>The raw method body.</returns> /// <exception cref="FormatException">Occurs when the method header indicates an method body that is not in the /// fat format.</exception> public new static CilRawFatMethodBody FromReader(IErrorListener errorListener, IBinaryStreamReader reader) { ulong fileOffset = reader.Offset; uint rva = reader.Rva; // Read flags. ushort header = reader.ReadUInt16(); var flags = (CilMethodBodyAttributes)(header & 0xFFF); int headerSize = (header >> 12) * sizeof(uint); // Verify this is a fat method body. if ((flags & CilMethodBodyAttributes.Fat) != CilMethodBodyAttributes.Fat) { errorListener.BadImage("Invalid fat CIL method body header."); return(null); } // Read remaining header. ushort maxStack = reader.ReadUInt16(); uint codeSize = reader.ReadUInt32(); uint localVarSigToken = reader.ReadUInt32(); // Move to code. reader.Offset = fileOffset + (ulong)headerSize; // Verify code size. if (reader.Offset + codeSize > reader.StartOffset + reader.Length) { errorListener.BadImage("Invalid fat CIL method body code size."); return(null); } // Read code. var code = new byte[codeSize]; reader.ReadBytes(code, 0, code.Length); // Create body. var body = new CilRawFatMethodBody(flags, maxStack, localVarSigToken, code); body.UpdateOffsets(fileOffset, rva); // Read any extra sections. if (body.HasSections) { reader.Align(4); CilExtraSection section; do { section = CilExtraSection.FromReader(reader); body.ExtraSections.Add(section); } while (section.HasMoreSections); } return(body); }
/// <summary> /// Reads a single metadata stream header from an input stream. /// </summary> /// <param name="reader">The input stream.</param> /// <returns>The header.</returns> public static MetadataStreamHeader FromReader(IBinaryStreamReader reader) { uint offset = reader.ReadUInt32(); uint size = reader.ReadUInt32(); string name = reader.ReadAsciiString(); reader.Align(4); return(new MetadataStreamHeader(offset, size, name)); }
private static VersionTableEntry ReadNextEntry(IBinaryStreamReader reader) { uint start = reader.FileOffset; var header = VersionTableEntryHeader.FromReader(reader); reader.Align(4); return(header.Key switch { VarFileInfo.VarFileInfoKey => VarFileInfo.FromReader(start, header, reader), StringFileInfo.StringFileInfoKey => StringFileInfo.FromReader(start, header, reader), _ => throw new FormatException($"Invalid or unsupported entry {header.Key}.") });
private static KeyValuePair <string, string> ReadEntry(IBinaryStreamReader reader) { uint start = reader.FileOffset; // Read header. var header = VersionTableEntryHeader.FromReader(reader); reader.Align(4); // Read value. var data = new byte[header.ValueLength * sizeof(char)]; int count = reader.ReadBytes(data, 0, data.Length); // Exclude zero terminator. count = Math.Max(count - 2, 0); string value = Encoding.Unicode.GetString(data, 0, count); // Skip any unprocessed bytes. reader.FileOffset = start + header.Length; return(new KeyValuePair <string, string>(header.Key, value)); }
/// <summary> /// Reads a single Var table at the provided input stream. /// </summary> /// <param name="reader">The input stream.</param> /// <returns>The var table.</returns> /// <exception cref="FormatException"> /// Occurs when the input stream does not point to a valid Var table structure. /// </exception> public static VarTable FromReader(IBinaryStreamReader reader) { var header = VersionTableEntryHeader.FromReader(reader); if (header.Key != TranslationKey) { throw new FormatException($"Expected a Var structure but got a {header.Key} structure."); } reader.Align(4); var result = new VarTable(); uint start = reader.FileOffset; while (reader.FileOffset - start < header.ValueLength) { result.Values.Add(reader.ReadUInt32()); } return(result); }
/// <summary> /// Reads a single StringTable structure from the provided input stream. /// </summary> /// <param name="reader">The input stream.</param> /// <returns>The read structure.</returns> public static StringTable FromReader(IBinaryStreamReader reader) { uint start = reader.FileOffset; // Read header. var header = VersionTableEntryHeader.FromReader(reader); if (header.Key.Length != 8 || !uint.TryParse(header.Key, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint rawKey)) { throw new FormatException("Invalid string table language identifier or code page."); } var result = new StringTable((ushort)(rawKey >> 16), (ushort)(rawKey & 0xFFFF)); // Read entries. while (reader.FileOffset - start < header.Length) { reader.Align(4); var entry = ReadEntry(reader); result.Add(entry.Key, entry.Value); } return(result); }