/// <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; }
/// <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; }
/// <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; }