170 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //
 | |
| // Author:
 | |
| //   Jb Evain (jbevain@gmail.com)
 | |
| //
 | |
| // Copyright (c) 2008 - 2015 Jb Evain
 | |
| // Copyright (c) 2008 - 2011 Novell, Inc.
 | |
| //
 | |
| // Licensed under the MIT/X11 license.
 | |
| //
 | |
| 
 | |
| using MonoFN.Cecil.Cil;
 | |
| using MonoFN.Cecil.Metadata;
 | |
| using System;
 | |
| using System.IO;
 | |
| using RVA = System.UInt32;
 | |
| 
 | |
| namespace MonoFN.Cecil.PE {
 | |
| 
 | |
| 	sealed class Image : IDisposable {
 | |
| 
 | |
| 		public Disposable<Stream> Stream;
 | |
| 		public string FileName;
 | |
| 
 | |
| 		public ModuleKind Kind;
 | |
| 		public uint Characteristics;
 | |
| 		public string RuntimeVersion;
 | |
| 		public TargetArchitecture Architecture;
 | |
| 		public ModuleCharacteristics DllCharacteristics;
 | |
| 		public ushort LinkerVersion;
 | |
| 		public ushort SubSystemMajor;
 | |
| 		public ushort SubSystemMinor;
 | |
| 
 | |
| 		public ImageDebugHeader DebugHeader;
 | |
| 
 | |
| 		public Section [] Sections;
 | |
| 
 | |
| 		public Section MetadataSection;
 | |
| 
 | |
| 		public uint EntryPointToken;
 | |
| 		public uint Timestamp;
 | |
| 		public ModuleAttributes Attributes;
 | |
| 
 | |
| 		public DataDirectory Win32Resources;
 | |
| 		public DataDirectory Debug;
 | |
| 		public DataDirectory Resources;
 | |
| 		public DataDirectory StrongName;
 | |
| 
 | |
| 		public StringHeap StringHeap;
 | |
| 		public BlobHeap BlobHeap;
 | |
| 		public UserStringHeap UserStringHeap;
 | |
| 		public GuidHeap GuidHeap;
 | |
| 		public TableHeap TableHeap;
 | |
| 		public PdbHeap PdbHeap;
 | |
| 
 | |
| 		readonly int [] coded_index_sizes = new int [14];
 | |
| 
 | |
| 		readonly Func<Table, int> counter;
 | |
| 
 | |
| 		public Image ()
 | |
| 		{
 | |
| 			counter = GetTableLength;
 | |
| 		}
 | |
| 
 | |
| 		public bool HasTable (Table table)
 | |
| 		{
 | |
| 			return GetTableLength (table) > 0;
 | |
| 		}
 | |
| 
 | |
| 		public int GetTableLength (Table table)
 | |
| 		{
 | |
| 			return (int)TableHeap [table].Length;
 | |
| 		}
 | |
| 
 | |
| 		public int GetTableIndexSize (Table table)
 | |
| 		{
 | |
| 			return GetTableLength (table) < 65536 ? 2 : 4;
 | |
| 		}
 | |
| 
 | |
| 		public int GetCodedIndexSize (CodedIndex coded_index)
 | |
| 		{
 | |
| 			var index = (int)coded_index;
 | |
| 			var size = coded_index_sizes [index];
 | |
| 			if (size != 0)
 | |
| 				return size;
 | |
| 
 | |
| 			return coded_index_sizes [index] = coded_index.GetSize (counter);
 | |
| 		}
 | |
| 
 | |
| 		public uint ResolveVirtualAddress (RVA rva)
 | |
| 		{
 | |
| 			var section = GetSectionAtVirtualAddress (rva);
 | |
| 			if (section == null)
 | |
| 				throw new ArgumentOutOfRangeException ();
 | |
| 
 | |
| 			return ResolveVirtualAddressInSection (rva, section);
 | |
| 		}
 | |
| 
 | |
| 		public uint ResolveVirtualAddressInSection (RVA rva, Section section)
 | |
| 		{
 | |
| 			return rva + section.PointerToRawData - section.VirtualAddress;
 | |
| 		}
 | |
| 
 | |
| 		public Section GetSection (string name)
 | |
| 		{
 | |
| 			var sections = this.Sections;
 | |
| 			for (int i = 0; i < sections.Length; i++) {
 | |
| 				var section = sections [i];
 | |
| 				if (section.Name == name)
 | |
| 					return section;
 | |
| 			}
 | |
| 
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		public Section GetSectionAtVirtualAddress (RVA rva)
 | |
| 		{
 | |
| 			var sections = this.Sections;
 | |
| 			for (int i = 0; i < sections.Length; i++) {
 | |
| 				var section = sections [i];
 | |
| 				if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData)
 | |
| 					return section;
 | |
| 			}
 | |
| 
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		BinaryStreamReader GetReaderAt (RVA rva)
 | |
| 		{
 | |
| 			var section = GetSectionAtVirtualAddress (rva);
 | |
| 			if (section == null)
 | |
| 				return null;
 | |
| 
 | |
| 			var reader = new BinaryStreamReader (Stream.value);
 | |
| 			reader.MoveTo (ResolveVirtualAddressInSection (rva, section));
 | |
| 			return reader;
 | |
| 		}
 | |
| 
 | |
| 		public TRet GetReaderAt<TItem, TRet> (RVA rva, TItem item, Func<TItem, BinaryStreamReader, TRet> read) where TRet : class
 | |
| 		{
 | |
| 			var position = Stream.value.Position;
 | |
| 			try {
 | |
| 				var reader = GetReaderAt (rva);
 | |
| 				if (reader == null)
 | |
| 					return null;
 | |
| 
 | |
| 				return read (item, reader);
 | |
| 			}
 | |
| 			finally {
 | |
| 				Stream.value.Position = position;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public bool HasDebugTables ()
 | |
| 		{
 | |
| 			return HasTable (Table.Document)
 | |
| 				|| HasTable (Table.MethodDebugInformation)
 | |
| 				|| HasTable (Table.LocalScope)
 | |
| 				|| HasTable (Table.LocalVariable)
 | |
| 				|| HasTable (Table.LocalConstant)
 | |
| 				|| HasTable (Table.StateMachineMethod)
 | |
| 				|| HasTable (Table.CustomDebugInformation);
 | |
| 		}
 | |
| 
 | |
| 		public void Dispose ()
 | |
| 		{
 | |
| 			Stream.Dispose ();
 | |
| 		}
 | |
| 	}
 | |
| }
 |