public MethodEntry(int rva, BlobReader reader) { RVA = rva; Flags = (MethodHeaderFlags)reader.ReadByte(); if (!Flags.HasFlag(MethodHeaderFlags.FatFormat)) { Size = (int)Flags & 0x3F; Flags = MethodHeaderFlags.TinyFormat; MethodBody = reader.ReadBytes((int)Size); } else { Size = (reader.ReadByte() & 0xF0) >> 4; MaxStack = reader.Read<ushort>(); CodeSize = reader.Read<uint>(); LocalVarSigTok = new MetadataToken(reader.Read<uint>()); MethodBody = reader.ReadBytes((int)CodeSize); //var end = reader.BaseStream.Position + Size; //var data = new List<MethodData>(); //while (reader.BaseStream.Position < end) //{ // data.Add(new MethodData(reader)); //} //Data = data.ToArray(); } }
internal CliMetadataMethodHeader(ICliMetadataRoot metadataRoot, uint relativeVirtualAddress, Action <byte[]> bodyBuilder) { var image = metadataRoot.SourceImage; var rvaLocationScan = image.ResolveRelativeVirtualAddress(relativeVirtualAddress); if (rvaLocationScan.Resolved) { var section = rvaLocationScan.Section; var bodySubstream = new Substream(section.SectionData, rvaLocationScan.Offset, 65536, false); var bodyReader = new EndianAwareBinaryReader(bodySubstream, Endianness.LittleEndian, false); var peekedChar = bodyReader.PeekByte(); if (peekedChar != -1) { MethodHeaderFlags headerType = ((MethodHeaderFlags)peekedChar) & MethodHeaderFlags.WideFormat; if (headerType == MethodHeaderFlags.NarrowFormat) { this.ReadNarrow(bodyReader, metadataRoot, bodyBuilder); } else { this.ReadWide(bodyReader, metadataRoot, bodyBuilder); } } } }
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; } }