diff options
author | Jb Evain <jbevain@gmail.com> | 2011-10-27 16:53:07 +0400 |
---|---|---|
committer | Jb Evain <jbevain@gmail.com> | 2011-10-27 16:53:07 +0400 |
commit | 8771de6415d3fa5e34b12fd90519a5405c02e8b2 (patch) | |
tree | 0a1707ab3fc77c49d3f5f6f51628089ccffb1d19 /Mono.Cecil.PE | |
parent | ecdd7454b53a4d6b57c9eb2a500b91025a63b401 (diff) |
First pass at a branch with reduced memory usage; Keeps an open handle on the file, dispose your modules
Diffstat (limited to 'Mono.Cecil.PE')
-rw-r--r-- | Mono.Cecil.PE/BinaryStreamReader.cs | 18 | ||||
-rw-r--r-- | Mono.Cecil.PE/ByteBuffer.cs | 6 | ||||
-rw-r--r-- | Mono.Cecil.PE/Image.cs | 50 | ||||
-rw-r--r-- | Mono.Cecil.PE/ImageReader.cs | 61 | ||||
-rw-r--r-- | Mono.Cecil.PE/ImageWriter.cs | 5 | ||||
-rw-r--r-- | Mono.Cecil.PE/Section.cs | 1 |
6 files changed, 74 insertions, 67 deletions
diff --git a/Mono.Cecil.PE/BinaryStreamReader.cs b/Mono.Cecil.PE/BinaryStreamReader.cs index ec2477c..77a8b44 100644 --- a/Mono.Cecil.PE/BinaryStreamReader.cs +++ b/Mono.Cecil.PE/BinaryStreamReader.cs @@ -33,17 +33,31 @@ namespace Mono.Cecil.PE { class BinaryStreamReader : BinaryReader { + public int Position { + get { return (int) BaseStream.Position; } + set { BaseStream.Position = value; } + } + + public int Length { + get { return (int) BaseStream.Length; } + } + public BinaryStreamReader (Stream stream) : base (stream) { } - protected void Advance (int bytes) + public void Advance (int bytes) { BaseStream.Seek (bytes, SeekOrigin.Current); } - protected DataDirectory ReadDataDirectory () + public void MoveTo (uint position) + { + BaseStream.Seek (position, SeekOrigin.Begin); + } + + public DataDirectory ReadDataDirectory () { return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); } diff --git a/Mono.Cecil.PE/ByteBuffer.cs b/Mono.Cecil.PE/ByteBuffer.cs index c7ae7ae..4f32c09 100644 --- a/Mono.Cecil.PE/ByteBuffer.cs +++ b/Mono.Cecil.PE/ByteBuffer.cs @@ -52,12 +52,6 @@ namespace Mono.Cecil.PE { this.length = this.buffer.Length; } - public void Reset (byte [] buffer) - { - this.buffer = buffer ?? Empty<byte>.Array; - this.length = this.buffer.Length; - } - public void Advance (int length) { position += length; diff --git a/Mono.Cecil.PE/Image.cs b/Mono.Cecil.PE/Image.cs index 9a04494..8971b13 100644 --- a/Mono.Cecil.PE/Image.cs +++ b/Mono.Cecil.PE/Image.cs @@ -27,8 +27,8 @@ // using System; +using System.IO; -using Mono; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; @@ -36,12 +36,13 @@ using RVA = System.UInt32; namespace Mono.Cecil.PE { - sealed class Image { + sealed class Image : IDisposable { + + public Stream Stream; public ModuleKind Kind; public TargetRuntime Runtime; public TargetArchitecture Architecture; - public string FileName; public Section [] Sections; @@ -131,29 +132,42 @@ namespace Mono.Cecil.PE { return null; } + public BinaryStreamReader GetReaderAt (RVA rva) + { + var reader = new BinaryStreamReader (Stream); + reader.MoveTo (ResolveVirtualAddress (rva)); + return reader; + } + public ImageDebugDirectory GetDebugHeader (out byte [] header) { - var section = GetSectionAtVirtualAddress (Debug.VirtualAddress); - var buffer = new ByteBuffer (section.Data); - buffer.position = (int) (Debug.VirtualAddress - section.VirtualAddress); + var reader = GetReaderAt (Debug.VirtualAddress); var directory = new ImageDebugDirectory { - Characteristics = buffer.ReadInt32 (), - TimeDateStamp = buffer.ReadInt32 (), - MajorVersion = buffer.ReadInt16 (), - MinorVersion = buffer.ReadInt16 (), - Type = buffer.ReadInt32 (), - SizeOfData = buffer.ReadInt32 (), - AddressOfRawData = buffer.ReadInt32 (), - PointerToRawData = buffer.ReadInt32 (), + Characteristics = reader.ReadInt32 (), + TimeDateStamp = reader.ReadInt32 (), + MajorVersion = reader.ReadInt16 (), + MinorVersion = reader.ReadInt16 (), + Type = reader.ReadInt32 (), + SizeOfData = reader.ReadInt32 (), + AddressOfRawData = reader.ReadInt32 (), + PointerToRawData = reader.ReadInt32 (), }; - buffer.position = (int) (directory.PointerToRawData - section.PointerToRawData); + reader = GetReaderAt ((uint) directory.AddressOfRawData); + header = reader.ReadBytes (directory.SizeOfData); + return directory; + } - header = new byte [directory.SizeOfData]; - Buffer.BlockCopy (buffer.buffer, buffer.position, header, 0, header.Length); + ~Image () + { + if (Stream != null) + Stream.Dispose (); + } - return directory; + public void Dispose () + { + Stream.Dispose (); } } } diff --git a/Mono.Cecil.PE/ImageReader.cs b/Mono.Cecil.PE/ImageReader.cs index 734b00a..1205e0b 100644 --- a/Mono.Cecil.PE/ImageReader.cs +++ b/Mono.Cecil.PE/ImageReader.cs @@ -42,12 +42,13 @@ namespace Mono.Cecil.PE { DataDirectory cli; DataDirectory metadata; + uint table_heap_offset; + public ImageReader (Stream stream) : base (stream) { image = new Image (); - - image.FileName = stream.GetFullyQualifiedName (); + image.Stream = stream; } void MoveTo (DataDirectory directory) @@ -55,11 +56,6 @@ namespace Mono.Cecil.PE { BaseStream.Position = image.ResolveVirtualAddress (directory.VirtualAddress); } - void MoveTo (uint position) - { - BaseStream.Position = position; - } - void ReadImage () { if (BaseStream.Length < 128) @@ -275,31 +271,11 @@ namespace Mono.Cecil.PE { Advance (16); sections [i] = section; - - ReadSectionData (section); } image.Sections = sections; } - void ReadSectionData (Section section) - { - var position = BaseStream.Position; - - MoveTo (section.PointerToRawData); - - var length = (int) section.SizeOfRawData; - var data = new byte [length]; - int offset = 0, read; - - while ((read = Read (data, offset, length - offset)) > 0) - offset += read; - - section.Data = data; - - BaseStream.Position = position; - } - void ReadCLIHeader () { MoveTo (cli); @@ -362,39 +338,50 @@ namespace Mono.Cecil.PE { void ReadMetadataStream (Section section) { // Offset 4 - uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start + uint offset = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start // Size 4 uint size = ReadUInt32 (); + var data = ReadHeapData (offset, size); + var name = ReadAlignedString (16); switch (name) { case "#~": case "#-": - image.TableHeap = new TableHeap (section, start, size); + image.TableHeap = new TableHeap (data); + table_heap_offset = offset; break; case "#Strings": - image.StringHeap = new StringHeap (section, start, size); + image.StringHeap = new StringHeap (data); break; case "#Blob": - image.BlobHeap = new BlobHeap (section, start, size); + image.BlobHeap = new BlobHeap (data); break; case "#GUID": - image.GuidHeap = new GuidHeap (section, start, size); + image.GuidHeap = new GuidHeap (data); break; case "#US": - image.UserStringHeap = new UserStringHeap (section, start, size); + image.UserStringHeap = new UserStringHeap (data); 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; - uint start = heap.Section.PointerToRawData; - - MoveTo (heap.Offset + start); + MoveTo (table_heap_offset + image.MetadataSection.PointerToRawData); // Reserved 4 // MajorVersion 1 @@ -447,7 +434,7 @@ namespace Mono.Cecil.PE { void ComputeTableInformations () { - uint offset = (uint) BaseStream.Position - image.MetadataSection.PointerToRawData; // header + uint offset = (uint) BaseStream.Position - table_heap_offset - image.MetadataSection.PointerToRawData; // header int stridx_size = image.StringHeap.IndexSize; int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; diff --git a/Mono.Cecil.PE/ImageWriter.cs b/Mono.Cecil.PE/ImageWriter.cs index 6f921d9..b5cdbe9 100644 --- a/Mono.Cecil.PE/ImageWriter.cs +++ b/Mono.Cecil.PE/ImageWriter.cs @@ -95,9 +95,8 @@ namespace Mono.Cecil.PE { if (rsrc == null) return; - var raw_resources = new byte [rsrc.Data.Length]; - Buffer.BlockCopy (rsrc.Data, 0, raw_resources, 0, rsrc.Data.Length); - win32_resources = new ByteBuffer (raw_resources); + var reader = module.Image.GetReaderAt (rsrc.VirtualAddress); + win32_resources = new ByteBuffer (reader.ReadBytes ((int) rsrc.SizeOfRawData)); } Section GetImageResourceSection () diff --git a/Mono.Cecil.PE/Section.cs b/Mono.Cecil.PE/Section.cs index 6a4c7ba..938d1a2 100644 --- a/Mono.Cecil.PE/Section.cs +++ b/Mono.Cecil.PE/Section.cs @@ -38,6 +38,5 @@ namespace Mono.Cecil.PE { public uint VirtualSize; public uint SizeOfRawData; public uint PointerToRawData; - public byte [] Data; } } |