public static int ReadCompressedUnsignedInt(EndianAwareBinaryReader reader, out byte bytesUsed) { byte compressedFirstByte = reader.ReadByte(); const int sevenBitMask = 0x7F; const int fourteenBitmask = 0xBF; const int twentyNineBitMask = 0xDF; bytesUsed = 1; int decompressedResult = 0; if ((compressedFirstByte & sevenBitMask) == compressedFirstByte) { decompressedResult = compressedFirstByte; } else if ((compressedFirstByte & fourteenBitmask) == compressedFirstByte) { byte hiByte = (byte)(compressedFirstByte & 0x3F); byte loByte = reader.ReadByte(); decompressedResult = loByte | hiByte << 8; bytesUsed = 2; } else if ((compressedFirstByte & twentyNineBitMask) == compressedFirstByte) { byte hiWordHiByte = (byte)(compressedFirstByte & 0x1F); byte hiWordLoByte = reader.ReadByte(); byte loWordHiByte = reader.ReadByte(); byte loWordLoByte = reader.ReadByte(); decompressedResult = loWordLoByte | loWordHiByte << 8 | hiWordLoByte << 16 | hiWordHiByte << 24; bytesUsed = 4; } return(decompressedResult); }
internal void Read(EndianAwareBinaryReader reader) { this.imageKind = (PEImageKind)reader.ReadUInt16(); this.lMajor = reader.ReadByte(); this.lMinor = reader.ReadByte(); this.codeSize = reader.ReadUInt32(); this.initializedDataSize = reader.ReadUInt32(); this.uninitializedDataSize = reader.ReadUInt32(); this.entryPointRVA = reader.ReadUInt32(); this.baseOfCode = reader.ReadUInt32(); switch (this.imageKind) { case PEImageKind.x86Image: this.baseOfData = reader.ReadUInt32(); break; case PEImageKind.x64Image: break; case PEImageKind.RomImage: throw new NotImplementedException(); default: throw new BadImageFormatException(); } }
private void ReadNarrow(EndianAwareBinaryReader reader, ICliMetadataRoot metadataRoot, Action <byte[]> bodyBuilder) { var firstByte = reader.ReadByte(); this.codeSize = (byte)((firstByte & 0xFC) >> 2); bodyBuilder(reader.ReadBytes((int)this.CodeSize)); }
/// <summary> /// Loads the header from the reader. /// </summary> /// <param name="reader">The reader.</param> public void Read(EndianAwareBinaryReader reader) { Magic = reader.ReadUInt16(); if (IMAGE_OPTIONAL_HEADER_MAGIC != Magic) { throw new BadImageFormatException(); } MajorLinkerVersion = reader.ReadByte(); MinorLinkerVersion = reader.ReadByte(); SizeOfCode = reader.ReadUInt32(); SizeOfInitializedData = reader.ReadUInt32(); SizeOfUninitializedData = reader.ReadUInt32(); AddressOfEntryPoint = reader.ReadUInt32(); BaseOfCode = reader.ReadUInt32(); BaseOfData = reader.ReadUInt32(); ImageBase = reader.ReadUInt32(); SectionAlignment = reader.ReadUInt32(); FileAlignment = reader.ReadUInt32(); MajorOperatingSystemVersion = reader.ReadUInt16(); MinorOperatingSystemVersion = reader.ReadUInt16(); MajorImageVersion = reader.ReadUInt16(); MinorImageVersion = reader.ReadUInt16(); MajorSubsystemVersion = reader.ReadUInt16(); MinorSubsystemVersion = reader.ReadUInt16(); Win32VersionValue = reader.ReadUInt32(); SizeOfImage = reader.ReadUInt32(); SizeOfHeaders = reader.ReadUInt32(); CheckSum = reader.ReadUInt32(); Subsystem = reader.ReadUInt16(); DllCharacteristics = reader.ReadUInt16(); SizeOfStackReserve = reader.ReadUInt32(); SizeOfStackCommit = reader.ReadUInt32(); SizeOfHeapReserve = reader.ReadUInt32(); SizeOfHeapCommit = reader.ReadUInt32(); LoaderFlags = reader.ReadUInt32(); NumberOfRvaAndSizes = reader.ReadUInt32(); DataDirectory = new ImageDataDirectory[NumberOfRvaAndSizes]; for (int i = 0; i < NumberOfRvaAndSizes; i++) { DataDirectory[i].Read(reader); } }
internal void Read(EndianAwareBinaryReader reader, PEImage sourceImage) { this.offset = reader.ReadUInt32(); this.size = reader.ReadUInt32(); byte[] name = new byte[32]; bool broke = false; int index = 0; for (index = 0; index < name.Length; index++) { name[index] = reader.ReadByte(); if (name[index] == '\0') { broke = true; index++; break; } } if (broke) { int remainder = index & 3; // aka: index % 4 int bytesRemaining = 4 - remainder; if (remainder > 0) { for (int i = 0; i < bytesRemaining; i++) { reader.ReadByte(); } int paddedLength = index + bytesRemaining; this.name = new byte[paddedLength]; Array.ConstrainedCopy(name, 0, this.name, 0, paddedLength); } else { this.name = new byte[index]; Array.ConstrainedCopy(name, 0, this.name, 0, index); } } else { this.name = name; } }
public static TypeHeader Deserialize(EndianAwareBinaryReader reader) { var typeId = reader.ReadInt32(); var typeName = Util.ReadLengthPrefixedString(reader); var containsExtraDataByte = reader.ReadByte(); var instanceCount = reader.ReadInt32(); var referentArray = Util.ReadReferentArray(reader, instanceCount); var extraData = (containsExtraDataByte != 0) ? reader.ReadBytes(instanceCount) : null; return(new TypeHeader(typeName, typeId, referentArray, extraData)); }
private unsafe bool ReadSubstring(uint index) { lock (this.syncObject) { reader.BaseStream.Position = index; /* * * To save space, smaller strings that exist as the * tail end of another string, are condensed accordingly. * * * It's quicker to construct the strings from the * original source than it is to iterate through the * location table used to quickly look items up. * */ uint loc = index; while (loc < base.Size) { byte current = reader.ReadByte(); if (current == 0) { break; } loc++; } uint size = loc - index; reader.BaseStream.Position = index; byte[] result = new byte[size]; for (int i = 0; i < size; i++) { result[i] = reader.ReadByte(); } this.AddSubstring(ConvertUTF8ByteArray(result), index); return(loc < base.Size); } }
public static Tuple <int, int>[] ReadParentData(EndianAwareBinaryReader reader) // Tuple format is (Child, Parent) { reader.ReadByte(); // Reserved var entryCount = reader.ReadInt32(); var childReferents = ReadReferentArray(reader, entryCount); var parentReferents = ReadReferentArray(reader, entryCount); var pairs = new Tuple <int, int> [entryCount]; for (var i = 0; i < entryCount; i++) { pairs[i] = new Tuple <int, int>(childReferents[i], parentReferents[i]); } return(pairs); }
internal bool ReadEntry() { var tailLength = this.tailLength; if (tailLength + 1 >= this.Size) { return(false); } byte compressedIntBytes = 0; byte[] currentData = null; int currentDataCount = 0; currentDataCount = CliMetadataFixedRoot.ReadCompressedUnsignedInt(reader, out compressedIntBytes); if (tailLength + compressedIntBytes >= this.Size) { reader.BaseStream.Seek(-(tailLength + compressedIntBytes - this.Size), SeekOrigin.Current); return(false); } else { tailLength += compressedIntBytes; } if (currentDataCount == 0) { /* * * Reached the end of the heap which is padded * with zeroes until the next 4-byte boundry. * */ return(false); } if (tailLength + currentDataCount > this.Size) { throw new BadImageFormatException(string.Format("The data within the {0} heap entry is longer than expected.", this.Name)); } currentData = new byte[currentDataCount]; for (int i = 0; i < currentDataCount && tailLength < this.Size; i++, tailLength++) { currentData[i] = reader.ReadByte(); } this.AddData(this.GetData(currentData), compressedIntBytes); if (tailLength >= this.Size) { return(false); } return(true); }
public static PhysicalProperties ReadPhysicalProperties(EndianAwareBinaryReader reader) { var enabled = (reader.ReadByte() != 0); if (enabled) { var density = reader.ReadSingle(); var friction = reader.ReadSingle(); var elasticity = reader.ReadSingle(); var frictionWeight = reader.ReadSingle(); var elasticityWeight = reader.ReadSingle(); return(new PhysicalProperties(density, friction, elasticity, frictionWeight, elasticityWeight)); } else { return(new PhysicalProperties(false)); } }
public static CFrame[] ReadCFrameArray(EndianAwareBinaryReader reader, int count) { var values = new CFrame[count]; var positions = new Vector3[count]; var matrices = new Matrix3[count]; for (var i = 0; i < count; i++) { var specialMatrixType = reader.ReadByte(); if (specialMatrixType == 0) { var r00 = reader.ReadSingle(); var r01 = reader.ReadSingle(); var r02 = reader.ReadSingle(); var r10 = reader.ReadSingle(); var r11 = reader.ReadSingle(); var r12 = reader.ReadSingle(); var r20 = reader.ReadSingle(); var r21 = reader.ReadSingle(); var r22 = reader.ReadSingle(); matrices[i] = new Matrix3(r00, r01, r02, r10, r11, r12, r20, r21, r22); } else { var mat = GetSpecialMatrix(specialMatrixType); matrices[i] = mat; } } var xValues = ReadFloatArray(reader, count); var yValues = ReadFloatArray(reader, count); var zValues = ReadFloatArray(reader, count); for (var i = 0; i < count; i++) { positions[i] = new Vector3(xValues[i], yValues[i], zValues[i]); } for (var i = 0; i < count; i++) { values[i] = new CFrame(positions[i], matrices[i]); } return(values); }
private string GetServerVersionFromResponse(Stream stream) { using (var reader = new EndianAwareBinaryReader(stream, Encoding.UTF8, true, false)) { //Read Type (should be response = 4) int type = reader.ReadByte(); if (type != 4) { throw new NAMEException($"{SupportedDependencies.SqlServer}: Server responded with wrong Type ({type}).", NAMEStatusLevel.Error); } //Skip Status bit mask reader.ReadByte(); //Read the full message length ushort length = reader.ReadUInt16(); //Skip Channel reader.ReadUInt16(); //Skip Packet Number reader.ReadByte(); //Skip Window reader.ReadByte(); //Read the rest of the message //preLoginBuffer = reader.ReadBytes(length - 2 - 1 - 1 - 2 - 1 - 1); //Read first option token (should be Version = 0) int token = reader.ReadByte(); if (token != 0) { throw new NAMEException($"{SupportedDependencies.SqlServer}: Server responded with wrong Token ({token}).", NAMEStatusLevel.Error); } //Read the offset ushort offset = reader.ReadUInt16(); //Read the length (should be 6) ushort optionlength = reader.ReadUInt16(); if (optionlength != 6) { throw new NAMEException($"{SupportedDependencies.SqlServer}: Server responded with an invalid version length ({length}).", NAMEStatusLevel.Error); } //Skip everything until the version. reader.ReadBytes(offset - 2 - 2 - 1); int major = reader.ReadByte(); int minor = reader.ReadByte(); int build = reader.ReadUInt16(); return($"{major}.{minor}.{build}"); } }
private static PropertyBlock Deserialize(EndianAwareBinaryReader reader, TypeHeader[] typeHeaders) { var typeId = reader.ReadInt32(); var name = Util.ReadLengthPrefixedString(reader); var dataType = (PropertyType)reader.ReadByte(); var typeHeader = typeHeaders.FirstOrDefault(n => n.TypeId == typeId); if (typeHeader == null) { throw new ArgumentException("No type header matches type id specified in property block."); } switch (dataType) { case PropertyType.String: { var values = Util.ReadStringArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <string>(name, dataType, typeId, values)); } case PropertyType.Boolean: { var values = Util.ReadBoolArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <bool>(name, dataType, typeId, values)); } case PropertyType.Int32: { var values = Util.ReadInt32Array(reader, typeHeader.InstanceCount); return(new PropertyBlock <int>(name, dataType, typeId, values)); } case PropertyType.Float: { var values = Util.ReadFloatArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <float>(name, dataType, typeId, values)); } case PropertyType.Double: { var values = Util.ReadDoubleArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <double>(name, dataType, typeId, values)); } case PropertyType.UDim2: { var values = Util.ReadUDim2Array(reader, typeHeader.InstanceCount); return(new PropertyBlock <UDim2>(name, dataType, typeId, values)); } case PropertyType.Ray: { var values = Util.ReadRayArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <Ray>(name, dataType, typeId, values)); } case PropertyType.Faces: { var values = Util.ReadFacesArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <Faces>(name, dataType, typeId, values)); } case PropertyType.Axis: { var values = Util.ReadAxisArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <Axis>(name, dataType, typeId, values)); } case PropertyType.BrickColor: { var values = Util.ReadBrickColorArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <BrickColor>(name, dataType, typeId, values)); } case PropertyType.Color3: { var values = Util.ReadColor3Array(reader, typeHeader.InstanceCount); return(new PropertyBlock <Color3>(name, dataType, typeId, values)); } case PropertyType.Vector2: { var values = Util.ReadVector2Array(reader, typeHeader.InstanceCount); return(new PropertyBlock <Vector2>(name, dataType, typeId, values)); } case PropertyType.Vector3: { var values = Util.ReadVector3Array(reader, typeHeader.InstanceCount); return(new PropertyBlock <Vector3>(name, dataType, typeId, values)); } case PropertyType.CFrame: { var values = Util.ReadCFrameArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <CFrame>(name, dataType, typeId, values)); } case PropertyType.Enumeration: { var values = Util.ReadEnumerationArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <int>(name, dataType, typeId, values)); } case PropertyType.Referent: { var values = Util.ReadReferentArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <int>(name, dataType, typeId, values)); } case PropertyType.NumberSequence: { var values = Util.ReadNumberSequenceArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <NumberSequence>(name, dataType, typeId, values)); } case PropertyType.ColorSequence: { var values = Util.ReadColorSequenceArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <ColorSequence>(name, dataType, typeId, values)); } case PropertyType.NumberRange: { var values = Util.ReadNumberRangeArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <NumberRange>(name, dataType, typeId, values)); } case PropertyType.Rectangle: { var values = Util.ReadRectangleArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <Rectangle>(name, dataType, typeId, values)); } case PropertyType.PhysicalProperties: { var values = Util.ReadPhysicalPropertiesArray(reader, typeHeader.InstanceCount); return(new PropertyBlock <PhysicalProperties>(name, dataType, typeId, values)); } default: { return(null); } } }
/// <summary> /// Reads the method header from the instruction stream. /// </summary> /// <param name="reader">The reader used to decode the instruction stream.</param> /// <returns></returns> private MethodHeader ReadMethodHeader(EndianAwareBinaryReader reader) { MethodHeader header = new MethodHeader(); // Read first byte header.Flags = (MethodFlags)reader.ReadByte(); // Check least significant 2 bits switch (header.Flags & MethodFlags.HeaderMask) { case MethodFlags.TinyFormat: header.CodeSize = ((uint)(header.Flags & MethodFlags.TinyCodeSizeMask) >> 2); header.Flags &= MethodFlags.HeaderMask; break; case MethodFlags.FatFormat: // Read second byte of flags header.Flags = (MethodFlags)(reader.ReadByte() << 8 | (byte)header.Flags); if (MethodFlags.ValidHeader != (header.Flags & MethodFlags.HeaderSizeMask)) throw new InvalidDataException(@"Invalid method header."); header.MaxStack = reader.ReadUInt16(); header.CodeSize = reader.ReadUInt32(); header.LocalsSignature = new Token(reader.ReadUInt32()); // ReadStandAloneSigRow break; default: throw new InvalidDataException(@"Invalid method header while trying to decode " + this.methodCompiler.Method.ToString() + ". (Flags = " + header.Flags.ToString("X") + ", Rva = " + this.methodCompiler.Method.Rva + ")"); } // Are there sections following the code? if (MethodFlags.MoreSections != (header.Flags & MethodFlags.MoreSections)) return header; // Yes, seek to them and process those sections long codepos = reader.BaseStream.Position; // Seek to the end of the code... long dataSectPos = codepos + header.CodeSize; if (0 != (dataSectPos & 3)) dataSectPos += (4 - (dataSectPos % 4)); reader.BaseStream.Position = dataSectPos; // Read all headers, so the IL decoder knows how to handle these... byte flags; do { flags = reader.ReadByte(); bool isFat = (0x40 == (flags & 0x40)); int length; int blocks; if (isFat) { byte a = reader.ReadByte(); byte b = reader.ReadByte(); byte c = reader.ReadByte(); length = (c << 24) | (b << 16) | a; blocks = (length - 4) / 24; } else { length = reader.ReadByte(); blocks = (length - 4) / 12; /* Read & skip the padding. */ reader.ReadInt16(); } Debug.Assert(0x01 == (flags & 0x3F), @"Unsupported method data section."); // Read the clause for (int i = 0; i < blocks; i++) { ExceptionHandlingClause clause = new ExceptionHandlingClause(); clause.Read(reader, isFat); methodCompiler.ExceptionClauseHeader.AddClause(clause); } } while (0x80 == (flags & 0x80)); reader.BaseStream.Position = codepos; return header; }
private static string GetVersionFromServerReponse(TcpClient client) { EndianAwareBinaryReader reader = new EndianAwareBinaryReader(client.GetStream(), false); try { byte type = reader.ReadByte(); if (type != 1) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server responded with wrong type ({type})."); } //Skip channel reader.ReadUInt16(); //Read Length uint length = reader.ReadUInt32(); //Read the rest of the message into memory. The length of Connection.Start will never be bigger than int.max byte[] buffer = reader.ReadBytes((int)length); reader.Dispose(); reader = new EndianAwareBinaryReader(new MemoryStream(buffer), false); //Read class (should be Connection (10)) ushort rClass = reader.ReadUInt16(); if (rClass != 10) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server responded with wrong class ({rClass})."); } //Read method (should be Start (10)) ushort rMethod = reader.ReadUInt16(); if (rMethod != 10) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server responded with wrong method ({rMethod})."); } //Read AMQP major version (should be 0) byte major = reader.ReadByte(); if (major != 0) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server responded with wrong AMQP major version ({major})."); } //Read AMQP minor version (should be 9) byte minor = reader.ReadByte(); if (major != 0) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server responded with wrong AMQP minor version ({minor})."); } IDictionary <string, object> serverProperties = AmqpTypesReader.ReadTable(reader); if (!serverProperties.ContainsKey("version")) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server did not send a server-properties table!"); } if (!(serverProperties["version"] is byte[])) { throw new NAMEException($"{SupportedDependencies.RabbitMq}: Server returned a version which is not a string!"); } var versionStr = Encoding.UTF8.GetString((byte[])serverProperties["version"]); return(versionStr); } finally { if (reader != null) { reader.Dispose(); } } }
public void Read(EndianAwareBinaryReader reader) { this.majorVersion = reader.ReadByte(); this.minorVersion = reader.ReadByte(); }
public object Deserialize(EndianAwareBinaryReader reader, SerializedType serializedType, int?length = null) { int?effectiveLength = null; var typeParent = TypeNode.Parent as TypeNode; if (length != null) { effectiveLength = length.Value; } else if (TypeNode.FieldLengthBinding != null) { object lengthValue = TypeNode.FieldLengthBinding.GetValue(this); effectiveLength = Convert.ToInt32(lengthValue); } else if (typeParent != null && typeParent.ItemLengthBinding != null) { object lengthValue = typeParent.ItemLengthBinding.GetValue((ValueNode)Parent); effectiveLength = Convert.ToInt32(lengthValue); } else if (TypeNode.FieldCountBinding != null) { object countValue = TypeNode.FieldCountBinding.GetValue(this); effectiveLength = Convert.ToInt32(countValue); } else if (serializedType == SerializedType.ByteArray || serializedType == SerializedType.SizedString) { checked { effectiveLength = (int)_remainder; } } object value; switch (serializedType) { case SerializedType.Int1: value = reader.ReadSByte(); break; case SerializedType.UInt1: value = reader.ReadByte(GetBitSize()); break; case SerializedType.Int2: value = reader.ReadInt16(); break; case SerializedType.UInt2: value = reader.ReadUInt16(); break; case SerializedType.Int4: value = reader.ReadInt32(); break; case SerializedType.UInt4: value = reader.ReadUInt32(); break; case SerializedType.Int8: value = reader.ReadInt64(); break; case SerializedType.UInt8: value = reader.ReadUInt64(); break; case SerializedType.Float4: value = reader.ReadSingle(); break; case SerializedType.Float8: value = reader.ReadDouble(); break; case SerializedType.ByteArray: { Debug.Assert(effectiveLength != null, "effectiveLength != null"); value = reader.ReadBytes(effectiveLength.Value); break; } case SerializedType.NullTerminatedString: { byte[] data = ReadNullTerminatedString(reader).ToArray(); value = Encoding.GetString(data, 0, data.Length); break; } case SerializedType.SizedString: { Debug.Assert(effectiveLength != null, "effectiveLength != null"); byte[] data = reader.ReadBytes(effectiveLength.Value); value = Encoding.GetString(data, 0, data.Length).TrimEnd('\0'); break; } case SerializedType.LengthPrefixedString: { value = reader.ReadString(); break; } default: throw new NotSupportedException(); } return(value); }
private void ReadWide(EndianAwareBinaryReader reader, ICliMetadataRoot metadataRoot, Action <byte[]> bodyBuilder) { var flagsAndSize = reader.ReadUInt16(); this.flags = ((MethodHeaderFlags)(flagsAndSize & 0x0FFF)) & ~MethodHeaderFlags.WideFormat; this.headerSize = (byte)((flagsAndSize & 0xF000) >> 0xA); this.maxStack = reader.ReadUInt16(); this.codeSize = reader.ReadUInt32(); var localVarSigToken = reader.ReadUInt32(); if (localVarSigToken != 0) { var sigTableKind = (CliMetadataTableKinds)(1UL << (int)((localVarSigToken & 0xFF000000) >> 24)); var sigIndex = localVarSigToken & 0x00FFFFFF; ICliMetadataTable table; if (metadataRoot.TableStream.TryGetValue(sigTableKind, out table)) { if (table is ICliMetadataStandAloneSigTable) { ICliMetadataStandAloneSigTable sigTable = (ICliMetadataStandAloneSigTable)table; var entry = sigTable[(int)sigIndex]; if (entry.Signature is ICliMetadataLocalVarSignature) { var sigEntry = (ICliMetadataLocalVarSignature)entry.Signature; this.locals = sigEntry; } } } long codePosition = reader.BaseStream.Position; bodyBuilder(reader.ReadBytes((int)this.codeSize)); if ((reader.BaseStream.Position % 4) != 0) { reader.BaseStream.Position += 4 - reader.BaseStream.Position % 4; } var ehTable = new byte[0]; if ((flags & MethodHeaderFlags.ContainsMoreSections) == MethodHeaderFlags.ContainsMoreSections) { readSection: MethodHeaderSectionFlags sectionFlags = (MethodHeaderSectionFlags)reader.ReadByte(); var smallFormat = ((sectionFlags & MethodHeaderSectionFlags.FatFormat) != MethodHeaderSectionFlags.FatFormat); int dataSize = 0; if (smallFormat) { dataSize = reader.ReadByte(); reader.ReadUInt16(); } else { dataSize = (int)new BitVector(new byte[] { reader.ReadByte(), reader.ReadByte(), reader.ReadByte() }).GetUInt32Nibbits(0, 24); } if ((sectionFlags & MethodHeaderSectionFlags.ExceptionHandlerTable) == MethodHeaderSectionFlags.ExceptionHandlerTable) { ehTable = ehTable.AddInlineArray(reader.ReadBytes(dataSize - 4)); } else { reader.BaseStream.Position += dataSize - 4; } if ((sectionFlags & MethodHeaderSectionFlags.ContainsMoreSections) == MethodHeaderSectionFlags.ContainsMoreSections) { goto readSection; } } if (ehTable.Length > 0) { this.exceptionTable = new CliMetadataMethodExceptionTable(ehTable); } reader.BaseStream.Position = codePosition; } }
/// <summary> /// Reads the method header from the instruction stream. /// </summary> /// <param name="reader">The reader used to decode the instruction stream.</param> /// <returns></returns> public MethodHeader(EndianAwareBinaryReader reader) { Clauses = new List <ExceptionHandlingClause>(); // Read first byte Flags = (MethodFlags)reader.ReadByte(); // Check least significant 2 bits switch (Flags & MethodFlags.HeaderMask) { case MethodFlags.TinyFormat: CodeSize = ((int)(Flags & MethodFlags.TinyCodeSizeMask) >> 2); Flags &= MethodFlags.HeaderMask; break; case MethodFlags.FatFormat: // Read second byte of flags Flags = (MethodFlags)(reader.ReadByte() << 8 | (byte)Flags); if (MethodFlags.ValidHeader != (Flags & MethodFlags.HeaderSizeMask)) { throw new CompilerException("Invalid method "); } MaxStack = reader.ReadUInt16(); CodeSize = reader.ReadInt32(); LocalVarSigTok = new Token(reader.ReadUInt32()); // ReadStandAloneSigRow break; default: throw new CompilerException("Invalid method header"); } // Are there sections following the code? if (MethodFlags.MoreSections != (Flags & MethodFlags.MoreSections)) { return; } // Yes, seek to them and process those sections long codepos = reader.BaseStream.Position; // Seek to the end of the code... long dataSectPos = codepos + CodeSize; if (0 != (dataSectPos & 3)) { dataSectPos += (4 - (dataSectPos % 4)); } reader.BaseStream.Position = dataSectPos; // Read all headers, so the IL decoder knows how to handle these... byte flags; do { flags = reader.ReadByte(); bool isFat = (0x40 == (flags & 0x40)); int length; int blocks; if (isFat) { byte a = reader.ReadByte(); byte b = reader.ReadByte(); byte c = reader.ReadByte(); length = (c << 24) | (b << 16) | a; blocks = (length - 4) / 24; } else { length = reader.ReadByte(); blocks = (length - 4) / 12; /* Read & skip the padding. */ reader.ReadInt16(); } Debug.Assert(0x01 == (flags & 0x3F), "Unsupported method data section."); // Read the clause for (int i = 0; i < blocks; i++) { ExceptionHandlingClause clause = new ExceptionHandlingClause(); clause.Read(reader, isFat); Clauses.Add(clause); } }while (0x80 == (flags & 0x80)); reader.BaseStream.Position = codepos; }