diff --git a/ICSharpCode.Decompiler.Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler.Tests/DecompilerTestBase.cs index 835c0134e..bc13d8db3 100644 --- a/ICSharpCode.Decompiler.Tests/DecompilerTestBase.cs +++ b/ICSharpCode.Decompiler.Tests/DecompilerTestBase.cs @@ -52,8 +52,7 @@ namespace ICSharpCode.Decompiler.Tests { var code = RemoveIgnorableLines(File.ReadLines(fileName)); using (var assembly = CompileLegacy(code, optimize, useDebug, compilerVersion)) { - var module = new Metadata.PEFile("temp.exe", assembly, PEStreamOptions.Default); - module.AssemblyResolver = new Metadata.UniversalAssemblyResolver(fileName, false, true, module.Reader.DetectTargetFrameworkId(), PEStreamOptions.Default); + var module = new PEFile("temp.exe", assembly, throwOnResolveError: false, options: PEStreamOptions.PrefetchEntireImage); CSharpDecompiler decompiler = new CSharpDecompiler(module, new DecompilerSettings()); decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAtttributes()); diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index ac5a749a6..f1232deee 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) { using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) - using (var peFile = new PEFile(sourceFileName, peFileStream, PEStreamOptions.Default)) + using (var peFile = new PEFile(sourceFileName, peFileStream)) using (var writer = new StringWriter()) { var metadata = peFile.GetMetadataReader(); var output = new PlainTextOutput(writer); @@ -341,8 +341,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var emitResult = compilation.Emit(peStream); peStream.Position = 0; - var moduleDefinition = new PEFile("TestAssembly.dll", peStream, PEStreamOptions.Default); - moduleDefinition.AssemblyResolver = new UniversalAssemblyResolver(typeof(Tester).Assembly.Location, false, true, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.Default); + var moduleDefinition = new PEFile("TestAssembly.dll", peStream, false, PEStreamOptions.PrefetchEntireImage); var decompiler = new CSharpDecompiler(moduleDefinition, new DecompilerSettings()); return decompiler; @@ -388,9 +387,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null) { using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) { - var module = new PEFile(assemblyFileName, file, PEStreamOptions.Default); - var resolver = new UniversalAssemblyResolver(assemblyFileName, false, true, module.Reader.DetectTargetFrameworkId(), PEStreamOptions.Default); - module.AssemblyResolver = resolver; + var module = new PEFile(assemblyFileName, file, false, PEStreamOptions.PrefetchEntireImage); var typeSystem = new DecompilerTypeSystem(module); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings ?? new DecompilerSettings()); decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAtttributes()); diff --git a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs index 4a5fb1b0e..a99c06f30 100644 --- a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs +++ b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection.PortableExecutable; using System.Text.RegularExpressions; using System.Threading; using ICSharpCode.Decompiler.CSharp; @@ -143,11 +144,10 @@ namespace ICSharpCode.Decompiler.Tests Console.WriteLine($"Decompiling {fileToRoundtrip}..."); Stopwatch w = Stopwatch.StartNew(); using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { - PEFile module = new PEFile(file, fileStream, System.Reflection.PortableExecutable.PEStreamOptions.Default); - var resolver = new UniversalAssemblyResolver(file, false, true, module.Reader.DetectTargetFrameworkId(), System.Reflection.PortableExecutable.PEStreamOptions.Default); + PEFile module = new PEFile(file, fileStream, false, PEStreamOptions.PrefetchEntireImage); + UniversalAssemblyResolver resolver = (UniversalAssemblyResolver)module.AssemblyResolver; resolver.AddSearchDirectory(inputDir); resolver.RemoveSearchDirectory("."); - module.AssemblyResolver = resolver; var decompiler = new TestProjectDecompiler(inputDir); // use a fixed GUID so that we can diff the output between different ILSpy runs without spurious changes decompiler.ProjectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}"); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index ecefef5f1..fd3d7f3bb 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -38,6 +38,7 @@ using System.Runtime.InteropServices; using System.Reflection.Metadata; using SRM = System.Reflection.Metadata; using ICSharpCode.Decompiler.Metadata; +using System.Reflection.PortableExecutable; namespace ICSharpCode.Decompiler.CSharp { @@ -301,19 +302,14 @@ namespace ICSharpCode.Decompiler.CSharp } #endregion - static Metadata.PEFile LoadPEFile(string fileName, DecompilerSettings settings) + static PEFile LoadPEFile(string fileName, DecompilerSettings settings) { - Stream stream; - if (settings.LoadInMemory) { - using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { - stream = new MemoryStream(); - fileStream.CopyTo(stream); - stream.Position = 0; - } - } else { - stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); - } - return new Metadata.PEFile(fileName, stream, System.Reflection.PortableExecutable.PEStreamOptions.Default); + return new PEFile( + fileName, + new FileStream(fileName, FileMode.Open, FileAccess.Read), + settings.ThrowOnAssemblyResolveErrors, + options: settings.LoadInMemory ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default + ); } TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext) diff --git a/ICSharpCode.Decompiler/Metadata/Dom.cs b/ICSharpCode.Decompiler/Metadata/Dom.cs index ca41d18ef..4b64742aa 100644 --- a/ICSharpCode.Decompiler/Metadata/Dom.cs +++ b/ICSharpCode.Decompiler/Metadata/Dom.cs @@ -94,14 +94,22 @@ namespace ICSharpCode.Decompiler.Metadata { public string FileName { get; } public PEReader Reader { get; } - public IAssemblyResolver AssemblyResolver { get; set; } + public IAssemblyResolver AssemblyResolver { get; } public IAssemblyDocumentationResolver DocumentationResolver { get; set; } public IDebugInfoProvider DebugInfo { get; set; } - public PEFile(string fileName, Stream stream, PEStreamOptions options) + public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default) { this.FileName = fileName; this.Reader = new PEReader(stream, options); + this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options); + } + + public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default) + { + this.FileName = fileName; + this.Reader = new PEReader(stream, options); + this.AssemblyResolver = assemblyResolver; } public bool IsAssembly => GetMetadataReader().IsAssembly; @@ -140,7 +148,6 @@ namespace ICSharpCode.Decompiler.Metadata public ImmutableArray AssemblyReferences => GetMetadataReader().AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray(); public ImmutableArray ModuleReferences => GetMetadataReader().GetModuleReferences().ToImmutableArray(); public ImmutableArray TypeDefinitions => Reader.GetMetadataReader().GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray(); - public ImmutableArray TypeReferences => Reader.GetMetadataReader().TypeReferences.Select(t => new TypeReference(this, t)).ToImmutableArray(); public ImmutableArray Resources => GetResources().ToImmutableArray(); IEnumerable GetResources() diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index aec843236..938ff3b35 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -10,7 +10,6 @@ namespace ICSharpCode.Decompiler.Metadata { DotNetCorePathFinder dotNetCorePathFinder; readonly bool throwOnError; - readonly bool inMemory; readonly PEStreamOptions options; readonly string mainAssemblyFileName; readonly string baseDirectory; @@ -49,9 +48,8 @@ namespace ICSharpCode.Decompiler.Metadata public string TargetFramework { get; } - public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, bool inMemory, string targetFramework, PEStreamOptions options) + public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework, PEStreamOptions options) { - this.inMemory = inMemory; this.options = options; this.TargetFramework = targetFramework; this.mainAssemblyFileName = mainAssemblyFileName; @@ -70,17 +68,7 @@ namespace ICSharpCode.Decompiler.Metadata throw new AssemblyResolutionException(name); return null; } - Stream stream; - if (inMemory) { - using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { - stream = new MemoryStream(); - fileStream.CopyTo(stream); - } - } else { - stream = new FileStream(file, FileMode.Open, FileAccess.Read); - } - stream.Position = 0; - return new PEFile(file, stream, options); + return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), this, options); } public string FindAssemblyFile(IAssemblyReference name) @@ -334,15 +322,5 @@ namespace ICSharpCode.Decompiler.Metadata } #endregion - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs index b0f6ba555..1d2661268 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs @@ -272,12 +272,12 @@ namespace ICSharpCode.Decompiler.TypeSystem #endregion #region Load Assembly From Disk - public IUnresolvedAssembly LoadAssemblyFile(string fileName) + public IUnresolvedAssembly LoadAssemblyFile(string fileName, bool throwOnResolveError = true, PEStreamOptions options = PEStreamOptions.Default) { if (fileName == null) throw new ArgumentNullException(nameof(fileName)); var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); - return LoadModule(new Metadata.PEFile(fileName, fileStream, PEStreamOptions.Default)); + return LoadModule(new Metadata.PEFile(fileName, fileStream, throwOnResolveError, options)); } #endregion diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 0a996e200..2f801dc99 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -113,11 +113,10 @@ namespace ILSpy.BamlDecompiler.Tests void RunTest(string name, string asmPath, string sourcePath) { using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) { - var module = new PEFile(asmPath, fileStream, System.Reflection.PortableExecutable.PEStreamOptions.Default); - var resolver = new UniversalAssemblyResolver(asmPath, false, true, module.Reader.DetectTargetFrameworkId(), System.Reflection.PortableExecutable.PEStreamOptions.Default); + var module = new PEFile(asmPath, fileStream); + var resolver = (UniversalAssemblyResolver)module.AssemblyResolver; resolver.RemoveSearchDirectory("."); resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); - module.AssemblyResolver = resolver; var res = module.Resources.First(); Stream bamlStream = LoadBaml(res, name + ".baml"); Assert.IsNotNull(bamlStream); diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 38c788fc6..d5861c4d0 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -119,17 +119,12 @@ namespace ICSharpCode.ILSpy if (stream != null) { // Read the module from a precrafted stream - module = new PEFile(fileName, stream, PEStreamOptions.Default) { AssemblyResolver = new MyAssemblyResolver(this) }; + module = new PEFile(fileName, stream, new MyAssemblyResolver(this), PEStreamOptions.Default); } else { // Read the module from disk (by default) - using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { - var ms = new MemoryStream(); - fs.CopyTo(ms); - ms.Position = 0; - module = new PEFile(fileName, ms, PEStreamOptions.Default) { AssemblyResolver = new MyAssemblyResolver(this) }; - } + module = new PEFile(fileName, new FileStream(fileName, FileMode.Open, FileAccess.Read), new MyAssemblyResolver(this), PEStreamOptions.PrefetchEntireImage); } if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { @@ -232,7 +227,7 @@ namespace ICSharpCode.ILSpy class MyUniversalResolver : UniversalAssemblyResolver { public MyUniversalResolver(LoadedAssembly assembly) - : base(assembly.FileName, false, true, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.Default) + : base(assembly.FileName, false, assembly.GetTargetFrameworkIdAsync().Result, PEStreamOptions.PrefetchEntireImage) { } }