diff --git a/Directory.Build.props b/Directory.Build.props index 8c391994c..893643cc4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,6 +9,7 @@ $(MSBuildThisFileDirectory)\cecil.snk $(DefineConstants);NET_CORE + true true diff --git a/Mono.Cecil.Cil/CodeReader.cs b/Mono.Cecil.Cil/CodeReader.cs index ac5b31be0..c9b6c5e3c 100644 --- a/Mono.Cecil.Cil/CodeReader.cs +++ b/Mono.Cecil.Cil/CodeReader.cs @@ -131,11 +131,7 @@ void ReadFatMethod () public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) { - var position = reader.position; - var variables = reader.ReadVariables (local_var_token); - reader.position = position; - - return variables; + return reader.ReadVariables (local_var_token); } void ReadCode () diff --git a/Mono.Cecil.Metadata/BlobHeap.cs b/Mono.Cecil.Metadata/BlobHeap.cs index 574a130c9..93814624c 100644 --- a/Mono.Cecil.Metadata/BlobHeap.cs +++ b/Mono.Cecil.Metadata/BlobHeap.cs @@ -9,36 +9,43 @@ // using System; +using System.Runtime.InteropServices; namespace Mono.Cecil.Metadata { - sealed class BlobHeap : Heap { + sealed unsafe class BlobHeap : Heap { - public BlobHeap (byte [] data) - : base (data) + public BlobHeap (byte* data, uint size) + : base (data, size) { } public byte [] Read (uint index) { - if (index == 0 || index > this.data.Length - 1) + if (index == 0 || index > this.size - 1) return Empty.Array; int position = (int) index; - int length = (int) data.ReadCompressedUInt32 (ref position); + int length = (int) Mixin.ReadCompressedUInt32 (data, ref position); - if (length > data.Length - position) + if (length > size - position) return Empty.Array; var buffer = new byte [length]; - Buffer.BlockCopy (data, position, buffer, 0, length); + Marshal.Copy ((IntPtr)(data + position), buffer, 0, length); return buffer; } public void GetView (uint signature, out byte [] buffer, out int index, out int length) { + buffer = Read (signature); + index = 0; + length = buffer.Length; + + + /* if (signature == 0 || signature > data.Length - 1) { buffer = null; index = length = 0; @@ -49,6 +56,7 @@ public void GetView (uint signature, out byte [] buffer, out int index, out int index = (int) signature; length = (int) buffer.ReadCompressedUInt32 (ref index); + */ } } } diff --git a/Mono.Cecil.Metadata/GuidHeap.cs b/Mono.Cecil.Metadata/GuidHeap.cs index 76ec9d1d1..e8157a7bd 100644 --- a/Mono.Cecil.Metadata/GuidHeap.cs +++ b/Mono.Cecil.Metadata/GuidHeap.cs @@ -9,13 +9,14 @@ // using System; +using System.Runtime.InteropServices; namespace Mono.Cecil.Metadata { - sealed class GuidHeap : Heap { + sealed unsafe class GuidHeap : Heap { - public GuidHeap (byte [] data) - : base (data) + public GuidHeap (byte* data, uint size) + : base (data, size) { } @@ -23,14 +24,16 @@ public Guid Read (uint index) { const int guid_size = 16; - if (index == 0 || ((index - 1) + guid_size) > data.Length) + if (index == 0 || ((index - 1) + guid_size) > size) return new Guid (); - var buffer = new byte [guid_size]; - - Buffer.BlockCopy (this.data, (int) ((index - 1) * guid_size), buffer, 0, guid_size); - - return new Guid (buffer); + if (BitConverter.IsLittleEndian) { + return *(Guid*) (data + ((index - 1) * guid_size)); + } else { + var buffer = new byte [guid_size]; + Marshal.Copy ((IntPtr)(data + ((index - 1) * guid_size)), buffer, 0, guid_size); + return new Guid (buffer); + } } } } diff --git a/Mono.Cecil.Metadata/Heap.cs b/Mono.Cecil.Metadata/Heap.cs index 6874d7963..d650ccc2a 100644 --- a/Mono.Cecil.Metadata/Heap.cs +++ b/Mono.Cecil.Metadata/Heap.cs @@ -8,17 +8,23 @@ // Licensed under the MIT/X11 license. // +using Mono.Cecil.PE; + namespace Mono.Cecil.Metadata { - abstract class Heap { + abstract unsafe class Heap { public int IndexSize; - readonly internal byte [] data; + readonly internal byte* data; + readonly internal uint size; + + public ByteSpan Span => new ByteSpan (data, size); - protected Heap (byte [] data) + protected Heap (byte* data, uint size) { this.data = data; + this.size = size; } } } diff --git a/Mono.Cecil.Metadata/PdbHeap.cs b/Mono.Cecil.Metadata/PdbHeap.cs index 39e275ad9..aa62c6d13 100644 --- a/Mono.Cecil.Metadata/PdbHeap.cs +++ b/Mono.Cecil.Metadata/PdbHeap.cs @@ -21,8 +21,8 @@ sealed class PdbHeap : Heap { public long TypeSystemTables; public uint [] TypeSystemTableRows; - public PdbHeap (byte [] data) - : base (data) + public unsafe PdbHeap (byte* data, uint size) + : base (data, size) { } diff --git a/Mono.Cecil.Metadata/StringHeap.cs b/Mono.Cecil.Metadata/StringHeap.cs index 4bde70e23..d3316fd7b 100644 --- a/Mono.Cecil.Metadata/StringHeap.cs +++ b/Mono.Cecil.Metadata/StringHeap.cs @@ -11,15 +11,16 @@ using System; using System.Collections.Generic; using System.Text; +using Mono.Cecil.PE; namespace Mono.Cecil.Metadata { - class StringHeap : Heap { + unsafe class StringHeap : Heap { readonly Dictionary strings = new Dictionary (); - public StringHeap (byte [] data) - : base (data) + public StringHeap (byte* data, uint size) + : base (data, size) { } @@ -32,7 +33,7 @@ public string Read (uint index) if (strings.TryGetValue (index, out @string)) return @string; - if (index > data.Length - 1) + if (index > size - 1) return string.Empty; @string = ReadStringAt (index); @@ -54,7 +55,12 @@ protected virtual string ReadStringAt (uint index) length++; } - return Encoding.UTF8.GetString (data, start, length); +#if NET_CORE + return Encoding.UTF8.GetString (this.data + start, length); +#else + var buffer = new PByteBuffer (this.data + start, (uint) length); + return Encoding.UTF8.GetString (buffer.ReadBytes (length)); +#endif } } } diff --git a/Mono.Cecil.Metadata/TableHeap.cs b/Mono.Cecil.Metadata/TableHeap.cs index dee655a34..ba583be4a 100644 --- a/Mono.Cecil.Metadata/TableHeap.cs +++ b/Mono.Cecil.Metadata/TableHeap.cs @@ -80,7 +80,7 @@ public bool IsLarge { } } - sealed class TableHeap : Heap { + sealed unsafe class TableHeap : Heap { public long Valid; public long Sorted; @@ -91,8 +91,8 @@ public TableInformation this [Table table] { get { return Tables [(int) table]; } } - public TableHeap (byte [] data) - : base (data) + public TableHeap (byte* data, uint size) + : base (data, size) { } diff --git a/Mono.Cecil.Metadata/UserStringHeap.cs b/Mono.Cecil.Metadata/UserStringHeap.cs index 7b1b42ffa..c81661a33 100644 --- a/Mono.Cecil.Metadata/UserStringHeap.cs +++ b/Mono.Cecil.Metadata/UserStringHeap.cs @@ -8,12 +8,14 @@ // Licensed under the MIT/X11 license. // +using System; + namespace Mono.Cecil.Metadata { - sealed class UserStringHeap : StringHeap { + sealed unsafe class UserStringHeap : StringHeap { - public UserStringHeap (byte [] data) - : base (data) + public UserStringHeap (byte* data, uint size) + : base (data, size) { } @@ -21,10 +23,14 @@ protected override string ReadStringAt (uint index) { int start = (int) index; - uint length = (uint) (data.ReadCompressedUInt32 (ref start) & ~1); + uint length = (uint) (Mixin.ReadCompressedUInt32 (data, ref start) & ~1); if (length < 1) return string.Empty; + if (BitConverter.IsLittleEndian) { + return new string ((char*)(data + start), 0, (int)length / 2); + } + var chars = new char [length / 2]; for (int i = start, j = 0; i < start + length; i += 2) diff --git a/Mono.Cecil.Metadata/Utilities.cs b/Mono.Cecil.Metadata/Utilities.cs index e29987251..0f18ac1b5 100644 --- a/Mono.Cecil.Metadata/Utilities.cs +++ b/Mono.Cecil.Metadata/Utilities.cs @@ -19,7 +19,7 @@ static partial class Mixin { public const int TableCount = 58; public const int CodedIndexCount = 14; - public static uint ReadCompressedUInt32 (this byte [] data, ref int position) + public static unsafe uint ReadCompressedUInt32 (byte* data, ref int position) { uint integer; if ((data [position] & 0x80) == 0) { diff --git a/Mono.Cecil.PE/ByteBuffer.cs b/Mono.Cecil.PE/ByteBuffer.cs index 9a6567ce1..e3be87c62 100644 --- a/Mono.Cecil.PE/ByteBuffer.cs +++ b/Mono.Cecil.PE/ByteBuffer.cs @@ -9,9 +9,173 @@ // using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace Mono.Cecil.PE { + readonly unsafe struct ByteSpan { + internal readonly byte* pointer; + internal readonly uint length; + + public ByteSpan (byte* pointer, uint length) + { + this.pointer = pointer; + this.length = length; + } + } + + unsafe ref struct PByteBuffer { + + internal readonly ByteSpan span; + internal byte* p; + internal readonly byte* e; + + public PByteBuffer (byte* bytes, uint length) + : this(new ByteSpan(bytes, length)) + { + } + + public PByteBuffer (ByteSpan span) + { + this.span = span; + this.p = this.span.pointer; + this.e = this.p + this.span.length; + } + + public int RemainingBytes () + { + return (int) (e - p); + } + + public bool CanReadMore () + { + return p < e; + } + + public void Advance (int length) + { + p += length; + } + + public byte PeekByte () + { + return p [0]; + } + + public byte ReadByte () + { + var b = p [0]; + p++; + return b; + } + + public ushort ReadUInt16 () + { + ushort value; + if (BitConverter.IsLittleEndian) { + value = *(ushort*) p; + } else { + value = (ushort) (p [0] | (p [1] << 8)); + } + + p += 2; + return value; + } + + public short ReadInt16 () + { + return (short) ReadUInt16 (); + } + + public uint ReadUInt32 () + { + uint value; + if (BitConverter.IsLittleEndian) { + value = *(uint*) p; + } else { + value = (uint) (p [0] | (p [1] << 8) | (p [2] << 16) | (p [3] << 24)); + } + + p += 4; + return value; + } + + public int ReadInt32 () + { + return (int) ReadUInt32 (); + } + + public ulong ReadUInt64 () + { + uint low = ReadUInt32 (); + uint high = ReadUInt32 (); + + return (((ulong) high) << 32) | low; + } + + public long ReadInt64 () + { + return (long) ReadUInt64 (); + } + + public uint ReadCompressedUInt32 () + { + byte first = ReadByte (); + if ((first & 0x80) == 0) + return first; + + if ((first & 0x40) == 0) + return ((uint) (first & ~0x80) << 8) + | ReadByte (); + + return ((uint) (first & ~0xc0) << 24) + | (uint) ReadByte () << 16 + | (uint) ReadByte () << 8 + | ReadByte (); + } + + public int ReadCompressedInt32 () + { + var b = p [0]; + var u = (int) ReadCompressedUInt32 (); + var v = u >> 1; + if ((u & 1) == 0) + return v; + + switch (b & 0xc0) + { + case 0: + case 0x40: + return v - 0x40; + case 0x80: + return v - 0x2000; + default: + return v - 0x10000000; + } + } + + public byte [] ReadBytes (int count) + { + var bytes = new byte [count]; + Marshal.Copy ((IntPtr)p, bytes, 0, count); + p += count; + return bytes; + } + + public float ReadSingle () + { + var u = ReadUInt32 (); + return *(float*) &u; + } + + public double ReadDouble () + { + var u = ReadUInt64 (); + return *(double*) &u; + } + } + class ByteBuffer { internal byte [] buffer; diff --git a/Mono.Cecil.PE/Image.cs b/Mono.Cecil.PE/Image.cs index 109206187..038bf56ba 100644 --- a/Mono.Cecil.PE/Image.cs +++ b/Mono.Cecil.PE/Image.cs @@ -10,7 +10,7 @@ using System; using System.IO; - +using System.Runtime.InteropServices; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Collections.Generic; @@ -19,6 +19,27 @@ namespace Mono.Cecil.PE { + readonly unsafe struct NativeMemory : IDisposable + { + private readonly IntPtr pointer; + private readonly int length; + + public byte* Pointer => (byte*)pointer; + + public int Length => length; + + public NativeMemory(int length) + { + this.pointer = Marshal.AllocHGlobal (length); + this.length = length; + } + + public void Dispose() + { + Marshal.FreeHGlobal (pointer); + } + } + sealed class Image : IDisposable { public Disposable Stream; @@ -36,7 +57,7 @@ sealed class Image : IDisposable { public Section [] Sections; - public Section MetadataSection; + public NativeMemory Metadata; public uint EntryPointToken; public uint Timestamp; @@ -164,6 +185,7 @@ public bool HasDebugTables () public void Dispose () { + Metadata.Dispose (); Stream.Dispose (); } } diff --git a/Mono.Cecil.PE/ImageReader.cs b/Mono.Cecil.PE/ImageReader.cs index 9731ba90b..a6f44c5e5 100644 --- a/Mono.Cecil.PE/ImageReader.cs +++ b/Mono.Cecil.PE/ImageReader.cs @@ -10,7 +10,7 @@ using System; using System.IO; - +using System.Runtime.InteropServices; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Collections.Generic; @@ -19,15 +19,13 @@ namespace Mono.Cecil.PE { - sealed class ImageReader : BinaryStreamReader { + sealed unsafe class ImageReader : BinaryStreamReader { readonly Image image; DataDirectory cli; DataDirectory metadata; - uint table_heap_offset; - public ImageReader (Disposable stream, string file_name) : base (stream.value) { @@ -199,29 +197,28 @@ void ReadOptionalHeaders (out ushort subsystem, out ushort dll_characteristics) Advance (8); } - string ReadAlignedString (int length) + string ReadAlignedString (int length, ref PByteBuffer b) { int read = 0; var buffer = new char [length]; while (read < length) { - var current = ReadByte (); + var current = b.ReadByte (); if (current == 0) break; buffer [read++] = (char) current; } - Advance (-1 + ((read + 4) & ~3) - read); + b.Advance (-1 + ((read + 4) & ~3) - read); return new string (buffer, 0, read); } - string ReadZeroTerminatedString (int length) + string ReadZeroTerminatedString (byte[] bytes) { int read = 0; - var buffer = new char [length]; - var bytes = ReadBytes (length); - while (read < length) { + var buffer = new char [bytes.Length]; + while (read < bytes.Length) { var current = bytes [read]; if (current == 0) break; @@ -240,7 +237,7 @@ void ReadSections (ushort count) var section = new Section (); // Name - section.Name = ReadZeroTerminatedString (8); + section.Name = ReadZeroTerminatedString (ReadBytes (8)); // VirtualSize 4 Advance (4); @@ -292,33 +289,53 @@ void ReadCLIHeader () // ManagedNativeHeader 8 } + void CopyTo (ref NativeMemory memory) + { + var destination = memory.Pointer; + var size = memory.Length; + + var buffer = new byte [Math.Min (81920, size)]; + while (size > 0) { + int readSize = Math.Min (size, buffer.Length); + int bytesRead = Read (buffer, 0, readSize); + + if (bytesRead <= 0 || bytesRead > readSize) { + throw new IOException (); + } + + Marshal.Copy (buffer, 0, (IntPtr) destination, bytesRead); + + destination += bytesRead; + size -= bytesRead; + } + } + void ReadMetadata () { + image.Metadata = new NativeMemory((int)metadata.Size); + MoveTo (metadata); + CopyTo (ref image.Metadata); + + var buffer = new PByteBuffer (image.Metadata.Pointer, (uint) image.Metadata.Length); - if (ReadUInt32 () != 0x424a5342) + if (buffer.ReadUInt32 () != 0x424a5342) throw new BadImageFormatException (); // MajorVersion 2 // MinorVersion 2 // Reserved 4 - Advance (8); + buffer.Advance (8); - image.RuntimeVersion = ReadZeroTerminatedString (ReadInt32 ()); + image.RuntimeVersion = ReadZeroTerminatedString (buffer.ReadBytes (buffer.ReadInt32 ())); // Flags 2 - Advance (2); - - var streams = ReadUInt16 (); + buffer.Advance (2); - var section = image.GetSectionAtVirtualAddress (metadata.VirtualAddress); - if (section == null) - throw new BadImageFormatException (); - - image.MetadataSection = section; + var streams = buffer.ReadUInt16 (); for (int i = 0; i < streams; i++) - ReadMetadataStream (section); + ReadMetadataStream (ref buffer); if (image.PdbHeap != null) ReadPdbHeap (); @@ -368,73 +385,62 @@ void ReadDebugHeader () image.DebugHeader = new ImageDebugHeader (entries); } - void ReadMetadataStream (Section section) + void ReadMetadataStream (ref PByteBuffer buffer) { // Offset 4 - uint offset = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start + var offset = buffer.ReadUInt32 (); // Size 4 - uint size = ReadUInt32 (); + uint size = buffer.ReadUInt32 (); - var data = ReadHeapData (offset, size); + var data = image.Metadata.Pointer + offset; - var name = ReadAlignedString (16); + var name = ReadAlignedString (16, ref buffer); switch (name) { case "#~": case "#-": - image.TableHeap = new TableHeap (data); - table_heap_offset = offset; + image.TableHeap = new TableHeap (data, size); break; case "#Strings": - image.StringHeap = new StringHeap (data); + image.StringHeap = new StringHeap (data, size); break; case "#Blob": - image.BlobHeap = new BlobHeap (data); + image.BlobHeap = new BlobHeap (data, size); break; case "#GUID": - image.GuidHeap = new GuidHeap (data); + image.GuidHeap = new GuidHeap (data, size); break; case "#US": - image.UserStringHeap = new UserStringHeap (data); + image.UserStringHeap = new UserStringHeap (data, size); break; case "#Pdb": - image.PdbHeap = new PdbHeap (data); + image.PdbHeap = new PdbHeap (data, size); break; } } - byte [] ReadHeapData (uint offset, uint size) - { - var position = BaseStream.Position; - MoveTo (offset + image.MetadataSection.PointerToRawData); - var data = ReadBytes ((int) size); - BaseStream.Position = position; - - return data; - } - void ReadTableHeap () { var heap = image.TableHeap; - MoveTo (table_heap_offset + image.MetadataSection.PointerToRawData); + var buffer = new PByteBuffer (heap.Span); // Reserved 4 // MajorVersion 1 // MinorVersion 1 - Advance (6); + buffer.Advance (6); // HeapSizes 1 - var sizes = ReadByte (); + var sizes = buffer.ReadByte (); // Reserved2 1 - Advance (1); + buffer.Advance (1); // Valid 8 - heap.Valid = ReadInt64 (); + heap.Valid = buffer.ReadInt64 (); // Sorted 8 - heap.Sorted = ReadInt64 (); + heap.Sorted = buffer.ReadInt64 (); if (image.PdbHeap != null) { for (int i = 0; i < Mixin.TableCount; i++) { @@ -449,14 +455,14 @@ void ReadTableHeap () if (!heap.HasTable ((Table) i)) continue; - heap.Tables [i].Length = ReadUInt32 (); + heap.Tables [i].Length = buffer.ReadUInt32 (); } SetIndexSize (image.StringHeap, sizes, 0x1); SetIndexSize (image.GuidHeap, sizes, 0x2); SetIndexSize (image.BlobHeap, sizes, 0x4); - ComputeTableInformations (); + ComputeTableInformations (ref buffer); } static void SetIndexSize (Heap heap, uint sizes, byte flag) @@ -477,9 +483,9 @@ int GetCodedIndexSize (CodedIndex index) return image.GetCodedIndexSize (index); } - void ComputeTableInformations () + void ComputeTableInformations (ref PByteBuffer buffer) { - uint offset = (uint) BaseStream.Position - table_heap_offset - image.MetadataSection.PointerToRawData; // header + uint offset = (uint) (buffer.p - image.TableHeap.data); int stridx_size = image.StringHeap.IndexSize; int guididx_size = image.GuidHeap != null ? image.GuidHeap.IndexSize : 2; @@ -740,7 +746,7 @@ void ReadPdbHeap () { var heap = image.PdbHeap; - var buffer = new ByteBuffer (heap.data); + var buffer = new PByteBuffer (heap.Span); heap.Id = buffer.ReadBytes (20); heap.EntryPoint = buffer.ReadUInt32 (); diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs index b64846368..38ef3bf9c 100644 --- a/Mono.Cecil/AssemblyReader.cs +++ b/Mono.Cecil/AssemblyReader.cs @@ -442,7 +442,7 @@ public override void ReadSymbols (ModuleDefinition module) } } - sealed class MetadataReader : ByteBuffer { + sealed unsafe class MetadataReader { readonly internal Image image; readonly internal ModuleDefinition module; @@ -454,7 +454,6 @@ sealed class MetadataReader : ByteBuffer { readonly MetadataReader metadata_reader; public MetadataReader (ModuleDefinition module) - : base (module.Image.TableHeap.data) { this.image = module.Image; this.module = module; @@ -463,7 +462,6 @@ public MetadataReader (ModuleDefinition module) } public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader) - : base (image.TableHeap.data) { this.image = image; this.module = module; @@ -476,23 +474,23 @@ int GetCodedIndexSize (CodedIndex index) return image.GetCodedIndexSize (index); } - uint ReadByIndexSize (int size) + uint ReadByIndexSize (int size, ref PByteBuffer buffer) { if (size == 4) - return ReadUInt32 (); + return buffer.ReadUInt32 (); else - return ReadUInt16 (); + return buffer.ReadUInt16 (); } - byte [] ReadBlob () + byte [] ReadBlob (ref PByteBuffer buffer) { var blob_heap = image.BlobHeap; if (blob_heap == null) { - position += 2; + buffer.Advance (2); return Empty.Array; } - return blob_heap.Read (ReadBlobIndex ()); + return blob_heap.Read (ReadBlobIndex (ref buffer)); } byte [] ReadBlob (uint signature) @@ -504,10 +502,10 @@ byte [] ReadBlob (uint signature) return blob_heap.Read (signature); } - uint ReadBlobIndex () + uint ReadBlobIndex (ref PByteBuffer buffer) { var blob_heap = image.BlobHeap; - return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2); + return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2, ref buffer); } void GetBlobView (uint signature, out byte [] blob, out int index, out int count) @@ -522,78 +520,88 @@ void GetBlobView (uint signature, out byte [] blob, out int index, out int count blob_heap.GetView (signature, out blob, out index, out count); } - string ReadString () + string ReadString (ref PByteBuffer buffer) { - return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize)); + return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize, ref buffer)); } - uint ReadStringIndex () + uint ReadStringIndex (ref PByteBuffer buffer) { - return ReadByIndexSize (image.StringHeap.IndexSize); + return ReadByIndexSize (image.StringHeap.IndexSize, ref buffer); } - Guid ReadGuid () + Guid ReadGuid (ref PByteBuffer buffer) { - return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); + return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize, ref buffer)); } - uint ReadTableIndex (Table table) + uint ReadTableIndex (Table table, ref PByteBuffer buffer) { - return ReadByIndexSize (image.GetTableIndexSize (table)); + return ReadByIndexSize (image.GetTableIndexSize (table), ref buffer); } - MetadataToken ReadMetadataToken (CodedIndex index) + MetadataToken ReadMetadataToken (CodedIndex index, ref PByteBuffer buffer) { - return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index))); + return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index), ref buffer)); } - int MoveTo (Table table) + int MoveTo (Table table, out PByteBuffer buffer) { var info = image.TableHeap [table]; - if (info.Length != 0) - this.position = (int) info.Offset; + if (info.Length != 0) { + buffer = new PByteBuffer(image.TableHeap.data + info.Offset, info.RowSize * info.Length); + return (int) info.Length; + } - return (int) info.Length; + buffer = default; + return 0; } - bool MoveTo (Table table, uint row) + bool MoveTo (Table table, uint row, out PByteBuffer buffer) { var info = image.TableHeap [table]; var length = info.Length; - if (length == 0 || row > length) + if (length == 0 || row > length) { + buffer = default; return false; + } + + var end = info.Offset + (info.RowSize * info.Length); + var start = (info.Offset + (info.RowSize * (row - 1))); + var size = end - start; + + buffer = new PByteBuffer (image.TableHeap.data + start, size); - this.position = (int) (info.Offset + (info.RowSize * (row - 1))); return true; } public AssemblyNameDefinition ReadAssemblyNameDefinition () { - if (MoveTo (Table.Assembly) == 0) + if (MoveTo (Table.Assembly, out PByteBuffer buffer) == 0) return null; var name = new AssemblyNameDefinition (); - name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 (); + name.HashAlgorithm = (AssemblyHashAlgorithm) buffer.ReadUInt32 (); - PopulateVersionAndFlags (name); + PopulateVersionAndFlags (name, ref buffer); - name.PublicKey = ReadBlob (); + name.PublicKey = ReadBlob (ref buffer); - PopulateNameAndCulture (name); + PopulateNameAndCulture (name, ref buffer); return name; } public ModuleDefinition Populate (ModuleDefinition module) { - if (MoveTo (Table.Module) == 0) + if (MoveTo (Table.Module, out PByteBuffer buffer) == 0) return module; - Advance (2); // Generation + buffer.Advance (2); // Generation - module.Name = ReadString (); - module.Mvid = ReadGuid (); + module.Name = ReadString (ref buffer); + module.Mvid = ReadGuid (ref buffer); return module; } @@ -603,25 +611,25 @@ void InitializeAssemblyReferences () if (metadata.AssemblyReferences != null) return; - int length = MoveTo (Table.AssemblyRef); + int length = MoveTo (Table.AssemblyRef, out PByteBuffer buffer); var references = metadata.AssemblyReferences = new AssemblyNameReference [length]; for (uint i = 0; i < length; i++) { var reference = new AssemblyNameReference (); reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1); - PopulateVersionAndFlags (reference); + PopulateVersionAndFlags (reference, ref buffer); - var key_or_token = ReadBlob (); + var key_or_token = ReadBlob (ref buffer); if (reference.HasPublicKey) reference.PublicKey = key_or_token; else reference.PublicKeyToken = key_or_token; - PopulateNameAndCulture (reference); + PopulateNameAndCulture (reference, ref buffer); - reference.Hash = ReadBlob (); + reference.Hash = ReadBlob (ref buffer); references [i] = reference; } @@ -652,11 +660,11 @@ public Collection ReadModules () var modules = new Collection (1); modules.Add (this.module); - int length = MoveTo (Table.File); + int length = MoveTo (Table.File, out PByteBuffer buffer); for (uint i = 1; i <= length; i++) { - var attributes = (FileAttributes) ReadUInt32 (); - var name = ReadString (); - ReadBlobIndex (); + var attributes = (FileAttributes) buffer.ReadUInt32 (); + var name = ReadString (ref buffer); + ReadBlobIndex (ref buffer); if (attributes != FileAttributes.ContainsMetaData) continue; @@ -688,11 +696,11 @@ void InitializeModuleReferences () if (metadata.ModuleReferences != null) return; - int length = MoveTo (Table.ModuleRef); + int length = MoveTo (Table.ModuleRef, out PByteBuffer buffer); var references = metadata.ModuleReferences = new ModuleReference [length]; for (uint i = 0; i < length; i++) { - var reference = new ModuleReference (ReadString ()); + var reference = new ModuleReference (ReadString (ref buffer)); reference.token = new MetadataToken (TokenType.ModuleRef, i + 1); references [i] = reference; @@ -708,7 +716,7 @@ public Collection ReadModuleReferences () public bool HasFileResource () { - int length = MoveTo (Table.File); + int length = MoveTo (Table.File, out PByteBuffer buffer); if (length == 0) return false; @@ -721,14 +729,14 @@ public bool HasFileResource () public Collection ReadResources () { - int length = MoveTo (Table.ManifestResource); + int length = MoveTo (Table.ManifestResource, out PByteBuffer buffer); var resources = new Collection (length); for (int i = 1; i <= length; i++) { - var offset = ReadUInt32 (); - var flags = (ManifestResourceAttributes) ReadUInt32 (); - var name = ReadString (); - var implementation = ReadMetadataToken (CodedIndex.Implementation); + var offset = buffer.ReadUInt32 (); + var flags = (ManifestResourceAttributes) buffer.ReadUInt32 (); + var name = ReadString (ref buffer); + var implementation = ReadMetadataToken (CodedIndex.Implementation, ref buffer); Resource resource; @@ -756,17 +764,13 @@ public Collection ReadResources () Row ReadFileRecord (uint rid) { - var position = this.position; - - if (!MoveTo (Table.File, rid)) + if (!MoveTo (Table.File, rid, out PByteBuffer buffer)) throw new ArgumentException (); var record = new Row ( - (FileAttributes) ReadUInt32 (), - ReadString (), - ReadBlobIndex ()); - - this.position = position; + (FileAttributes) buffer.ReadUInt32 (), + ReadString (ref buffer), + ReadBlobIndex (ref buffer)); return record; } @@ -779,21 +783,21 @@ public byte [] GetManagedResource (uint offset) }) ?? Empty.Array; } - void PopulateVersionAndFlags (AssemblyNameReference name) + void PopulateVersionAndFlags (AssemblyNameReference name, ref PByteBuffer buffer) { name.Version = new Version ( - ReadUInt16 (), - ReadUInt16 (), - ReadUInt16 (), - ReadUInt16 ()); + buffer.ReadUInt16 (), + buffer.ReadUInt16 (), + buffer.ReadUInt16 (), + buffer.ReadUInt16 ()); - name.Attributes = (AssemblyAttributes) ReadUInt32 (); + name.Attributes = (AssemblyAttributes) buffer.ReadUInt32 (); } - void PopulateNameAndCulture (AssemblyNameReference name) + void PopulateNameAndCulture (AssemblyNameReference name, ref PByteBuffer buffer) { - name.Name = ReadString (); - name.Culture = ReadString (); + name.Name = ReadString (ref buffer); + name.Culture = ReadString (ref buffer); } public TypeDefinitionCollection ReadTypes () @@ -838,7 +842,7 @@ void InitializeTypeDefinitions () InitializeFields (); InitializeMethods (); - int length = MoveTo (Table.TypeDef); + int length = image.GetTableLength (Table.TypeDef); var types = metadata.Types = new TypeDefinition [length]; for (uint i = 0; i < length; i++) { @@ -907,7 +911,7 @@ void InitializeNestedTypes () if (metadata.NestedTypes != null) return; - var length = MoveTo (Table.NestedClass); + var length = MoveTo (Table.NestedClass, out PByteBuffer buffer); metadata.NestedTypes = new Dictionary> (length); metadata.ReverseNestedTypes = new Dictionary (length); @@ -916,8 +920,8 @@ void InitializeNestedTypes () return; for (int i = 1; i <= length; i++) { - var nested = ReadTableIndex (Table.TypeDef); - var declaring = ReadTableIndex (Table.TypeDef); + var nested = ReadTableIndex (Table.TypeDef, ref buffer); + var declaring = ReadTableIndex (Table.TypeDef, ref buffer); AddNestedMapping (declaring, nested); } @@ -941,12 +945,12 @@ static Collection AddMapping (Dictionary> (length); for (uint i = 0; i < length; i++) { - var packing_size = ReadUInt16 (); - var class_size = ReadUInt32 (); + var packing_size = buffer.ReadUInt16 (); + var class_size = buffer.ReadUInt32 (); - var parent = ReadTableIndex (Table.TypeDef); + var parent = ReadTableIndex (Table.TypeDef, ref buffer); class_layouts.Add (parent, new Row (packing_size, class_size)); } @@ -1061,9 +1064,6 @@ public TypeDefinition GetTypeDefinition (uint rid) TypeDefinition ReadTypeDefinition (uint rid) { - if (!MoveTo (Table.TypeDef, rid)) - return null; - return ReadType (rid); } @@ -1110,16 +1110,16 @@ TypeReference GetTypeReference (uint rid) TypeReference ReadTypeReference (uint rid) { - if (!MoveTo (Table.TypeRef, rid)) + if (!MoveTo (Table.TypeRef, rid, out PByteBuffer buffer)) return null; TypeReference declaring_type = null; IMetadataScope scope; - var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope); + var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope, ref buffer); - var name = ReadString (); - var @namespace = ReadString (); + var name = ReadString (ref buffer); + var @namespace = ReadString (ref buffer); var type = new TypeReference ( @namespace, @@ -1197,20 +1197,28 @@ public IEnumerable GetTypeReferences () TypeReference GetTypeSpecification (uint rid) { - if (!MoveTo (Table.TypeSpec, rid)) + if (!MoveTo (Table.TypeSpec, rid, out PByteBuffer buffer)) return null; - var reader = ReadSignature (ReadBlobIndex ()); - var type = reader.ReadTypeSignature (); + var reader = ReadSignature (ReadBlobIndex (ref buffer), out PByteBuffer sig); + var type = reader.ReadTypeSignature (ref sig); if (type.token.RID == 0) type.token = new MetadataToken (TokenType.TypeSpec, rid); return type; } - SignatureReader ReadSignature (uint signature) + SignatureReader ReadSignature (uint signature, out PByteBuffer buffer) { - return new SignatureReader (signature, this); + var heapSpan = new ByteSpan (image.BlobHeap.data, image.BlobHeap.size); + var heapBuffer = new PByteBuffer (heapSpan.pointer, heapSpan.length); + heapBuffer.Advance ((int) signature); + + var length = heapBuffer.ReadCompressedUInt32 (); + + buffer = new PByteBuffer (new ByteSpan (heapBuffer.p, length)); + + return new SignatureReader (this); } public bool HasInterfaces (TypeDefinition type) @@ -1250,13 +1258,13 @@ void InitializeInterfaces () if (metadata.Interfaces != null) return; - int length = MoveTo (Table.InterfaceImpl); + int length = MoveTo (Table.InterfaceImpl, out PByteBuffer buffer); metadata.Interfaces = new Dictionary>> (length); for (uint i = 1; i <= length; i++) { - var type = ReadTableIndex (Table.TypeDef); - var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef); + var type = ReadTableIndex (Table.TypeDef, ref buffer); + var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef, ref buffer); AddInterfaceMapping (type, new Row (i, @interface)); } @@ -1276,23 +1284,23 @@ public Collection ReadFields (TypeDefinition type) var fields = new MemberDefinitionCollection (type, (int) fields_range.Length); this.context = type; - if (!MoveTo (Table.FieldPtr, fields_range.Start)) { - if (!MoveTo (Table.Field, fields_range.Start)) + if (!MoveTo (Table.FieldPtr, fields_range.Start, out PByteBuffer buffer)) { + if (!MoveTo (Table.Field, fields_range.Start, out buffer)) return fields; for (uint i = 0; i < fields_range.Length; i++) - ReadField (fields_range.Start + i, fields); + ReadField (fields_range.Start + i, fields, ref buffer); } else ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField); return fields; } - void ReadField (uint field_rid, Collection fields) + void ReadField (uint field_rid, Collection fields, ref PByteBuffer buffer) { - var attributes = (FieldAttributes) ReadUInt16 (); - var name = ReadString (); - var signature = ReadBlobIndex (); + var attributes = (FieldAttributes) buffer.ReadUInt16 (); + var name = ReadString (ref buffer); + var signature = ReadBlobIndex (ref buffer); var field = new FieldDefinition (name, attributes, ReadFieldType (signature)); field.token = new MetadataToken (TokenType.Field, field_rid); @@ -1317,14 +1325,14 @@ void InitializeFields () TypeReference ReadFieldType (uint signature) { - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); const byte field_sig = 0x6; - if (reader.ReadByte () != field_sig) + if (sig.ReadByte () != field_sig) throw new NotSupportedException (); - return reader.ReadTypeSignature (); + return reader.ReadTypeSignature (ref sig); } public int ReadFieldRVA (FieldDefinition field) @@ -1401,13 +1409,13 @@ void InitializeFieldRVAs () if (metadata.FieldRVAs != null) return; - int length = MoveTo (Table.FieldRVA); + int length = MoveTo (Table.FieldRVA, out PByteBuffer buffer); var field_rvas = metadata.FieldRVAs = new Dictionary (length); for (int i = 0; i < length; i++) { - var rva = ReadUInt32 (); - var field = ReadTableIndex (Table.Field); + var rva = buffer.ReadUInt32 (); + var field = ReadTableIndex (Table.Field, ref buffer); field_rvas.Add (field, rva); } @@ -1431,13 +1439,13 @@ void InitializeFieldLayouts () if (metadata.FieldLayouts != null) return; - int length = MoveTo (Table.FieldLayout); + int length = MoveTo (Table.FieldLayout, out PByteBuffer buffer); var field_layouts = metadata.FieldLayouts = new Dictionary (length); for (int i = 0; i < length; i++) { - var offset = ReadUInt32 (); - var field = ReadTableIndex (Table.Field); + var offset = buffer.ReadUInt32 (); + var field = ReadTableIndex (Table.Field, ref buffer); field_layouts.Add (field, offset); } @@ -1471,23 +1479,23 @@ public Collection ReadEvents (TypeDefinition type) this.context = type; - if (!MoveTo (Table.EventPtr, range.Start)) { - if (!MoveTo (Table.Event, range.Start)) + if (!MoveTo (Table.EventPtr, range.Start, out PByteBuffer buffer)) { + if (!MoveTo (Table.Event, range.Start, out buffer)) return events; for (uint i = 0; i < range.Length; i++) - ReadEvent (range.Start + i, events); + ReadEvent (range.Start + i, events, ref buffer); } else ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent); return events; } - void ReadEvent (uint event_rid, Collection events) + void ReadEvent (uint event_rid, Collection events, ref PByteBuffer buffer) { - var attributes = (EventAttributes) ReadUInt16 (); - var name = ReadString (); - var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); + var attributes = (EventAttributes) buffer.ReadUInt16 (); + var name = ReadString (ref buffer); + var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef, ref buffer)); var @event = new EventDefinition (name, attributes, event_type); @event.token = new MetadataToken (TokenType.Event, event_rid); @@ -1503,13 +1511,13 @@ void InitializeEvents () if (metadata.Events != null) return; - int length = MoveTo (Table.EventMap); + int length = MoveTo (Table.EventMap, out PByteBuffer buffer); metadata.Events = new Dictionary (length); for (uint i = 1; i <= length; i++) { - var type_rid = ReadTableIndex (Table.TypeDef); - Range events_range = ReadListRange (i, Table.EventMap, Table.Event); + var type_rid = ReadTableIndex (Table.TypeDef, ref buffer); + Range events_range = ReadListRange (i, Table.EventMap, Table.Event, ref buffer); metadata.AddEventsRange (type_rid, events_range); } } @@ -1543,36 +1551,37 @@ public Collection ReadProperties (TypeDefinition type) this.context = type; - if (!MoveTo (Table.PropertyPtr, range.Start)) { - if (!MoveTo (Table.Property, range.Start)) + if (!MoveTo (Table.PropertyPtr, range.Start, out PByteBuffer buffer)) { + if (!MoveTo (Table.Property, range.Start, out buffer)) return properties; for (uint i = 0; i < range.Length; i++) - ReadProperty (range.Start + i, properties); + ReadProperty (range.Start + i, properties, ref buffer); } else ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty); return properties; } - void ReadProperty (uint property_rid, Collection properties) + void ReadProperty (uint property_rid, Collection properties, ref PByteBuffer buffer) { - var attributes = (PropertyAttributes) ReadUInt16 (); - var name = ReadString (); - var signature = ReadBlobIndex (); + var attributes = (PropertyAttributes) buffer.ReadUInt16 (); + var name = ReadString (ref buffer); + var signature = ReadBlobIndex (ref buffer); + + var reader = ReadSignature (signature, out PByteBuffer sig); - var reader = ReadSignature (signature); const byte property_signature = 0x8; - var calling_convention = reader.ReadByte (); + var calling_convention = sig.ReadByte (); if ((calling_convention & property_signature) == 0) throw new NotSupportedException (); var has_this = (calling_convention & 0x20) != 0; - reader.ReadCompressedUInt32 (); // count + sig.ReadCompressedUInt32 (); // count - var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ()); + var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature (ref sig)); property.HasThis = has_this; property.token = new MetadataToken (TokenType.Property, property_rid); @@ -1587,13 +1596,13 @@ void InitializeProperties () if (metadata.Properties != null) return; - int length = MoveTo (Table.PropertyMap); + int length = MoveTo (Table.PropertyMap, out PByteBuffer buffer); metadata.Properties = new Dictionary (length); for (uint i = 1; i <= length; i++) { - var type_rid = ReadTableIndex (Table.TypeDef); - var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property); + var type_rid = ReadTableIndex (Table.TypeDef, ref buffer); + var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property, ref buffer); metadata.AddPropertiesRange (type_rid, properties_range); } } @@ -1687,14 +1696,14 @@ void InitializeMethodSemantics () if (metadata.Semantics != null) return; - int length = MoveTo (Table.MethodSemantics); + int length = MoveTo (Table.MethodSemantics, out PByteBuffer buffer); var semantics = metadata.Semantics = new Dictionary> (0); for (uint i = 0; i < length; i++) { - var attributes = (MethodSemanticsAttributes) ReadUInt16 (); - var method_rid = ReadTableIndex (Table.Method); - var association = ReadMetadataToken (CodedIndex.HasSemantics); + var attributes = (MethodSemanticsAttributes) buffer.ReadUInt16 (); + var method_rid = ReadTableIndex (Table.Method, ref buffer); + var association = ReadMetadataToken (CodedIndex.HasSemantics, ref buffer); semantics [method_rid] = new Row (attributes, association); } @@ -1735,28 +1744,30 @@ public Collection ReadMethods (TypeDefinition type) return new MemberDefinitionCollection (type); var methods = new MemberDefinitionCollection (type, (int) methods_range.Length); - if (!MoveTo (Table.MethodPtr, methods_range.Start)) { - if (!MoveTo (Table.Method, methods_range.Start)) + if (!MoveTo (Table.MethodPtr, methods_range.Start, out PByteBuffer buffer)) { + if (!MoveTo (Table.Method, methods_range.Start, out buffer)) return methods; for (uint i = 0; i < methods_range.Length; i++) - ReadMethod (methods_range.Start + i, methods); + ReadMethod (methods_range.Start + i, methods, ref buffer); } else ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); return methods; } - void ReadPointers (Table ptr, Table table, Range range, Collection members, Action> reader) + delegate void PointerReader (uint rid, Collection members, ref PByteBuffer buffer) where TMember : IMemberDefinition; + + void ReadPointers (Table ptr, Table table, Range range, Collection members, PointerReader reader) where TMember : IMemberDefinition { for (uint i = 0; i < range.Length; i++) { - MoveTo (ptr, range.Start + i); + MoveTo (ptr, range.Start + i, out PByteBuffer buffer); - var rid = ReadTableIndex (table); - MoveTo (table, rid); + var rid = ReadTableIndex (table, ref buffer); + MoveTo (table, rid, out buffer); - reader (rid, members); + reader (rid, members, ref buffer); } } @@ -1773,13 +1784,13 @@ void InitializeMethods () metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)]; } - void ReadMethod (uint method_rid, Collection methods) + void ReadMethod (uint method_rid, Collection methods, ref PByteBuffer buffer) { var method = new MethodDefinition (); - method.rva = ReadUInt32 (); - method.ImplAttributes = (MethodImplAttributes) ReadUInt16 (); - method.Attributes = (MethodAttributes) ReadUInt16 (); - method.Name = ReadString (); + method.rva = buffer.ReadUInt32 (); + method.ImplAttributes = (MethodImplAttributes) buffer.ReadUInt16 (); + method.Attributes = (MethodAttributes) buffer.ReadUInt16 (); + method.Name = ReadString (ref buffer); method.token = new MetadataToken (TokenType.Method, method_rid); if (IsDeleted (method)) @@ -1787,8 +1798,8 @@ void ReadMethod (uint method_rid, Collection methods) methods.Add (method); // attach method - var signature = ReadBlobIndex (); - var param_range = ReadListRange (method_rid, Table.Method, Table.Param); + var signature = ReadBlobIndex (ref buffer); + var param_range = ReadListRange (method_rid, Table.Method, Table.Param, ref buffer); this.context = method; @@ -1796,9 +1807,7 @@ void ReadMethod (uint method_rid, Collection methods) metadata.AddMethodDefinition (method); if (param_range.Length != 0) { - var position = base.position; ReadParameters (method, param_range); - base.position = position; } if (module.IsWindowsMetadata ()) @@ -1807,12 +1816,12 @@ void ReadMethod (uint method_rid, Collection methods) void ReadParameters (MethodDefinition method, Range param_range) { - if (!MoveTo (Table.ParamPtr, param_range.Start)) { - if (!MoveTo (Table.Param, param_range.Start)) + if (!MoveTo (Table.ParamPtr, param_range.Start, out PByteBuffer buffer)) { + if (!MoveTo (Table.Param, param_range.Start, out buffer)) return; for (uint i = 0; i < param_range.Length; i++) - ReadParameter (param_range.Start + i, method); + ReadParameter (param_range.Start + i, method, ref buffer); } else ReadParameterPointers (method, param_range); } @@ -1820,21 +1829,21 @@ void ReadParameters (MethodDefinition method, Range param_range) void ReadParameterPointers (MethodDefinition method, Range range) { for (uint i = 0; i < range.Length; i++) { - MoveTo (Table.ParamPtr, range.Start + i); + MoveTo (Table.ParamPtr, range.Start + i, out PByteBuffer buffer); - var rid = ReadTableIndex (Table.Param); + var rid = ReadTableIndex (Table.Param, ref buffer); - MoveTo (Table.Param, rid); + MoveTo (Table.Param, rid, out buffer); - ReadParameter (rid, method); + ReadParameter (rid, method, ref buffer); } } - void ReadParameter (uint param_rid, MethodDefinition method) + void ReadParameter (uint param_rid, MethodDefinition method, ref PByteBuffer buffer) { - var attributes = (ParameterAttributes) ReadUInt16 (); - var sequence = ReadUInt16 (); - var name = ReadString (); + var attributes = (ParameterAttributes) buffer.ReadUInt16 (); + var sequence = buffer.ReadUInt16 (); + var name = ReadString (ref buffer); var parameter = sequence == 0 ? method.MethodReturnType.Parameter @@ -1847,8 +1856,8 @@ void ReadParameter (uint param_rid, MethodDefinition method) void ReadMethodSignature (uint signature, IMethodSignature method) { - var reader = ReadSignature (signature); - reader.ReadMethodSignature (method); + var reader = ReadSignature (signature, out PByteBuffer sig); + reader.ReadMethodSignature (method, ref sig); } public PInvokeInfo ReadPInvokeInfo (MethodDefinition method) @@ -1874,15 +1883,15 @@ void InitializePInvokes () if (metadata.PInvokes != null) return; - int length = MoveTo (Table.ImplMap); + int length = MoveTo (Table.ImplMap, out PByteBuffer buffer); var pinvokes = metadata.PInvokes = new Dictionary> (length); for (int i = 1; i <= length; i++) { - var attributes = (PInvokeAttributes) ReadUInt16 (); - var method = ReadMetadataToken (CodedIndex.MemberForwarded); - var name = ReadStringIndex (); - var scope = ReadTableIndex (Table.File); + var attributes = (PInvokeAttributes) buffer.ReadUInt16 (); + var method = ReadMetadataToken (CodedIndex.MemberForwarded, ref buffer); + var name = ReadStringIndex (ref buffer); + var scope = ReadTableIndex (Table.File, ref buffer); if (method.TokenType != TokenType.Method) continue; @@ -1922,14 +1931,14 @@ public Collection ReadGenericParameters (IGenericParameterProv void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters) { - if (!MoveTo (Table.GenericParam, range.Start)) + if (!MoveTo (Table.GenericParam, range.Start, out PByteBuffer buffer)) return; for (uint i = 0; i < range.Length; i++) { - ReadUInt16 (); // index - var flags = (GenericParameterAttributes) ReadUInt16 (); - ReadMetadataToken (CodedIndex.TypeOrMethodDef); - var name = ReadString (); + buffer.ReadUInt16 (); // index + var flags = (GenericParameterAttributes) buffer.ReadUInt16 (); + ReadMetadataToken (CodedIndex.TypeOrMethodDef, ref buffer); + var name = ReadString (ref buffer); var parameter = new GenericParameter (name, provider); parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i); @@ -1945,17 +1954,19 @@ void InitializeGenericParameters () return; metadata.GenericParameters = InitializeRanges ( - Table.GenericParam, () => { - Advance (4); - var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef); - ReadStringIndex (); + Table.GenericParam, (ref PByteBuffer buffer) => { + buffer.Advance (4); + var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef, ref buffer); + ReadStringIndex (ref buffer); return next; }); } - Dictionary InitializeRanges (Table table, Func get_next) + delegate MetadataToken NextInRangeReader (ref PByteBuffer buffer); + + Dictionary InitializeRanges (Table table, NextInRangeReader get_next) { - int length = MoveTo (table); + int length = MoveTo (table, out PByteBuffer buffer); var ranges = new Dictionary (length); if (length == 0) @@ -1965,7 +1976,7 @@ Dictionary InitializeRanges (Table table, Func>> (length); for (uint i = 1; i <= length; i++) { AddGenericConstraintMapping ( - ReadTableIndex (Table.GenericParam), - new Row (i, ReadMetadataToken (CodedIndex.TypeDefOrRef))); + ReadTableIndex (Table.GenericParam, ref buffer), + new Row (i, ReadMetadataToken (CodedIndex.TypeDefOrRef, ref buffer))); } } @@ -2091,18 +2102,18 @@ void InitializeOverrides () if (metadata.Overrides != null) return; - var length = MoveTo (Table.MethodImpl); + var length = MoveTo (Table.MethodImpl, out PByteBuffer buffer); metadata.Overrides = new Dictionary> (length); for (int i = 1; i <= length; i++) { - ReadTableIndex (Table.TypeDef); + ReadTableIndex (Table.TypeDef, ref buffer); - var method = ReadMetadataToken (CodedIndex.MethodDefOrRef); + var method = ReadMetadataToken (CodedIndex.MethodDefOrRef, ref buffer); if (method.TokenType != TokenType.Method) throw new NotSupportedException (); - var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef); + var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef, ref buffer); AddOverrideMapping (method.RID, @override); } @@ -2127,10 +2138,10 @@ public int ReadCodeSize (MethodDefinition method) public CallSite ReadCallSite (MetadataToken token) { - if (!MoveTo (Table.StandAloneSig, token.RID)) + if (!MoveTo (Table.StandAloneSig, token.RID, out PByteBuffer buffer)) return null; - var signature = ReadBlobIndex (); + var signature = ReadBlobIndex (ref buffer); var call_site = new CallSite (); @@ -2143,23 +2154,24 @@ public CallSite ReadCallSite (MetadataToken token) public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) { - if (!MoveTo (Table.StandAloneSig, local_var_token.RID)) + if (!MoveTo (Table.StandAloneSig, local_var_token.RID, out PByteBuffer buffer)) return null; - var reader = ReadSignature (ReadBlobIndex ()); + var reader = ReadSignature (ReadBlobIndex (ref buffer), out PByteBuffer sig); + const byte local_sig = 0x7; - if (reader.ReadByte () != local_sig) + if (sig.ReadByte () != local_sig) throw new NotSupportedException (); - var count = reader.ReadCompressedUInt32 (); + var count = sig.ReadCompressedUInt32 (); if (count == 0) return null; var variables = new VariableDefinitionCollection ((int) count); for (int i = 0; i < count; i++) - variables.Add (new VariableDefinition (reader.ReadTypeSignature ())); + variables.Add (new VariableDefinition (reader.ReadTypeSignature (ref sig))); return variables; } @@ -2175,7 +2187,6 @@ public IMetadataTokenProvider LookupToken (MetadataToken token) return metadata_reader.LookupToken (token); IMetadataTokenProvider element; - var position = this.position; var context = this.context; switch (token.TokenType) { @@ -2204,7 +2215,6 @@ public IMetadataTokenProvider LookupToken (MetadataToken token) return null; } - this.position = position; this.context = context; return element; @@ -2256,12 +2266,12 @@ MethodDefinition LookupMethod (uint rid) MethodSpecification GetMethodSpecification (uint rid) { - if (!MoveTo (Table.MethodSpec, rid)) + if (!MoveTo (Table.MethodSpec, rid, out PByteBuffer buffer)) return null; var element_method = (MethodReference) LookupToken ( - ReadMetadataToken (CodedIndex.MethodDefOrRef)); - var signature = ReadBlobIndex (); + ReadMetadataToken (CodedIndex.MethodDefOrRef, ref buffer)); + var signature = ReadBlobIndex (ref buffer); var method_spec = ReadMethodSpecSignature (signature, element_method); method_spec.token = new MetadataToken (TokenType.MethodSpec, rid); @@ -2270,19 +2280,19 @@ MethodSpecification GetMethodSpecification (uint rid) MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method) { - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); const byte methodspec_sig = 0x0a; - var call_conv = reader.ReadByte (); + var call_conv = sig.ReadByte (); if (call_conv != methodspec_sig) throw new NotSupportedException (); - var arity = reader.ReadCompressedUInt32 (); + var arity = sig.ReadCompressedUInt32 (); var instance = new GenericInstanceMethod (method, (int) arity); - reader.ReadGenericInstanceSignature (method, instance, arity); + reader.ReadGenericInstanceSignature (method, instance, arity, ref sig); return instance; } @@ -2303,12 +2313,12 @@ MemberReference GetMemberReference (uint rid) MemberReference ReadMemberReference (uint rid) { - if (!MoveTo (Table.MemberRef, rid)) + if (!MoveTo (Table.MemberRef, rid, out PByteBuffer buffer)) return null; - var token = ReadMetadataToken (CodedIndex.MemberRefParent); - var name = ReadString (); - var signature = ReadBlobIndex (); + var token = ReadMetadataToken (CodedIndex.MemberRefParent, ref buffer); + var name = ReadString (ref buffer); + var signature = ReadBlobIndex (ref buffer); MemberReference member; @@ -2348,19 +2358,20 @@ MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint s MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type) { - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); + const byte field_sig = 0x6; - if (reader.buffer [reader.position] == field_sig) { - reader.position++; + if (sig.PeekByte () == field_sig) { + sig.Advance (1); var field = new FieldReference (); field.DeclaringType = declaring_type; - field.FieldType = reader.ReadTypeSignature (); + field.FieldType = reader.ReadTypeSignature (ref sig); return field; } else { var method = new MethodReference (); method.DeclaringType = declaring_type; - reader.ReadMethodSignature (method); + reader.ReadMethodSignature (method, ref sig); return method; } } @@ -2411,14 +2422,14 @@ void InitializeConstants () if (metadata.Constants != null) return; - var length = MoveTo (Table.Constant); + var length = MoveTo (Table.Constant, out PByteBuffer buffer); var constants = metadata.Constants = new Dictionary> (length); for (uint i = 1; i <= length; i++) { - var type = (ElementType) ReadUInt16 (); - var owner = ReadMetadataToken (CodedIndex.HasConstant); - var signature = ReadBlobIndex (); + var type = (ElementType) buffer.ReadUInt16 (); + var owner = ReadMetadataToken (CodedIndex.HasConstant, ref buffer); + var signature = ReadBlobIndex (ref buffer); constants.Add (owner, new Row (type, signature)); } @@ -2432,10 +2443,10 @@ public TypeReference ReadConstantSignature (MetadataToken token) if (token.RID == 0) return null; - if (!MoveTo (Table.StandAloneSig, token.RID)) + if (!MoveTo (Table.StandAloneSig, token.RID, out PByteBuffer buffer)) return null; - return ReadFieldType (ReadBlobIndex ()); + return ReadFieldType (ReadBlobIndex (ref buffer)); } public object ReadConstant (IConstantProvider owner) @@ -2481,8 +2492,8 @@ string ReadConstantString (uint signature) object ReadConstantPrimitive (ElementType type, uint signature) { - var reader = ReadSignature (signature); - return reader.ReadConstantSignature (type); + var reader = ReadSignature (signature, out PByteBuffer sig); + return reader.ReadConstantSignature (type, ref sig); } internal void InitializeCustomAttributes () @@ -2491,10 +2502,10 @@ internal void InitializeCustomAttributes () return; metadata.CustomAttributes = InitializeRanges ( - Table.CustomAttribute, () => { - var next = ReadMetadataToken (CodedIndex.HasCustomAttribute); - ReadMetadataToken (CodedIndex.CustomAttributeType); - ReadBlobIndex (); + Table.CustomAttribute, (ref PByteBuffer buffer) => { + var next = ReadMetadataToken (CodedIndex.HasCustomAttribute, ref buffer); + ReadMetadataToken (CodedIndex.CustomAttributeType, ref buffer); + ReadBlobIndex (ref buffer); return next; }); } @@ -2534,16 +2545,16 @@ public Collection ReadCustomAttributes (ICustomAttributeProvide void ReadCustomAttributeRange (Range range, Collection custom_attributes) { - if (!MoveTo (Table.CustomAttribute, range.Start)) + if (!MoveTo (Table.CustomAttribute, range.Start, out PByteBuffer buffer)) return; for (var i = 0; i < range.Length; i++) { - ReadMetadataToken (CodedIndex.HasCustomAttribute); + ReadMetadataToken (CodedIndex.HasCustomAttribute, ref buffer); var constructor = (MethodReference) LookupToken ( - ReadMetadataToken (CodedIndex.CustomAttributeType)); + ReadMetadataToken (CodedIndex.CustomAttributeType, ref buffer)); - var signature = ReadBlobIndex (); + var signature = ReadBlobIndex (ref buffer); custom_attributes.Add (new CustomAttribute (signature, constructor)); } @@ -2576,27 +2587,27 @@ public byte [] ReadCustomAttributeBlob (uint signature) public void ReadCustomAttributeSignature (CustomAttribute attribute) { - var reader = ReadSignature (attribute.signature); + var reader = ReadSignature (attribute.signature, out PByteBuffer sig); - if (!reader.CanReadMore ()) + if (!sig.CanReadMore ()) return; - if (reader.ReadUInt16 () != 0x0001) + if (sig.ReadUInt16 () != 0x0001) throw new InvalidOperationException (); var constructor = attribute.Constructor; if (constructor.HasParameters) - reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters); + reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters, ref sig); - if (!reader.CanReadMore ()) + if (!sig.CanReadMore ()) return; - var named = reader.ReadUInt16 (); + var named = sig.ReadUInt16 (); if (named == 0) return; - reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties); + reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties, ref sig); } void InitializeMarshalInfos () @@ -2604,13 +2615,13 @@ void InitializeMarshalInfos () if (metadata.FieldMarshals != null) return; - var length = MoveTo (Table.FieldMarshal); + var length = MoveTo (Table.FieldMarshal, out PByteBuffer buffer); var marshals = metadata.FieldMarshals = new Dictionary (length); for (int i = 0; i < length; i++) { - var token = ReadMetadataToken (CodedIndex.HasFieldMarshal); - var signature = ReadBlobIndex (); + var token = ReadMetadataToken (CodedIndex.HasFieldMarshal, ref buffer); + var signature = ReadBlobIndex (ref buffer); if (token.RID == 0) continue; @@ -2633,11 +2644,11 @@ public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner) if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature)) return null; - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); metadata.FieldMarshals.Remove (owner.MetadataToken); - return reader.ReadMarshalInfo (); + return reader.ReadMarshalInfo (ref sig); } void InitializeSecurityDeclarations () @@ -2646,10 +2657,10 @@ void InitializeSecurityDeclarations () return; metadata.SecurityDeclarations = InitializeRanges ( - Table.DeclSecurity, () => { - ReadUInt16 (); - var next = ReadMetadataToken (CodedIndex.HasDeclSecurity); - ReadBlobIndex (); + Table.DeclSecurity, (ref PByteBuffer buffer) => { + buffer.ReadUInt16 (); + var next = ReadMetadataToken (CodedIndex.HasDeclSecurity, ref buffer); + ReadBlobIndex (ref buffer); return next; }); } @@ -2685,13 +2696,13 @@ public Collection ReadSecurityDeclarations (ISecurityDeclar void ReadSecurityDeclarationRange (Range range, Collection security_declarations) { - if (!MoveTo (Table.DeclSecurity, range.Start)) + if (!MoveTo (Table.DeclSecurity, range.Start, out PByteBuffer buffer)) return; for (int i = 0; i < range.Length; i++) { - var action = (SecurityAction) ReadUInt16 (); - ReadMetadataToken (CodedIndex.HasDeclSecurity); - var signature = ReadBlobIndex (); + var action = (SecurityAction) buffer.ReadUInt16 (); + ReadMetadataToken (CodedIndex.HasDeclSecurity, ref buffer); + var signature = ReadBlobIndex (ref buffer); security_declarations.Add (new SecurityDeclaration (action, signature, module)); } @@ -2705,19 +2716,19 @@ public byte [] ReadSecurityDeclarationBlob (uint signature) public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration) { var signature = declaration.signature; - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); - if (reader.buffer [reader.position] != '.') { + if (sig.PeekByte () != '.') { ReadXmlSecurityDeclaration (signature, declaration); return; } - reader.position++; - var count = reader.ReadCompressedUInt32 (); + sig.Advance (1); + var count = sig.ReadCompressedUInt32 (); var attributes = new Collection ((int) count); for (int i = 0; i < count; i++) - attributes.Add (reader.ReadSecurityAttribute ()); + attributes.Add (reader.ReadSecurityAttribute (ref sig)); declaration.security_attributes = attributes; } @@ -2744,18 +2755,18 @@ void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration public Collection ReadExportedTypes () { - var length = MoveTo (Table.ExportedType); + var length = MoveTo (Table.ExportedType, out PByteBuffer buffer); if (length == 0) return new Collection (); var exported_types = new Collection (length); for (int i = 1; i <= length; i++) { - var attributes = (TypeAttributes) ReadUInt32 (); - var identifier = ReadUInt32 (); - var name = ReadString (); - var @namespace = ReadString (); - var implementation = ReadMetadataToken (CodedIndex.Implementation); + var attributes = (TypeAttributes) buffer.ReadUInt32 (); + var identifier = buffer.ReadUInt32 (); + var name = ReadString (ref buffer); + var @namespace = ReadString (ref buffer); + var implementation = ReadMetadataToken (CodedIndex.Implementation, ref buffer); ExportedType declaring_type = null; IMetadataScope scope = null; @@ -2786,7 +2797,6 @@ public Collection ReadExportedTypes () IMetadataScope GetExportedTypeScope (MetadataToken token) { - var position = this.position; IMetadataScope scope; switch (token.TokenType) { @@ -2802,17 +2812,16 @@ IMetadataScope GetExportedTypeScope (MetadataToken token) throw new NotSupportedException (); } - this.position = position; return scope; } ModuleReference GetModuleReferenceFromFile (MetadataToken token) { - if (!MoveTo (Table.File, token.RID)) + if (!MoveTo (Table.File, token.RID, out PByteBuffer buffer)) return null; - ReadUInt32 (); - var file_name = ReadString (); + buffer.Advance (4); + var file_name = ReadString (ref buffer); var modules = module.ModuleReferences; ModuleReference reference; @@ -2832,18 +2841,18 @@ void InitializeDocuments () if (metadata.Documents != null) return; - int length = MoveTo (Table.Document); + int length = MoveTo (Table.Document, out PByteBuffer buffer); var documents = metadata.Documents = new Document [length]; for (uint i = 1; i <= length; i++) { - var name_index = ReadBlobIndex (); - var hash_algorithm = ReadGuid (); - var hash = ReadBlob (); - var language = ReadGuid (); + var name_index = ReadBlobIndex (ref buffer); + var hash_algorithm = ReadGuid (ref buffer); + var hash = ReadBlob (ref buffer); + var language = ReadGuid (ref buffer); - var signature = ReadSignature (name_index); - var name = signature.ReadDocumentName (); + var signature = ReadSignature (name_index, out PByteBuffer sig); + var name = signature.ReadDocumentName (ref sig); documents [i - 1] = new Document (name) { HashAlgorithmGuid = hash_algorithm, @@ -2858,18 +2867,18 @@ public Collection ReadSequencePoints (MethodDefinition method) { InitializeDocuments (); - if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID)) + if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID, out PByteBuffer buffer)) return new Collection (0); - var document_index = ReadTableIndex (Table.Document); - var signature = ReadBlobIndex (); + var document_index = ReadTableIndex (Table.Document, ref buffer); + var signature = ReadBlobIndex (ref buffer); if (signature == 0) return new Collection (0); var document = GetDocument (document_index); - var reader = ReadSignature (signature); + var reader = ReadSignature (signature, out PByteBuffer sig); - return reader.ReadSequencePoints (document); + return reader.ReadSequencePoints (document, ref sig); } public Document GetDocument (uint rid) @@ -2889,17 +2898,17 @@ void InitializeLocalScopes () InitializeMethods (); - int length = MoveTo (Table.LocalScope); + int length = MoveTo (Table.LocalScope, out PByteBuffer buffer); metadata.LocalScopes = new Dictionary>> (); for (uint i = 1; i <= length; i++) { - var method = ReadTableIndex (Table.Method); - var import = ReadTableIndex (Table.ImportScope); - var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable); - var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant); - var scope_start = ReadUInt32 (); - var scope_length = ReadUInt32 (); + var method = ReadTableIndex (Table.Method, ref buffer); + var import = ReadTableIndex (Table.ImportScope, ref buffer); + var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable, ref buffer); + var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant, ref buffer); + var scope_start = buffer.ReadUInt32 (); + var scope_length = buffer.ReadUInt32 (); metadata.SetLocalScopes (method, AddMapping (metadata.LocalScopes, method, new Row (import, variables, constants, scope_start, scope_length, i))); } @@ -2984,12 +2993,12 @@ ScopeDebugInformation ReadLocalScope (Row VariableDebugInformation ReadLocalVariable (uint rid) { - if (!MoveTo (Table.LocalVariable, rid)) + if (!MoveTo (Table.LocalVariable, rid, out PByteBuffer buffer)) return null; - var attributes = (VariableAttributes) ReadUInt16 (); - var index = ReadUInt16 (); - var name = ReadString (); + var attributes = (VariableAttributes) buffer.ReadUInt16 (); + var index = buffer.ReadUInt16 (); + var name = ReadString (ref buffer); var variable = new VariableDebugInformation (index, name) { Attributes = attributes, token = new MetadataToken (TokenType.LocalVariable, rid) }; variable.custom_infos = GetCustomDebugInformation (variable); @@ -2998,29 +3007,29 @@ VariableDebugInformation ReadLocalVariable (uint rid) ConstantDebugInformation ReadLocalConstant (uint rid) { - if (!MoveTo (Table.LocalConstant, rid)) + if (!MoveTo (Table.LocalConstant, rid, out PByteBuffer buffer)) return null; - var name = ReadString (); - var signature = ReadSignature (ReadBlobIndex ()); - var type = signature.ReadTypeSignature (); + var name = ReadString (ref buffer); + var signature = ReadSignature (ReadBlobIndex (ref buffer), out PByteBuffer sig); + var type = signature.ReadTypeSignature (ref sig); object value; if (type.etype == ElementType.String) { - if (signature.buffer [signature.position] != 0xff) { - var bytes = signature.ReadBytes ((int) (signature.sig_length - (signature.position - signature.start))); + if (sig.PeekByte () != 0xff) { + var bytes = sig.ReadBytes ((int) (sig.e - sig.p)); value = Encoding.Unicode.GetString (bytes, 0, bytes.Length); } else value = null; } else if (type.IsTypeOf ("System", "Decimal")) { - var b = signature.ReadByte (); - value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte) (b & 0x7f)); + var bb = sig.ReadByte (); + value = new decimal (sig.ReadInt32 (), sig.ReadInt32 (), sig.ReadInt32 (), (bb & 0x80) != 0, (byte) (bb & 0x7f)); } else if (type.IsTypeOf ("System", "DateTime")) { - value = new DateTime (signature.ReadInt64()); + value = new DateTime (sig.ReadInt64()); } else if (type.etype == ElementType.Object || type.etype == ElementType.None || type.etype == ElementType.Class) { value = null; } else - value = signature.ReadConstantSignature (type.etype); + value = signature.ReadConstantSignature (type.etype, ref sig); var constant = new ConstantDebugInformation (name, type, value) { token = new MetadataToken (TokenType.LocalConstant, rid) }; constant.custom_infos = GetCustomDebugInformation (constant); @@ -3032,29 +3041,29 @@ void InitializeImportScopes () if (metadata.ImportScopes != null) return; - var length = MoveTo (Table.ImportScope); + var length = MoveTo (Table.ImportScope, out PByteBuffer buffer); metadata.ImportScopes = new ImportDebugInformation [length]; for (int i = 1; i <= length; i++) { - ReadTableIndex (Table.ImportScope); + ReadTableIndex (Table.ImportScope, ref buffer); var import = new ImportDebugInformation (); import.token = new MetadataToken (TokenType.ImportScope, i); - var signature = ReadSignature (ReadBlobIndex ()); - while (signature.CanReadMore ()) - import.Targets.Add (ReadImportTarget (signature)); + var reader = ReadSignature (ReadBlobIndex (ref buffer), out PByteBuffer sig); + while (sig.CanReadMore ()) + import.Targets.Add (ReadImportTarget (reader, ref sig)); metadata.ImportScopes [i - 1] = import; } - MoveTo (Table.ImportScope); + MoveTo (Table.ImportScope, out buffer); for (int i = 0; i < length; i++) { - var parent = ReadTableIndex (Table.ImportScope); + var parent = ReadTableIndex (Table.ImportScope, ref buffer); - ReadBlobIndex (); + ReadBlobIndex (ref buffer); if (parent != 0) metadata.ImportScopes [i].Parent = metadata.GetImportScope (parent); @@ -3083,48 +3092,48 @@ string ReadStringBlob (uint signature, Encoding encoding) return encoding.GetString (blob, index, count); } - ImportTarget ReadImportTarget (SignatureReader signature) + ImportTarget ReadImportTarget (SignatureReader signature, ref PByteBuffer sig) { AssemblyNameReference reference = null; string @namespace = null; string alias = null; TypeReference type = null; - var kind = (ImportTargetKind) signature.ReadCompressedUInt32 (); + var kind = (ImportTargetKind) sig.ReadCompressedUInt32 (); switch (kind) { case ImportTargetKind.ImportNamespace: - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.ImportNamespaceInAssembly: - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + reference = metadata.GetAssemblyNameReference (sig.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.ImportType: - type = signature.ReadTypeToken (); + type = signature.ReadTypeToken (ref sig); break; case ImportTargetKind.ImportXmlNamespaceWithAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.ImportAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.DefineAssemblyAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); + reference = metadata.GetAssemblyNameReference (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.DefineNamespaceAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.DefineNamespaceInAssemblyAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); + reference = metadata.GetAssemblyNameReference (sig.ReadCompressedUInt32 ()); + @namespace = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); break; case ImportTargetKind.DefineTypeAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - type = signature.ReadTypeToken (); + alias = ReadUTF8StringBlob (sig.ReadCompressedUInt32 ()); + type = signature.ReadTypeToken (ref sig); break; } @@ -3141,12 +3150,12 @@ void InitializeStateMachineMethods () if (metadata.StateMachineMethods != null) return; - var length = MoveTo (Table.StateMachineMethod); + var length = MoveTo (Table.StateMachineMethod, out PByteBuffer buffer); metadata.StateMachineMethods = new Dictionary (length); for (int i = 0; i < length; i++) - metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method), ReadTableIndex (Table.Method)); + metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method, ref buffer), ReadTableIndex (Table.Method, ref buffer)); } public MethodDefinition ReadStateMachineKickoffMethod (MethodDefinition method) @@ -3165,13 +3174,13 @@ void InitializeCustomDebugInformations () if (metadata.CustomDebugInformations != null) return; - var length = MoveTo (Table.CustomDebugInformation); + var length = MoveTo (Table.CustomDebugInformation, out PByteBuffer buffer); metadata.CustomDebugInformations = new Dictionary []> (); for (uint i = 1; i <= length; i++) { - var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation); - var info = new Row (ReadGuid (), ReadBlobIndex (), i); + var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation, ref buffer); + var info = new Row (ReadGuid (ref buffer), ReadBlobIndex (ref buffer), i); Row [] infos; metadata.CustomDebugInformations.TryGetValue (token, out infos); @@ -3191,12 +3200,13 @@ public Collection GetCustomDebugInformation (ICustomDebu for (int i = 0; i < rows.Length; i++) { if (rows [i].Col1 == StateMachineScopeDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); + ReadSignature (rows [i].Col2, out PByteBuffer sig); + var scopes = new Collection (); - while (signature.CanReadMore ()) { - var start = signature.ReadInt32 (); - var end = start + signature.ReadInt32 (); + while (sig.CanReadMore ()) { + var start = sig.ReadInt32 (); + var end = start + sig.ReadInt32 (); scopes.Add (new StateMachineScope (start, end)); } @@ -3205,17 +3215,17 @@ public Collection GetCustomDebugInformation (ICustomDebu infos.Add (state_machine); } else if (rows [i].Col1 == AsyncMethodBodyDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); + ReadSignature (rows [i].Col2, out PByteBuffer sig); - var catch_offset = signature.ReadInt32 () - 1; + var catch_offset = sig.ReadInt32 () - 1; var yields = new Collection (); var resumes = new Collection (); var resume_methods = new Collection (); - while (signature.CanReadMore ()) { - yields.Add (new InstructionOffset (signature.ReadInt32 ())); - resumes.Add (new InstructionOffset (signature.ReadInt32 ())); - resume_methods.Add (GetMethodDefinition (signature.ReadCompressedUInt32 ())); + while (sig.CanReadMore ()) { + yields.Add (new InstructionOffset (sig.ReadInt32 ())); + resumes.Add (new InstructionOffset (sig.ReadInt32 ())); + resume_methods.Add (GetMethodDefinition (sig.ReadCompressedUInt32 ())); } var async_body = new AsyncMethodBodyDebugInformation (catch_offset); @@ -3225,16 +3235,17 @@ public Collection GetCustomDebugInformation (ICustomDebu infos.Add (async_body); } else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); - var format = signature.ReadInt32 (); - var length = signature.sig_length - 4; + ReadSignature (rows [i].Col2, out PByteBuffer sig); + + var format = sig.ReadInt32 (); + var length = sig.span.length - 4; var info = null as CustomDebugInformation; if (format == 0) { - info = new EmbeddedSourceDebugInformation (signature.ReadBytes ((int) length), compress: false); + info = new EmbeddedSourceDebugInformation (sig.ReadBytes ((int) length), compress: false); } else if (format > 0) { - var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); + var compressed_stream = new MemoryStream (sig.ReadBytes ((int) length)); var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document var decompressed_stream = new MemoryStream (decompressed_document); @@ -3260,27 +3271,22 @@ public Collection GetCustomDebugInformation (ICustomDebu } } - sealed class SignatureReader : ByteBuffer { + ref struct SignatureReader { readonly MetadataReader reader; - readonly internal uint start, sig_length; TypeSystem TypeSystem { get { return reader.module.TypeSystem; } } - public SignatureReader (uint blob, MetadataReader reader) - : base (reader.image.BlobHeap.data) + public SignatureReader (MetadataReader reader) { this.reader = reader; - this.position = (int) blob; - this.sig_length = ReadCompressedUInt32(); - this.start = (uint) this.position; } - MetadataToken ReadTypeTokenSignature () + MetadataToken ReadTypeTokenSignature (ref PByteBuffer buffer) { - return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ()); + return CodedIndex.TypeDefOrRef.GetMetadataToken (buffer.ReadCompressedUInt32 ()); } GenericParameter GetGenericParameter (GenericParameterType type, uint var) @@ -3326,7 +3332,7 @@ static void CheckGenericContext (IGenericParameterProvider owner, int index) owner_parameters.Add (new GenericParameter (owner)); } - public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance, uint arity) + public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance, uint arity, ref PByteBuffer buffer) { if (!provider.IsDefinition) CheckGenericContext (provider, (int) arity - 1); @@ -3334,22 +3340,22 @@ public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IG var instance_arguments = instance.GenericArguments; for (int i = 0; i < arity; i++) - instance_arguments.Add (ReadTypeSignature ()); + instance_arguments.Add (ReadTypeSignature (ref buffer)); } - ArrayType ReadArrayTypeSignature () + ArrayType ReadArrayTypeSignature (ref PByteBuffer buffer) { - var array = new ArrayType (ReadTypeSignature ()); + var array = new ArrayType (ReadTypeSignature (ref buffer)); - var rank = ReadCompressedUInt32 (); + var rank = buffer.ReadCompressedUInt32 (); - var sizes = new uint [ReadCompressedUInt32 ()]; + var sizes = new uint [buffer.ReadCompressedUInt32 ()]; for (int i = 0; i < sizes.Length; i++) - sizes [i] = ReadCompressedUInt32 (); + sizes [i] = buffer.ReadCompressedUInt32 (); - var low_bounds = new int [ReadCompressedUInt32 ()]; + var low_bounds = new int [buffer.ReadCompressedUInt32 ()]; for (int i = 0; i < low_bounds.Length; i++) - low_bounds [i] = ReadCompressedInt32 (); + low_bounds [i] = buffer.ReadCompressedInt32 (); array.Dimensions.Clear (); @@ -3373,61 +3379,61 @@ TypeReference GetTypeDefOrRef (MetadataToken token) return reader.GetTypeDefOrRef (token); } - public TypeReference ReadTypeSignature () + public TypeReference ReadTypeSignature (ref PByteBuffer buffer) { - return ReadTypeSignature ((ElementType) ReadByte ()); + return ReadTypeSignature ((ElementType) buffer.ReadByte (), ref buffer); } - public TypeReference ReadTypeToken () + public TypeReference ReadTypeToken (ref PByteBuffer buffer) { - return GetTypeDefOrRef (ReadTypeTokenSignature ()); + return GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)); } - TypeReference ReadTypeSignature (ElementType etype) + TypeReference ReadTypeSignature (ElementType etype, ref PByteBuffer buffer) { switch (etype) { case ElementType.ValueType: { - var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); + var value_type = GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)); value_type.KnownValueType (); return value_type; } case ElementType.Class: - return GetTypeDefOrRef (ReadTypeTokenSignature ()); + return GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)); case ElementType.Ptr: - return new PointerType (ReadTypeSignature ()); + return new PointerType (ReadTypeSignature (ref buffer)); case ElementType.FnPtr: { var fptr = new FunctionPointerType (); - ReadMethodSignature (fptr); + ReadMethodSignature (fptr, ref buffer); return fptr; } case ElementType.ByRef: - return new ByReferenceType (ReadTypeSignature ()); + return new ByReferenceType (ReadTypeSignature (ref buffer)); case ElementType.Pinned: - return new PinnedType (ReadTypeSignature ()); + return new PinnedType (ReadTypeSignature (ref buffer)); case ElementType.SzArray: - return new ArrayType (ReadTypeSignature ()); + return new ArrayType (ReadTypeSignature (ref buffer)); case ElementType.Array: - return ReadArrayTypeSignature (); + return ReadArrayTypeSignature (ref buffer); case ElementType.CModOpt: return new OptionalModifierType ( - GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); + GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)), ReadTypeSignature (ref buffer)); case ElementType.CModReqD: return new RequiredModifierType ( - GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); + GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)), ReadTypeSignature (ref buffer)); case ElementType.Sentinel: - return new SentinelType (ReadTypeSignature ()); + return new SentinelType (ReadTypeSignature (ref buffer)); case ElementType.Var: - return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ()); + return GetGenericParameter (GenericParameterType.Type, buffer.ReadCompressedUInt32 ()); case ElementType.MVar: - return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ()); + return GetGenericParameter (GenericParameterType.Method, buffer.ReadCompressedUInt32 ()); case ElementType.GenericInst: { - var is_value_type = ReadByte () == (byte) ElementType.ValueType; - var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); + var is_value_type = buffer.ReadByte () == (byte) ElementType.ValueType; + var element_type = GetTypeDefOrRef (ReadTypeTokenSignature (ref buffer)); - var arity = ReadCompressedUInt32 (); - var generic_instance = new GenericInstanceType (element_type, (int) arity); + var arity = buffer.ReadCompressedUInt32 (); + var generic_instance = new GenericInstanceType (element_type); - ReadGenericInstanceSignature (element_type, generic_instance, arity); + ReadGenericInstanceSignature (element_type, generic_instance, arity, ref buffer); if (is_value_type) { generic_instance.KnownValueType (); @@ -3445,9 +3451,9 @@ TypeReference ReadTypeSignature (ElementType etype) } } - public void ReadMethodSignature (IMethodSignature method) + public void ReadMethodSignature (IMethodSignature method, ref PByteBuffer buffer) { - var calling_convention = ReadByte (); + var calling_convention = buffer.ReadByte (); const byte has_this = 0x20; const byte explicit_this = 0x40; @@ -3469,15 +3475,15 @@ public void ReadMethodSignature (IMethodSignature method) reader.context = generic_context; if ((calling_convention & 0x10) != 0) { - var arity = ReadCompressedUInt32 (); + var arity = buffer.ReadCompressedUInt32 (); if (generic_context != null && !generic_context.IsDefinition) CheckGenericContext (generic_context, (int) arity -1 ); } - var param_count = ReadCompressedUInt32 (); + var param_count = buffer.ReadCompressedUInt32 (); - method.MethodReturnType.ReturnType = ReadTypeSignature (); + method.MethodReturnType.ReturnType = ReadTypeSignature (ref buffer); if (param_count == 0) return; @@ -3491,15 +3497,15 @@ public void ReadMethodSignature (IMethodSignature method) parameters = method.Parameters; for (int i = 0; i < param_count; i++) - parameters.Add (new ParameterDefinition (ReadTypeSignature ())); + parameters.Add (new ParameterDefinition (ReadTypeSignature (ref buffer))); } - public object ReadConstantSignature (ElementType type) + public object ReadConstantSignature (ElementType type, ref PByteBuffer buffer) { - return ReadPrimitiveValue (type); + return ReadPrimitiveValue (type, ref buffer); } - public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection parameters) + public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection parameters, ref PByteBuffer buffer) { var count = parameters.Count; if (count == 0) @@ -3509,31 +3515,31 @@ public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, for (int i = 0; i < count; i++) attribute.arguments.Add ( - ReadCustomAttributeFixedArgument (parameters [i].ParameterType)); + ReadCustomAttributeFixedArgument (parameters [i].ParameterType, ref buffer)); } - CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type) + CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type, ref PByteBuffer buffer) { if (type.IsArray) - return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); + return ReadCustomAttributeFixedArrayArgument ((ArrayType) type, ref buffer); - return ReadCustomAttributeElement (type); + return ReadCustomAttributeElement (type, ref buffer); } - public void ReadCustomAttributeNamedArguments (ushort count, ref Collection fields, ref Collection properties) + public void ReadCustomAttributeNamedArguments (ushort count, ref Collection fields, ref Collection properties, ref PByteBuffer buffer) { for (int i = 0; i < count; i++) { - if (!CanReadMore ()) + if (!buffer.CanReadMore ()) return; - ReadCustomAttributeNamedArgument (ref fields, ref properties); + ReadCustomAttributeNamedArgument (ref fields, ref properties, ref buffer); } } - void ReadCustomAttributeNamedArgument (ref Collection fields, ref Collection properties) + void ReadCustomAttributeNamedArgument (ref Collection fields, ref Collection properties, ref PByteBuffer buffer) { - var kind = ReadByte (); - var type = ReadCustomAttributeFieldOrPropType (); - var name = ReadUTF8String (); + var kind = buffer.ReadByte (); + var type = ReadCustomAttributeFieldOrPropType (ref buffer); + var name = ReadUTF8String (ref buffer); Collection container; switch (kind) { @@ -3547,7 +3553,7 @@ void ReadCustomAttributeNamedArgument (ref Collection GetCustomAttributeNamedArgumentCollection (ref Collection collection) @@ -3558,9 +3564,9 @@ static Collection GetCustomAttributeNamedArgumentC return collection = new Collection (); } - CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type) + CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type, ref PByteBuffer buffer) { - var length = ReadUInt32 (); + var length = buffer.ReadUInt32 (); if (length == 0xffffffff) return new CustomAttributeArgument (type, null); @@ -3572,67 +3578,67 @@ CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type) var element_type = type.ElementType; for (int i = 0; i < length; i++) - arguments [i] = ReadCustomAttributeElement (element_type); + arguments [i] = ReadCustomAttributeElement (element_type, ref buffer); return new CustomAttributeArgument (type, arguments); } - CustomAttributeArgument ReadCustomAttributeElement (TypeReference type) + CustomAttributeArgument ReadCustomAttributeElement (TypeReference type, ref PByteBuffer buffer) { if (type.IsArray) - return ReadCustomAttributeFixedArrayArgument ((ArrayType) type); + return ReadCustomAttributeFixedArrayArgument ((ArrayType) type, ref buffer); return new CustomAttributeArgument ( type, type.etype == ElementType.Object - ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ()) - : ReadCustomAttributeElementValue (type)); + ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType (ref buffer), ref buffer) + : ReadCustomAttributeElementValue (type, ref buffer)); } - object ReadCustomAttributeElementValue (TypeReference type) + object ReadCustomAttributeElementValue (TypeReference type, ref PByteBuffer buffer) { var etype = type.etype; switch (etype) { case ElementType.String: - return ReadUTF8String (); + return ReadUTF8String (ref buffer); case ElementType.None: if (type.IsTypeOf ("System", "Type")) - return ReadTypeReference (); + return ReadTypeReference (ref buffer); - return ReadCustomAttributeEnum (type); + return ReadCustomAttributeEnum (type, ref buffer); default: - return ReadPrimitiveValue (etype); + return ReadPrimitiveValue (etype, ref buffer); } } - object ReadPrimitiveValue (ElementType type) + object ReadPrimitiveValue (ElementType type, ref PByteBuffer buffer) { switch (type) { case ElementType.Boolean: - return ReadByte () == 1; + return buffer.ReadByte () == 1; case ElementType.I1: - return (sbyte) ReadByte (); + return (sbyte) buffer.ReadByte (); case ElementType.U1: - return ReadByte (); + return buffer.ReadByte (); case ElementType.Char: - return (char) ReadUInt16 (); + return (char) buffer.ReadUInt16 (); case ElementType.I2: - return ReadInt16 (); + return buffer.ReadInt16 (); case ElementType.U2: - return ReadUInt16 (); + return buffer.ReadUInt16 (); case ElementType.I4: - return ReadInt32 (); + return buffer.ReadInt32 (); case ElementType.U4: - return ReadUInt32 (); + return buffer.ReadUInt32 (); case ElementType.I8: - return ReadInt64 (); + return buffer.ReadInt64 (); case ElementType.U8: - return ReadUInt64 (); + return buffer.ReadUInt64 (); case ElementType.R4: - return ReadSingle (); + return buffer.ReadSingle (); case ElementType.R8: - return ReadDouble (); + return buffer.ReadDouble (); default: throw new NotImplementedException (type.ToString ()); } @@ -3672,17 +3678,17 @@ TypeReference GetPrimitiveType (ElementType etype) } } - TypeReference ReadCustomAttributeFieldOrPropType () + TypeReference ReadCustomAttributeFieldOrPropType (ref PByteBuffer buffer) { - var etype = (ElementType) ReadByte (); + var etype = (ElementType) buffer.ReadByte (); switch (etype) { case ElementType.Boxed: return TypeSystem.Object; case ElementType.SzArray: - return new ArrayType (ReadCustomAttributeFieldOrPropType ()); + return new ArrayType (ReadCustomAttributeFieldOrPropType (ref buffer)); case ElementType.Enum: - return ReadTypeReference (); + return ReadTypeReference (ref buffer); case ElementType.Type: return TypeSystem.LookupType ("System", "Type"); default: @@ -3690,77 +3696,78 @@ TypeReference ReadCustomAttributeFieldOrPropType () } } - public TypeReference ReadTypeReference () + public TypeReference ReadTypeReference (ref PByteBuffer buffer) { - return TypeParser.ParseType (reader.module, ReadUTF8String ()); + return TypeParser.ParseType (reader.module, ReadUTF8String (ref buffer)); } - object ReadCustomAttributeEnum (TypeReference enum_type) + object ReadCustomAttributeEnum (TypeReference enum_type, ref PByteBuffer buffer) { var type = enum_type.CheckedResolve (); if (!type.IsEnum) throw new ArgumentException (); - return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ()); + return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType (), ref buffer); } - public SecurityAttribute ReadSecurityAttribute () + public SecurityAttribute ReadSecurityAttribute (ref PByteBuffer buffer) { - var attribute = new SecurityAttribute (ReadTypeReference ()); + var attribute = new SecurityAttribute (ReadTypeReference (ref buffer)); - ReadCompressedUInt32 (); + buffer.ReadCompressedUInt32 (); ReadCustomAttributeNamedArguments ( - (ushort) ReadCompressedUInt32 (), + (ushort) buffer.ReadCompressedUInt32 (), ref attribute.fields, - ref attribute.properties); + ref attribute.properties, + ref buffer); return attribute; } - public MarshalInfo ReadMarshalInfo () + public MarshalInfo ReadMarshalInfo (ref PByteBuffer buffer) { - var native = ReadNativeType (); + var native = ReadNativeType (ref buffer); switch (native) { case NativeType.Array: { var array = new ArrayMarshalInfo (); - if (CanReadMore ()) - array.element_type = ReadNativeType (); - if (CanReadMore ()) - array.size_parameter_index = (int) ReadCompressedUInt32 (); - if (CanReadMore ()) - array.size = (int) ReadCompressedUInt32 (); - if (CanReadMore ()) - array.size_parameter_multiplier = (int) ReadCompressedUInt32 (); + if (buffer.CanReadMore ()) + array.element_type = ReadNativeType (ref buffer); + if (buffer.CanReadMore ()) + array.size_parameter_index = (int) buffer.ReadCompressedUInt32 (); + if (buffer.CanReadMore ()) + array.size = (int) buffer.ReadCompressedUInt32 (); + if (buffer.CanReadMore ()) + array.size_parameter_multiplier = (int) buffer.ReadCompressedUInt32 (); return array; } case NativeType.SafeArray: { var array = new SafeArrayMarshalInfo (); - if (CanReadMore ()) - array.element_type = ReadVariantType (); + if (buffer.CanReadMore ()) + array.element_type = ReadVariantType (ref buffer); return array; } case NativeType.FixedArray: { var array = new FixedArrayMarshalInfo (); - if (CanReadMore ()) - array.size = (int) ReadCompressedUInt32 (); - if (CanReadMore ()) - array.element_type = ReadNativeType (); + if (buffer.CanReadMore ()) + array.size = (int) buffer.ReadCompressedUInt32 (); + if (buffer.CanReadMore ()) + array.element_type = ReadNativeType (ref buffer); return array; } case NativeType.FixedSysString: { var sys_string = new FixedSysStringMarshalInfo (); - if (CanReadMore ()) - sys_string.size = (int) ReadCompressedUInt32 (); + if (buffer.CanReadMore ()) + sys_string.size = (int) buffer.ReadCompressedUInt32 (); return sys_string; } case NativeType.CustomMarshaler: { var marshaler = new CustomMarshalInfo (); - var guid_value = ReadUTF8String (); + var guid_value = ReadUTF8String (ref buffer); marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty; - marshaler.unmanaged_type = ReadUTF8String (); - marshaler.managed_type = ReadTypeReference (); - marshaler.cookie = ReadUTF8String (); + marshaler.unmanaged_type = ReadUTF8String (ref buffer); + marshaler.managed_type = ReadTypeReference (ref buffer); + marshaler.cookie = ReadUTF8String (ref buffer); return marshaler; } default: @@ -3768,47 +3775,42 @@ public MarshalInfo ReadMarshalInfo () } } - NativeType ReadNativeType () + NativeType ReadNativeType (ref PByteBuffer buffer) { - return (NativeType) ReadByte (); + return (NativeType) buffer.ReadByte (); } - VariantType ReadVariantType () + VariantType ReadVariantType (ref PByteBuffer buffer) { - return (VariantType) ReadByte (); + return (VariantType) buffer.ReadByte (); } - string ReadUTF8String () + string ReadUTF8String (ref PByteBuffer buffer) { - if (buffer [position] == 0xff) { - position++; + if (buffer.PeekByte () == 0xff) { + buffer.Advance (1); return null; } - var length = (int) ReadCompressedUInt32 (); + var length = (int) buffer.ReadCompressedUInt32 (); if (length == 0) return string.Empty; - if (position + length > buffer.Length) - return string.Empty; - - var @string = Encoding.UTF8.GetString (buffer, position, length); + var bytes = buffer.ReadBytes (length); - position += length; - return @string; + return Encoding.UTF8.GetString (bytes); } - public string ReadDocumentName () + public string ReadDocumentName (ref PByteBuffer buffer) { - var separator = (char) buffer [position]; - position++; + var separator = (char) buffer.ReadByte (); var builder = new StringBuilder (); - for (int i = 0; CanReadMore (); i++) { + for (int i = 0; buffer.CanReadMore (); i++) { if (i > 0 && separator != 0) builder.Append (separator); - uint part = ReadCompressedUInt32 (); + uint part = buffer.ReadCompressedUInt32 (); if (part != 0) builder.Append (reader.ReadUTF8StringBlob (part)); } @@ -3816,38 +3818,37 @@ public string ReadDocumentName () return builder.ToString (); } - public Collection ReadSequencePoints (Document document) + public Collection ReadSequencePoints (Document document, ref PByteBuffer buffer) { - ReadCompressedUInt32 (); // local_sig_token + buffer.ReadCompressedUInt32 (); // local_sig_token if (document == null) - document = reader.GetDocument (ReadCompressedUInt32 ()); + document = reader.GetDocument (buffer.ReadCompressedUInt32 ()); var offset = 0; var start_line = 0; var start_column = 0; var first_non_hidden = true; - //there's about 5 compressed int32's per sequenec points. we don't know exactly how many + //there's about 5 compressed int32's per sequence points. we don't know exactly how many //but let's take a conservative guess so we dont end up reallocating the sequence_points collection //as it grows. - var bytes_remaining_for_sequencepoints = sig_length - (position - start); - var estimated_sequencepoint_amount = (int)bytes_remaining_for_sequencepoints / 5; + var estimated_sequencepoint_amount = (int) buffer.RemainingBytes () / 5; var sequence_points = new Collection (estimated_sequencepoint_amount); - for (var i = 0; CanReadMore (); i++) { - var delta_il = (int) ReadCompressedUInt32 (); + for (var i = 0; buffer.CanReadMore (); i++) { + var delta_il = (int) buffer.ReadCompressedUInt32 (); if (i > 0 && delta_il == 0) { - document = reader.GetDocument (ReadCompressedUInt32 ()); + document = reader.GetDocument (buffer.ReadCompressedUInt32 ()); continue; } offset += delta_il; - var delta_lines = (int) ReadCompressedUInt32 (); + var delta_lines = (int) buffer.ReadCompressedUInt32 (); var delta_columns = delta_lines == 0 - ? (int) ReadCompressedUInt32 () - : ReadCompressedInt32 (); + ? (int) buffer.ReadCompressedUInt32 () + : buffer.ReadCompressedInt32 (); if (delta_lines == 0 && delta_columns == 0) { sequence_points.Add (new SequencePoint (offset, document) { @@ -3860,11 +3861,11 @@ public Collection ReadSequencePoints (Document document) } if (first_non_hidden) { - start_line = (int) ReadCompressedUInt32 (); - start_column = (int) ReadCompressedUInt32 (); + start_line = (int) buffer.ReadCompressedUInt32 (); + start_column = (int) buffer.ReadCompressedUInt32 (); } else { - start_line += ReadCompressedInt32 (); - start_column += ReadCompressedInt32 (); + start_line += buffer.ReadCompressedInt32 (); + start_column += buffer.ReadCompressedInt32 (); } sequence_points.Add (new SequencePoint (offset, document) { @@ -3878,10 +3879,5 @@ public Collection ReadSequencePoints (Document document) return sequence_points; } - - public bool CanReadMore () - { - return (position - start) < sig_length; - } } } diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index 3ea1088b3..dc3f0beba 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -117,6 +117,7 @@ static void Write (ModuleDefinition module, Disposable stream, WriterPar using (var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters)) { metadata.SetSymbolWriter (symbol_writer); BuildMetadata (module, metadata); + module.symbol_reader = null; if (parameters.DeterministicMvid) metadata.ComputeDeterministicMvid (); diff --git a/Mono.Cecil/ModuleDefinition.cs b/Mono.Cecil/ModuleDefinition.cs index 707a1358f..05a6b07b9 100644 --- a/Mono.Cecil/ModuleDefinition.cs +++ b/Mono.Cecil/ModuleDefinition.cs @@ -923,12 +923,10 @@ internal object SyncRoot { internal void Read (TItem item, Action read) { lock (module_lock) { - var position = reader.position; var context = reader.context; read (item, reader); - reader.position = position; reader.context = context; } } @@ -936,12 +934,10 @@ internal void Read (TItem item, Action read) internal TRet Read (TItem item, Func read) { lock (module_lock) { - var position = reader.position; var context = reader.context; var ret = read (item, reader); - reader.position = position; reader.context = context; return ret; @@ -954,12 +950,10 @@ internal TRet Read (ref TRet variable, TItem item, Func (); } - public byte[] GetDebugInfo (out ImageDebugDirectory idd) + public byte [] GetDebugInfo (out ImageDebugDirectory idd) { int size; // get size of debug info writer.GetDebugInfo (out idd, 0, out size, null); - byte[] debug_info = new byte[size]; + byte [] debug_info = new byte [size]; writer.GetDebugInfo (out idd, size, out size, debug_info); return debug_info;