using System; using System.IO; using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.PE; using Mono.Cecil.Metadata; using NUnit.Framework; namespace Mono.Cecil.Tests { [TestFixture] public class ImageReadTests : BaseTestFixture { [Test] public void ImageSections () { using (var image = GetResourceImage ("hello.exe")) { Assert.AreEqual (3, image.Sections.Length); Assert.AreEqual (".text", image.Sections [0].Name); Assert.AreEqual (".rsrc", image.Sections [1].Name); Assert.AreEqual (".reloc", image.Sections [2].Name); } } [Test] public void ImageMetadataVersion () { using (var image = GetResourceImage ("hello.exe")) Assert.AreEqual (TargetRuntime.Net_2_0, image.RuntimeVersion.ParseRuntime ()); using (var image = GetResourceImage ("hello1.exe")) Assert.AreEqual (TargetRuntime.Net_1_1, image.RuntimeVersion.ParseRuntime ()); } [Test] public void ImageModuleKind () { using (var image = GetResourceImage ("hello.exe")) Assert.AreEqual (ModuleKind.Console, image.Kind); using (var image = GetResourceImage ("libhello.dll")) Assert.AreEqual (ModuleKind.Dll, image.Kind); using (var image = GetResourceImage ("hellow.exe")) Assert.AreEqual (ModuleKind.Windows, image.Kind); } [Test] public void MetadataHeaps () { using (var image = GetResourceImage ("hello.exe")) { Assert.IsNotNull (image.TableHeap); Assert.IsNotNull (image.StringHeap); Assert.AreEqual (string.Empty, image.StringHeap.Read (0)); Assert.AreEqual ("", image.StringHeap.Read (1)); Assert.IsNotNull (image.UserStringHeap); Assert.AreEqual (string.Empty, image.UserStringHeap.Read (0)); Assert.AreEqual ("Hello Cecil World !", image.UserStringHeap.Read (1)); Assert.IsNotNull (image.GuidHeap); Assert.AreEqual (new Guid (), image.GuidHeap.Read (0)); Assert.AreEqual (new Guid ("C3BC2BD3-2576-4D00-A80E-465B5632415F"), image.GuidHeap.Read (1)); Assert.IsNotNull (image.BlobHeap); Assert.AreEqual (new byte [0], image.BlobHeap.Read (0)); } } [Test] public void TablesHeap () { using (var image = GetResourceImage ("hello.exe")) { var heap = image.TableHeap; Assert.IsNotNull (heap); Assert.AreEqual (1, heap [Table.Module].Length); Assert.AreEqual (4, heap [Table.TypeRef].Length); Assert.AreEqual (2, heap [Table.TypeDef].Length); Assert.AreEqual (0, heap [Table.Field].Length); Assert.AreEqual (2, heap [Table.Method].Length); Assert.AreEqual (4, heap [Table.MemberRef].Length); Assert.AreEqual (2, heap [Table.CustomAttribute].Length); Assert.AreEqual (1, heap [Table.Assembly].Length); Assert.AreEqual (1, heap [Table.AssemblyRef].Length); } } [Test] public void X64Module () { TestModule ("hello.x64.exe", module => { Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); }, verify: !Platform.OnMono); } [Test] public void AnyCPU32BitPreferred () { TestModule ("anycpu32bitpreferred.exe", module => { Assert.AreNotEqual (0, module.Image.Characteristics & 0x0020); }); } [Test] public void X64ModuleTextOnlySection () { TestModule ("hello.textonly.x64.exe", module => { Assert.AreEqual (TargetArchitecture.AMD64, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); }, verify: !Platform.OnMono); } [Test] public void IA64Module () { TestModule ("hello.ia64.exe", module => { Assert.AreEqual (TargetArchitecture.IA64, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); }, verify: !Platform.OnMono); } [Test] public void X86Module () { TestModule ("hello.x86.exe", module => { Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly | ModuleAttributes.Required32Bit, module.Image.Attributes); }); } [Test] public void AnyCpuModule () { TestModule ("hello.anycpu.exe", module => { Assert.AreEqual (TargetArchitecture.I386, module.Image.Architecture); Assert.AreEqual (ModuleAttributes.ILOnly, module.Image.Attributes); }); } [Test] public void DelaySignedAssembly () { TestModule ("delay-signed.dll", module => { Assert.IsNotNull (module.Assembly.Name.PublicKey); Assert.AreNotEqual (0, module.Assembly.Name.PublicKey.Length); Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); Assert.AreNotEqual (0, module.Image.StrongName.VirtualAddress); Assert.AreNotEqual (0, module.Image.StrongName.Size); }); } [Test] public void WindowsPhoneNonSignedAssembly () { TestModule ("wp7.dll", module => { Assert.AreEqual (0, module.Assembly.Name.PublicKey.Length); Assert.AreNotEqual (ModuleAttributes.StrongNameSigned, module.Attributes & ModuleAttributes.StrongNameSigned); Assert.AreEqual (0, module.Image.StrongName.VirtualAddress); Assert.AreEqual (0, module.Image.StrongName.Size); }, verify: false); } [Test] public void MetroAssembly () { if (Platform.OnMono) return; TestModule ("metro.exe", module => { Assert.AreEqual (ModuleCharacteristics.AppContainer, module.Characteristics & ModuleCharacteristics.AppContainer); }, verify: false); } #if !NET_CORE [Test] public void WindowsRuntimeComponentAssembly () { var resolver = WindowsRuntimeAssemblyResolver.CreateInstance (); if (resolver == null) return; TestModule("winrtcomp.winmd", module => { Assert.IsTrue (module.Assembly.Name.IsWindowsRuntime); Assert.AreEqual (6, module.Image.SubSystemMajor); Assert.AreEqual (2, module.Image.SubSystemMinor); }, verify: false, assemblyResolver: resolver); } #endif [Test] public void DeterministicAssembly () { TestModule ("Deterministic.dll", module => { Assert.IsTrue (module.HasDebugHeader); var header = module.GetDebugHeader (); Assert.AreEqual (1, header.Entries.Length); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.Deterministic)); }); } [Test] public void Net471TargetingAssembly () { TestModule ("net471.exe", module => { Assert.AreEqual (6, module.Image.SubSystemMajor); Assert.AreEqual (0, module.Image.SubSystemMinor); }); } [Test] public void LocallyScopedConstantArray () { TestModule ("LocallyScopedConstantArray.dll", module => { Assert.IsTrue (module.HasDebugHeader); var method = module.Types .Single (x => x.Name == "TestClass") .Methods .Single (x => x.Name == "TestMethod"); var debugInformation = method.DebugInformation; Assert.IsNull (debugInformation.Scope.Constants.Single ().Value); }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); } [Test] public void ExternalPdbDeterministicAssembly () { TestModule ("ExternalPdbDeterministic.dll", module => { Assert.IsTrue (module.HasDebugHeader); var header = module.GetDebugHeader (); Assert.IsTrue (header.Entries.Length >= 2); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.CodeView)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.Deterministic)); // If read directly from a file the PdbChecksum may not be persent (in this test case it isn't) // but when written through Cecil it will always be there. if (header.Entries.Length > 2) { Assert.AreEqual (3, header.Entries.Length); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.PdbChecksum)); } }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); } [Test] public void EmbeddedPdbDeterministicAssembly () { TestModule ("EmbeddedPdbDeterministic.dll", module => { Assert.IsTrue (module.HasDebugHeader); var header = module.GetDebugHeader (); Assert.IsTrue (header.Entries.Length >= 3); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.CodeView)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.Deterministic)); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.EmbeddedPortablePdb)); // If read directly from a file the PdbChecksum may not be persent (in this test case it isn't) // but when written through Cecil it will always be there. if (header.Entries.Length > 3) { Assert.AreEqual (4, header.Entries.Length); Assert.IsTrue (header.Entries.Any (e => e.Directory.Type == ImageDebugType.PdbChecksum)); } }, symbolReaderProvider: typeof (EmbeddedPortablePdbReaderProvider), symbolWriterProvider: typeof (EmbeddedPortablePdbWriterProvider)); } } }