diff --git a/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs b/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs index 7e8bdc9de..616d85617 100644 --- a/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs +++ b/ICSharpCode.BamlDecompiler/Baml/KnownThings.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.BamlDecompiler.Baml } catch (Exception ex) { - throw new ICSharpCode.Decompiler.DecompilerException(typeSystem.MainModule.PEFile, ex.Message, ex); + throw new ICSharpCode.Decompiler.DecompilerException(typeSystem.MainModule.MetadataFile, ex.Message, ex); } } diff --git a/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs b/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs index 01b2875d8..d6072b6a1 100644 --- a/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs +++ b/ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.BamlDecompiler "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" }; - public BamlDecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver) + public BamlDecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver) { if (mainModule == null) throw new ArgumentNullException(nameof(mainModule)); @@ -48,8 +48,8 @@ namespace ICSharpCode.BamlDecompiler throw new ArgumentNullException(nameof(assemblyResolver)); // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. - var referencedAssemblies = new List(); - var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>(); + var referencedAssemblies = new List(); + var assemblyReferenceQueue = new Queue<(bool IsAssembly, MetadataFile MainModule, object Reference)>(); var mainMetadata = mainModule.Metadata; foreach (var h in mainMetadata.GetModuleReferences()) { @@ -73,16 +73,16 @@ namespace ICSharpCode.BamlDecompiler { assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference))); } - var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => + var comparer = KeyComparer.Create(((bool IsAssembly, MetadataFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); - var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); + var processedAssemblyReferences = new HashSet<(bool IsAssembly, MetadataFile Parent, object Reference)>(comparer); while (assemblyReferenceQueue.Count > 0) { var asmRef = assemblyReferenceQueue.Dequeue(); if (!processedAssemblyReferences.Add(asmRef)) continue; - PEFile asm; + MetadataFile asm; if (asmRef.IsAssembly) { asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference); diff --git a/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs index 5e886536c..104f6343b 100644 --- a/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs +++ b/ICSharpCode.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs @@ -128,7 +128,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite IMethod connectMethod = null; MethodDefinition connectMetadataEntry = default; - var module = ctx.TypeSystem.MainModule.PEFile; + var module = ctx.TypeSystem.MainModule.MetadataFile; foreach (IMethod m in type.Methods) { @@ -171,9 +171,7 @@ namespace ICSharpCode.BamlDecompiler.Rewrite ctx.GeneratedMembers.Add(connectMethod.MetadataToken); - - - var body = module.Reader.GetMethodBody(connectMetadataEntry.RelativeVirtualAddress); + var body = module.GetMethodBody(connectMetadataEntry.RelativeVirtualAddress); var genericContext = new GenericContext( classTypeParameters: connectMethod.DeclaringType?.TypeParameters, methodTypeParameters: connectMethod.TypeParameters); diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs index 9b87d99be..e94175e80 100644 --- a/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs +++ b/ICSharpCode.Decompiler.PowerShell/GetDecompiledProjectCmdlet.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.IO; using System.Management.Automation; using System.Threading; @@ -89,7 +88,7 @@ namespace ICSharpCode.Decompiler.PowerShell private void DoDecompile(string path) { - PEFile module = Decompiler.TypeSystem.MainModule.PEFile; + MetadataFile module = Decompiler.TypeSystem.MainModule.MetadataFile; var assemblyResolver = new UniversalAssemblyResolver(module.FileName, false, module.Metadata.DetectTargetFrameworkId()); WholeProjectDecompiler decompiler = new WholeProjectDecompiler(assemblyResolver); decompiler.ProgressIndicator = this; diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index cedf88894..9d44a14a3 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -251,7 +251,7 @@ namespace ICSharpCode.Decompiler.CSharp /// /// Creates a new instance from the given using the given and . /// - public CSharpDecompiler(PEFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + public CSharpDecompiler(MetadataFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings) : this(new DecompilerTypeSystem(module, assemblyResolver, settings), settings) { } @@ -264,7 +264,7 @@ namespace ICSharpCode.Decompiler.CSharp this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem)); this.settings = settings; this.module = typeSystem.MainModule; - this.metadata = module.PEFile.Metadata; + this.metadata = module.MetadataFile.Metadata; if (module.TypeSystemOptions.HasFlag(TypeSystemOptions.Uncached)) throw new ArgumentException("Cannot use an uncached type system in the decompiler."); } @@ -276,7 +276,7 @@ namespace ICSharpCode.Decompiler.CSharp /// The module containing the member. /// The metadata token/handle of the member. Can be a TypeDef, MethodDef or FieldDef. /// THe settings used to determine whether code should be hidden. E.g. if async methods are not transformed, async state machines are included in the decompiled code. - public static bool MemberIsHidden(Metadata.PEFile module, EntityHandle member, DecompilerSettings settings) + public static bool MemberIsHidden(MetadataFile module, EntityHandle member, DecompilerSettings settings) { if (module == null || member.IsNil) return false; @@ -539,7 +539,7 @@ namespace ICSharpCode.Decompiler.CSharp { try { - return XmlDocLoader.LoadDocumentation(module.PEFile); + return XmlDocLoader.LoadDocumentation(module.MetadataFile); } catch (System.Xml.XmlException) { @@ -633,7 +633,7 @@ namespace ICSharpCode.Decompiler.CSharp var typeDef = module.GetDefinition(typeDefHandle); if (typeDef.Name == "" && typeDef.Members.Count == 0) continue; - if (MemberIsHidden(module.PEFile, typeDefHandle, settings)) + if (MemberIsHidden(module.MetadataFile, typeDefHandle, settings)) continue; if (string.IsNullOrEmpty(typeDef.Namespace)) { @@ -702,7 +702,7 @@ namespace ICSharpCode.Decompiler.CSharp /// /// Determines the "code-mappings" for a given TypeDef or MethodDef. See for more information. /// - public static CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public static CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { var declaringType = (TypeDefinitionHandle)member.GetDeclaringType(module.Metadata); @@ -744,7 +744,7 @@ namespace ICSharpCode.Decompiler.CSharp return info; } - private static void ReadCodeMappingInfo(PEFile module, CodeMappingInfo info, MethodDefinitionHandle parent, MethodDefinitionHandle part, Queue connectedMethods, HashSet processedNestedTypes) + private static void ReadCodeMappingInfo(MetadataFile module, CodeMappingInfo info, MethodDefinitionHandle parent, MethodDefinitionHandle part, Queue connectedMethods, HashSet processedNestedTypes) { var md = module.Metadata.GetMethodDefinition(part); @@ -756,7 +756,7 @@ namespace ICSharpCode.Decompiler.CSharp var declaringType = md.GetDeclaringType(); - var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); + var blob = module.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); while (blob.RemainingBytes > 0) { var code = blob.DecodeOpCode(); @@ -1357,7 +1357,7 @@ namespace ICSharpCode.Decompiler.CSharp // Decompile members that are not compiler-generated. foreach (var entity in allOrderedEntities) { - if (entity.MetadataToken.IsNil || MemberIsHidden(module.PEFile, entity.MetadataToken, settings)) + if (entity.MetadataToken.IsNil || MemberIsHidden(module.MetadataFile, entity.MetadataToken, settings)) { continue; } @@ -1403,7 +1403,7 @@ namespace ICSharpCode.Decompiler.CSharp if (typeDecl.ClassType == ClassType.Enum) { Debug.Assert(typeDef.Kind == TypeKind.Enum); - EnumValueDisplayMode displayMode = DetectBestEnumValueDisplayMode(typeDef, module.PEFile); + EnumValueDisplayMode displayMode = DetectBestEnumValueDisplayMode(typeDef, module.MetadataFile); switch (displayMode) { case EnumValueDisplayMode.FirstOnly: @@ -1532,7 +1532,7 @@ namespace ICSharpCode.Decompiler.CSharp } } - EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module) + EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, MetadataFile module) { if (typeDef.HasAttribute(KnownAttribute.Flags)) return EnumValueDisplayMode.AllHex; @@ -1608,7 +1608,7 @@ namespace ICSharpCode.Decompiler.CSharp } FixParameterNames(methodDecl); var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) + if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.MetadataFile, (MethodDefinitionHandle)method.MetadataToken)) { // if local functions are not active and we're dealing with a local function, // reduce the visibility of the method to private, @@ -1701,7 +1701,7 @@ namespace ICSharpCode.Decompiler.CSharp MethodBodyBlock methodBody; try { - methodBody = module.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + methodBody = module.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); } catch (BadImageFormatException ex) { @@ -1980,7 +1980,7 @@ namespace ICSharpCode.Decompiler.CSharp string message; try { - var initVal = fieldDefinition.GetInitialValue(module.PEFile.Reader, TypeSystem); + var initVal = fieldDefinition.GetInitialValue(module.MetadataFile, TypeSystem); message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(initVal.ReadBytes(initVal.RemainingBytes)).Replace('-', ' ')); } catch (BadImageFormatException ex) diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs index 26c1a8a58..f66485585 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs @@ -36,6 +36,6 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// The information about the project being created. /// A collection of source files to be included into the project. /// The module being decompiled. - void Write(TextWriter target, IProjectInfoProvider project, IEnumerable files, PEFile module); + void Write(TextWriter target, IProjectInfoProvider project, IEnumerable files, MetadataFile module); } } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs index eb383ba75..a536d72c7 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs @@ -45,10 +45,10 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler TextWriter target, IProjectInfoProvider project, IEnumerable files, - PEFile module) + MetadataFile module) { const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; - string platformName = TargetServices.GetPlatformName(module); + string platformName = module is PEFile peFile ? TargetServices.GetPlatformName(peFile) : "AnyCPU"; var targetFramework = TargetServices.DetectTargetFramework(module); if (targetFramework.Identifier == ".NETFramework" && targetFramework.VersionNumber == 200) targetFramework = TargetServices.DetectTargetFrameworkNET20(module, project.AssemblyResolver, targetFramework); @@ -80,26 +80,22 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteValue(platformName); w.WriteEndElement(); // - if (module.Reader.PEHeaders.IsDll) - { - w.WriteElementString("OutputType", "Library"); - } - else + string outputType; + + switch ((module as PEFile)?.Reader.PEHeaders.PEHeader.Subsystem) { - switch (module.Reader.PEHeaders.PEHeader.Subsystem) - { - case Subsystem.WindowsGui: - w.WriteElementString("OutputType", "WinExe"); - break; - case Subsystem.WindowsCui: - w.WriteElementString("OutputType", "Exe"); - break; - default: - w.WriteElementString("OutputType", "Library"); - break; - } + case Subsystem.WindowsGui: + outputType = "WinExe"; + break; + case Subsystem.WindowsCui: + outputType = "Exe"; + break; + default: + outputType = "Library"; + break; } + w.WriteElementString("OutputType", outputType); w.WriteElementString("LangVersion", project.LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); w.WriteElementString("AssemblyName", module.Name); @@ -123,7 +119,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteStartElement("PropertyGroup"); // platform-specific w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); w.WriteElementString("PlatformTarget", platformName); - if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) + if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" + && ((module as PEFile)?.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) { w.WriteElementString("Prefer32Bit", "false"); } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs index b5273f1d5..ee0029dc9 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler TextWriter target, IProjectInfoProvider project, IEnumerable files, - PEFile module) + MetadataFile module) { using (XmlTextWriter xmlWriter = new XmlTextWriter(target)) { @@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } } - static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable files, PEFile module) + static void Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable files, MetadataFile module) { xml.WriteStartElement("Project"); @@ -105,18 +105,30 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } } - static void WriteAssemblyInfo(XmlTextWriter xml, PEFile module, IProjectInfoProvider project, ProjectType projectType) + static void WriteAssemblyInfo(XmlTextWriter xml, MetadataFile module, IProjectInfoProvider project, ProjectType projectType) { xml.WriteElementString("AssemblyName", module.Name); // Since we create AssemblyInfo.cs manually, we need to disable the auto-generation xml.WriteElementString("GenerateAssemblyInfo", FalseString); - WriteOutputType(xml, module.Reader.PEHeaders.IsDll, module.Reader.PEHeaders.PEHeader.Subsystem, projectType); + string platformName; + CorFlags flags; + if (module is PEFile { Reader.PEHeaders: var headers } peFile) + { + WriteOutputType(xml, headers.IsDll, headers.PEHeader.Subsystem, projectType); + platformName = TargetServices.GetPlatformName(peFile); + flags = headers.CorHeader.Flags; + } + else + { + WriteOutputType(xml, isDll: true, Subsystem.Unknown, projectType); + platformName = AnyCpuString; + flags = 0; + } WriteDesktopExtensions(xml, projectType); - string platformName = TargetServices.GetPlatformName(module); var targetFramework = TargetServices.DetectTargetFramework(module); if (targetFramework.Identifier == ".NETFramework" && targetFramework.VersionNumber == 200) targetFramework = TargetServices.DetectTargetFrameworkNET20(module, project.AssemblyResolver, targetFramework); @@ -134,7 +146,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler xml.WriteElementString("PlatformTarget", platformName); } - if (platformName == AnyCpuString && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) + if (platformName == AnyCpuString && (flags & CorFlags.Prefers32Bit) != 0) { xml.WriteElementString("Prefer32Bit", TrueString); } @@ -238,7 +250,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } } - static void WriteReferences(XmlTextWriter xml, PEFile module, IProjectInfoProvider project, ProjectType projectType) + static void WriteReferences(XmlTextWriter xml, MetadataFile module, IProjectInfoProvider project, ProjectType projectType) { bool isNetCoreApp = TargetServices.DetectTargetFramework(module).Identifier == ".NETCoreApp"; var targetPacks = new HashSet(); @@ -292,7 +304,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } } - static ProjectType GetProjectType(PEFile module) + static ProjectType GetProjectType(MetadataFile module) { foreach (var referenceName in module.AssemblyReferences.Select(r => r.Name)) { diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs index eb00bc6c9..adbf96fc4 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// The module to get the target framework description for. Cannot be null. /// A new instance of the class that describes the specified . /// - public static TargetFramework DetectTargetFramework(PEFile module) + public static TargetFramework DetectTargetFramework(MetadataFile module) { if (module is null) { @@ -216,9 +216,9 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler }; /// - /// Gets exact if is + /// Gets exact if is /// - public static TargetFramework DetectTargetFrameworkNET20(PEFile module, IAssemblyResolver assemblyResolver, TargetFramework targetFramework) + public static TargetFramework DetectTargetFrameworkNET20(MetadataFile module, IAssemblyResolver assemblyResolver, TargetFramework targetFramework) { var resolvedAssemblies = new HashSet(); int version = 200; @@ -226,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler return new TargetFramework(targetFramework.Identifier, version, targetFramework.Profile); } - static void GetFrameworkVersionNET20(PEFile module, IAssemblyResolver assemblyResolver, HashSet resolvedAssemblies, ref int version) + static void GetFrameworkVersionNET20(MetadataFile module, IAssemblyResolver assemblyResolver, HashSet resolvedAssemblies, ref int version) { foreach (var r in module.Metadata.AssemblyReferences) { @@ -245,7 +245,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler break; } - PEFile resolvedReference; + MetadataFile resolvedReference; try { resolvedReference = assemblyResolver.Resolve(reference); diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 4dd22ee8f..5a22d218f 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -37,8 +37,6 @@ using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using Microsoft.Win32; - using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -133,16 +131,16 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler HashSet directories = new HashSet(Platform.FileNameComparer); readonly IProjectFileWriter projectWriter; - public void DecompileProject(PEFile moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) + public void DecompileProject(MetadataFile file, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) { - string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(moduleDefinition.Name) + ".csproj"); + string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(file.Name) + ".csproj"); using (var writer = new StreamWriter(projectFileName)) { - DecompileProject(moduleDefinition, targetDirectory, writer, cancellationToken); + DecompileProject(file, targetDirectory, writer, cancellationToken); } } - public ProjectId DecompileProject(PEFile moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) + public ProjectId DecompileProject(MetadataFile file, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) { if (string.IsNullOrEmpty(targetDirectory)) { @@ -150,23 +148,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } TargetDirectory = targetDirectory; directories.Clear(); - var resources = WriteResourceFilesInProject(moduleDefinition).ToList(); - var files = WriteCodeFilesInProject(moduleDefinition, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty()).ToList(), cancellationToken).ToList(); + var resources = WriteResourceFilesInProject(file).ToList(); + var files = WriteCodeFilesInProject(file, resources.SelectMany(r => r.PartialTypes ?? Enumerable.Empty()).ToList(), cancellationToken).ToList(); files.AddRange(resources); - files.AddRange(WriteMiscellaneousFilesInProject(moduleDefinition)); + var module = file as PEFile; + if (module != null) + { + files.AddRange(WriteMiscellaneousFilesInProject(module)); + } if (StrongNameKeyFile != null) { File.Copy(StrongNameKeyFile, Path.Combine(targetDirectory, Path.GetFileName(StrongNameKeyFile)), overwrite: true); } - projectWriter.Write(projectFileWriter, this, files, moduleDefinition); + projectWriter.Write(projectFileWriter, this, files, file); - string platformName = TargetServices.GetPlatformName(moduleDefinition); + string platformName = module != null ? TargetServices.GetPlatformName(module) : "AnyCPU"; return new ProjectId(platformName, ProjectGuid, ProjectTypeGuids.CSharpWindows); } #region WriteCodeFilesInProject - protected virtual bool IncludeTypeWhenDecompilingProject(PEFile module, TypeDefinitionHandle type) + protected virtual bool IncludeTypeWhenDecompilingProject(MetadataFile module, TypeDefinitionHandle type) { var metadata = module.Metadata; var typeDef = metadata.GetTypeDefinition(type); @@ -208,7 +210,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler return new[] { new ProjectItemInfo("Compile", assemblyInfo) }; } - IEnumerable WriteCodeFilesInProject(Metadata.PEFile module, IList partialTypes, CancellationToken cancellationToken) + IEnumerable WriteCodeFilesInProject(MetadataFile module, IList partialTypes, CancellationToken cancellationToken) { var metadata = module.Metadata; var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)) @@ -306,7 +308,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler #endregion #region WriteResourceFilesInProject - protected virtual IEnumerable WriteResourceFilesInProject(Metadata.PEFile module) + protected virtual IEnumerable WriteResourceFilesInProject(MetadataFile module) { foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded)) { @@ -758,7 +760,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } } - public static bool CanUseSdkStyleProjectFormat(PEFile module) + public static bool CanUseSdkStyleProjectFormat(MetadataFile module) { return TargetServices.DetectTargetFramework(module).Moniker != null; } diff --git a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs index 6ddc23b43..8abe102f2 100644 --- a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs @@ -1100,7 +1100,7 @@ namespace ICSharpCode.Decompiler.CSharp var genericContext = new GenericContext( classTypeParameters: recordTypeDef.TypeParameters, methodTypeParameters: null); - var body = typeSystem.MainModule.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = typeSystem.MainModule.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); var ilReader = new ILReader(typeSystem.MainModule); var il = ilReader.ReadIL(methodDefHandle, body, genericContext, ILFunctionKind.TopLevelFunction, cancellationToken); var settings = new DecompilerSettings(LanguageVersion.CSharp1); diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index bdb77fab4..d304ad3fe 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -58,10 +58,10 @@ namespace ICSharpCode.Decompiler.CSharp void CollectNamespaces(IEntity entity, MetadataModule module, CodeMappingInfo mappingInfo = null) { - if (entity == null || entity.MetadataToken.IsNil) + if (entity == null || entity.MetadataToken.IsNil || module.MetadataFile is not MetadataFile corFile) return; if (mappingInfo == null) - mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); + mappingInfo = CSharpDecompiler.GetCodeMappingInfo(corFile, entity.MetadataToken); switch (entity) { case ITypeDefinition td: @@ -104,7 +104,6 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(field.ReturnType); break; case IMethod method: - var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); foreach (var part in parts) { @@ -125,7 +124,7 @@ namespace ICSharpCode.Decompiler.CSharp MethodBodyBlock body; try { - body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); + body = module.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); } catch (BadImageFormatException) { diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs index bb32e2ac6..6d00db35a 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs @@ -311,7 +311,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; if (!ctorMethod.MetadataToken.IsNil) { - var metadata = context.TypeSystem.MainModule.PEFile.Metadata; + var metadata = context.TypeSystem.MainModule.MetadataFile.Metadata; SRM.MethodDefinition ctorMethodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)ctorMethod.MetadataToken); SRM.TypeDefinition declaringType = metadata.GetTypeDefinition(ctorMethodDef.GetDeclaringType()); bool declaringTypeIsBeforeFieldInit = declaringType.HasFlag(TypeAttributes.BeforeFieldInit); diff --git a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs index 84de80d2a..daca4e6e3 100644 --- a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs +++ b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs @@ -19,15 +19,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Text; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -231,11 +228,11 @@ namespace ICSharpCode.Decompiler.DebugInfo this.functions.Add(function); var method = function.MoveNextMethod ?? function.Method; MethodDefinitionHandle handle = (MethodDefinitionHandle)method.MetadataToken; - var file = typeSystem.MainModule.PEFile; + var file = typeSystem.MainModule.MetadataFile; MethodDefinition md = file.Metadata.GetMethodDefinition(handle); if (md.HasBody()) { - HandleMethodBody(function, file.Reader.GetMethodBody(md.RelativeVirtualAddress)); + HandleMethodBody(function, file.GetMethodBody(md.RelativeVirtualAddress)); } } diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index 0e0026ea8..3779ace15 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -26,10 +26,8 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; -using System.Runtime; using System.Security.Cryptography; using System.Text; -using System.Threading; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; @@ -49,7 +47,7 @@ namespace ICSharpCode.Decompiler.DebugInfo public static bool HasCodeViewDebugDirectoryEntry(PEFile file) { - return file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); + return file != null && file.Reader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.CodeView); } private static bool IncludeTypeWhenGeneratingPdb(PEFile module, TypeDefinitionHandle type, DecompilerSettings settings) diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs index ef3ba7d17..b32563526 100644 --- a/ICSharpCode.Decompiler/DecompilerException.cs +++ b/ICSharpCode.Decompiler/DecompilerException.cs @@ -42,18 +42,18 @@ namespace ICSharpCode.Decompiler public IEntity DecompiledEntity { get; } public IModule Module { get; } - public PEFile File { get; } + public MetadataFile File { get; } public DecompilerException(MetadataModule module, IEntity decompiledEntity, Exception innerException, string message = null) : base(message ?? GetDefaultMessage(decompiledEntity), innerException) { - this.File = module.PEFile; + this.File = module.MetadataFile; this.Module = module; this.DecompiledEntity = decompiledEntity; } - public DecompilerException(PEFile file, string message, Exception innerException) + public DecompilerException(MetadataFile file, string message, Exception innerException) : base(message, innerException) { this.File = file; diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 77c79137a..f73b31763 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.Disassembler /// public class ILStructure { - public readonly PEFile Module; + public readonly MetadataFile Module; public readonly MethodDefinitionHandle MethodHandle; public readonly MetadataGenericContext GenericContext; public readonly ILStructureType Type; @@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.Disassembler /// public readonly List Children = new List(); - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, MethodBodyBlock body) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, MethodBodyBlock body) : this(module, handle, genericContext, ILStructureType.Root, 0, body.GetILReader().Length) { // Build the tree of exception structures: @@ -142,7 +142,7 @@ namespace ICSharpCode.Decompiler.Disassembler SortChildren(); } - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default) { Debug.Assert(startOffset < endOffset); this.Module = module; @@ -154,7 +154,7 @@ namespace ICSharpCode.Decompiler.Disassembler this.ExceptionHandler = handler; } - public ILStructure(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint) + public ILStructure(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint) { Debug.Assert(startOffset < endOffset); this.Module = module; diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index d0ba6a499..c61179211 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.Disassembler int nextSequencePointIndex; // cache info - PEFile module; + MetadataFile module; MetadataReader metadata; MetadataGenericContext genericContext; DisassemblerSignatureTypeProvider signatureDecoder; @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Disassembler this.cancellationToken = cancellationToken; } - public virtual void Disassemble(PEFile module, MethodDefinitionHandle handle) + public virtual void Disassemble(MetadataFile module, MethodDefinitionHandle handle) { this.module = module ?? throw new ArgumentNullException(nameof(module)); metadata = module.Metadata; @@ -105,8 +105,8 @@ namespace ICSharpCode.Decompiler.Disassembler BlobReader bodyBlockReader; try { - body = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); - bodyBlockReader = module.Reader.GetSectionData(methodDefinition.RelativeVirtualAddress).GetReader(); + body = module.GetMethodBody(methodDefinition.RelativeVirtualAddress); + bodyBlockReader = module.GetSectionData(methodDefinition.RelativeVirtualAddress).GetReader(); } catch (BadImageFormatException ex) { @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("// Code size: {0} (0x{0:x})", blob.Length); output.WriteLine(".maxstack {0}", body.MaxStack); - var entrypointHandle = MetadataTokens.MethodDefinitionHandle(module.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); + var entrypointHandle = MetadataTokens.MethodDefinitionHandle(module.CorHeader?.EntryPointTokenOrRelativeVirtualAddress ?? 0); if (handle == entrypointHandle) output.WriteLine(".entrypoint"); @@ -141,7 +141,7 @@ namespace ICSharpCode.Decompiler.Disassembler while (blob.RemainingBytes > 0) { cancellationToken.ThrowIfCancellationRequested(); - WriteInstruction(output, metadata, handle, ref blob, methodDefinition.RelativeVirtualAddress); + WriteInstruction(output, module, handle, ref blob, methodDefinition.RelativeVirtualAddress); } WriteExceptionHandlers(module, handle, body); } @@ -195,7 +195,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(")"); } - internal void WriteExceptionHandlers(PEFile module, MethodDefinitionHandle handle, MethodBodyBlock body) + internal void WriteExceptionHandlers(MetadataFile module, MethodDefinitionHandle handle, MethodBodyBlock body) { this.module = module; metadata = module.Metadata; @@ -291,7 +291,7 @@ namespace ICSharpCode.Decompiler.Disassembler } var currentOpCode = ILParser.DecodeOpCode(ref body); body.Offset = offset; // reset IL stream - WriteInstruction(output, metadata, s.MethodHandle, ref body, methodRva); + WriteInstruction(output, module, s.MethodHandle, ref body, methodRva); prevInstructionWasBranch = currentOpCode.IsBranch() || currentOpCode.IsReturn() || currentOpCode == ILOpCode.Throw @@ -324,8 +324,9 @@ namespace ICSharpCode.Decompiler.Disassembler } } - protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) + protected virtual void WriteInstruction(ITextOutput output, MetadataFile metadataFile, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) { + var metadata = metadataFile.Metadata; int offset = blob.Offset; if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index e32077459..11c8bdb9a 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -143,7 +143,7 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodImplAttributes.AggressiveInlining, "aggressiveinlining" }, }; - public void DisassembleMethod(PEFile module, MethodDefinitionHandle handle) + public void DisassembleMethod(MetadataFile module, MethodDefinitionHandle handle) { var genericContext = new MetadataGenericContext(handle, module); // write method header @@ -153,7 +153,7 @@ namespace ICSharpCode.Decompiler.Disassembler DisassembleMethodBlock(module, handle, genericContext); } - public void DisassembleMethodHeader(PEFile module, MethodDefinitionHandle handle) + public void DisassembleMethodHeader(MetadataFile module, MethodDefinitionHandle handle) { var genericContext = new MetadataGenericContext(handle, module); // write method header @@ -162,7 +162,7 @@ namespace ICSharpCode.Decompiler.Disassembler DisassembleMethodHeaderInternal(module, handle, genericContext); } - void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) + void DisassembleMethodHeaderInternal(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) { var metadata = module.Metadata; @@ -310,7 +310,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.Unindent(); } - internal static void WriteMetadataToken(ITextOutput output, PEFile module, Handle? handle, + internal static void WriteMetadataToken(ITextOutput output, MetadataFile module, Handle? handle, int metadataToken, bool spaceAfter, bool spaceBefore, bool showMetadataTokens, bool base10) { // handle can be null in case of errors, if that's the case, we always want to print a comment, @@ -344,7 +344,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, + void DisassembleMethodBlock(MetadataFile module, MethodDefinitionHandle handle, MetadataGenericContext genericContext) { var metadata = module.Metadata; @@ -380,7 +380,7 @@ namespace ICSharpCode.Decompiler.Disassembler } #region Write Security Declarations - void WriteSecurityDeclarations(PEFile module, DeclarativeSecurityAttributeHandleCollection secDeclProvider) + void WriteSecurityDeclarations(MetadataFile module, DeclarativeSecurityAttributeHandleCollection secDeclProvider) { if (secDeclProvider.Count == 0) return; @@ -479,9 +479,9 @@ namespace ICSharpCode.Decompiler.Disassembler { readonly ITextOutput output; readonly IAssemblyResolver resolver; - readonly PEFile module; + readonly MetadataFile module; - public SecurityDeclarationDecoder(ITextOutput output, IAssemblyResolver resolver, PEFile module) + public SecurityDeclarationDecoder(ITextOutput output, IAssemblyResolver resolver, MetadataFile module) { this.output = output; this.resolver = resolver; @@ -535,11 +535,11 @@ namespace ICSharpCode.Decompiler.Disassembler return "type" == type.Item2; } - (PEFile, TypeDefinitionHandle) ResolveType(string typeName, PEFile module) + (MetadataFile, TypeDefinitionHandle) ResolveType(string typeName, MetadataFile module) { string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None); string[] typeNameParts = nameParts[0].Split('.'); - PEFile containingModule = null; + MetadataFile containingModule = null; TypeDefinitionHandle typeDefHandle = default; // if we deal with an assembly-qualified name, resolve the assembly if (nameParts.Length == 2) @@ -564,7 +564,7 @@ namespace ICSharpCode.Decompiler.Disassembler return (containingModule, typeDefHandle); - TypeDefinitionHandle FindType(PEFile currentModule, string[] name) + TypeDefinitionHandle FindType(MetadataFile currentModule, string[] name) { var metadata = currentModule.Metadata; var currentNamespace = metadata.GetNamespaceDefinitionRoot(); @@ -618,9 +618,9 @@ namespace ICSharpCode.Decompiler.Disassembler return typeCode; } - PEFile mscorlib; + MetadataFile mscorlib; - bool TryResolveMscorlib(out PEFile mscorlib) + bool TryResolveMscorlib(out MetadataFile mscorlib) { mscorlib = null; if (this.mscorlib != null) @@ -637,7 +637,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - void TryDecodeSecurityDeclaration(TextOutputWithRollback output, BlobReader blob, PEFile module) + void TryDecodeSecurityDeclaration(TextOutputWithRollback output, BlobReader blob, MetadataFile module) { output.WriteLine(" = {"); output.Indent(); @@ -1134,7 +1134,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } - void WriteGenericParametersAndAttributes(PEFile module, MetadataGenericContext context, GenericParameterHandle handle) + void WriteGenericParametersAndAttributes(MetadataFile module, MetadataGenericContext context, GenericParameterHandle handle) { var metadata = module.Metadata; var p = metadata.GetGenericParameter(handle); @@ -1161,7 +1161,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - void WriteParameterAttributes(PEFile module, ParameterHandle handle) + void WriteParameterAttributes(MetadataFile module, ParameterHandle handle) { var metadata = module.Metadata; var p = metadata.GetParameter(handle); @@ -1247,7 +1247,7 @@ namespace ICSharpCode.Decompiler.Disassembler { FieldAttributes.NotSerialized, "notserialized" }, }; - public void DisassembleField(PEFile module, FieldDefinitionHandle handle) + public void DisassembleField(MetadataFile module, FieldDefinitionHandle handle) { var metadata = module.Metadata; var fieldDefinition = metadata.GetFieldDefinition(handle); @@ -1264,7 +1264,7 @@ namespace ICSharpCode.Decompiler.Disassembler { // Field data as specified in II.16.3.1 of ECMA-335 6th edition int rva = fieldDefinition.GetRelativeVirtualAddress(); - int sectionIndex = module.Reader.PEHeaders.GetContainingSectionIndex(rva); + int sectionIndex = module.GetContainingSectionIndex(rva); if (sectionIndex < 0) { output.WriteLine($"// RVA {rva:X8} invalid (not in any section)"); @@ -1274,7 +1274,7 @@ namespace ICSharpCode.Decompiler.Disassembler BlobReader initVal; try { - initVal = fieldDefinition.GetInitialValue(module.Reader, null); + initVal = fieldDefinition.GetInitialValue(module, null); } catch (BadImageFormatException ex) { @@ -1283,7 +1283,7 @@ namespace ICSharpCode.Decompiler.Disassembler } if (initVal.Length > 0) { - var sectionHeader = module.Reader.PEHeaders.SectionHeaders[sectionIndex]; + var sectionHeader = module.SectionHeaders[sectionIndex]; output.Write(".data "); if (sectionHeader.Name == ".text") { @@ -1293,7 +1293,7 @@ namespace ICSharpCode.Decompiler.Disassembler { output.Write("tls "); } - else if (sectionHeader.Name != ".data") + else if (sectionHeader.Name is not (null or ".data")) { output.Write($"/* {sectionHeader.Name} */ "); } @@ -1305,14 +1305,14 @@ namespace ICSharpCode.Decompiler.Disassembler } } - public void DisassembleFieldHeader(PEFile module, FieldDefinitionHandle handle) + public void DisassembleFieldHeader(MetadataFile module, FieldDefinitionHandle handle) { var metadata = module.Metadata; var fieldDefinition = metadata.GetFieldDefinition(handle); DisassembleFieldHeaderInternal(module, handle, metadata, fieldDefinition); } - private char DisassembleFieldHeaderInternal(PEFile module, FieldDefinitionHandle handle, MetadataReader metadata, FieldDefinition fieldDefinition) + private char DisassembleFieldHeaderInternal(MetadataFile module, FieldDefinitionHandle handle, MetadataReader metadata, FieldDefinition fieldDefinition) { output.WriteReference(module, handle, ".field", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1342,7 +1342,7 @@ namespace ICSharpCode.Decompiler.Disassembler if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) { int rva = fieldDefinition.GetRelativeVirtualAddress(); - sectionPrefix = GetRVASectionPrefix(module.Reader.PEHeaders, rva); + sectionPrefix = GetRVASectionPrefix(module, rva); output.Write(" at {1}_{0:X8}", rva, sectionPrefix); } @@ -1356,12 +1356,14 @@ namespace ICSharpCode.Decompiler.Disassembler return sectionPrefix; } - char GetRVASectionPrefix(System.Reflection.PortableExecutable.PEHeaders headers, int rva) + char GetRVASectionPrefix(MetadataFile module, int rva) { - int sectionIndex = headers.GetContainingSectionIndex(rva); + if (module is not PEFile peFile) + throw new NotSupportedException("Cannot get RVA section prefix from module"); + int sectionIndex = peFile.Reader.PEHeaders.GetContainingSectionIndex(rva); if (sectionIndex < 0) return 'D'; - var sectionHeader = headers.SectionHeaders[sectionIndex]; + var sectionHeader = peFile.Reader.PEHeaders.SectionHeaders[sectionIndex]; switch (sectionHeader.Name) { case ".tls": @@ -1381,7 +1383,7 @@ namespace ICSharpCode.Decompiler.Disassembler { PropertyAttributes.HasDefault, "hasdefault" }, }; - public void DisassembleProperty(PEFile module, PropertyDefinitionHandle property) + public void DisassembleProperty(MetadataFile module, PropertyDefinitionHandle property) { var metadata = module.Metadata; var propertyDefinition = metadata.GetPropertyDefinition(property); @@ -1398,14 +1400,14 @@ namespace ICSharpCode.Decompiler.Disassembler CloseBlock(); } - public void DisassemblePropertyHeader(PEFile module, PropertyDefinitionHandle property) + public void DisassemblePropertyHeader(MetadataFile module, PropertyDefinitionHandle property) { var metadata = module.Metadata; var propertyDefinition = metadata.GetPropertyDefinition(property); DisassemblePropertyHeaderInternal(module, property, metadata, propertyDefinition); } - private PropertyAccessors DisassemblePropertyHeaderInternal(PEFile module, PropertyDefinitionHandle handle, MetadataReader metadata, PropertyDefinition propertyDefinition) + private PropertyAccessors DisassemblePropertyHeaderInternal(MetadataFile module, PropertyDefinitionHandle handle, MetadataReader metadata, PropertyDefinition propertyDefinition) { output.WriteReference(module, handle, ".property", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1436,7 +1438,7 @@ namespace ICSharpCode.Decompiler.Disassembler return accessors; } - void WriteNestedMethod(string keyword, PEFile module, MethodDefinitionHandle method) + void WriteNestedMethod(string keyword, MetadataFile module, MethodDefinitionHandle method) { if (method.IsNil) return; @@ -1454,7 +1456,7 @@ namespace ICSharpCode.Decompiler.Disassembler { EventAttributes.RTSpecialName, "rtspecialname" }, }; - public void DisassembleEvent(PEFile module, EventDefinitionHandle handle) + public void DisassembleEvent(MetadataFile module, EventDefinitionHandle handle) { var eventDefinition = module.Metadata.GetEventDefinition(handle); var accessors = eventDefinition.GetAccessors(); @@ -1471,14 +1473,14 @@ namespace ICSharpCode.Decompiler.Disassembler CloseBlock(); } - public void DisassembleEventHeader(PEFile module, EventDefinitionHandle handle) + public void DisassembleEventHeader(MetadataFile module, EventDefinitionHandle handle) { var eventDefinition = module.Metadata.GetEventDefinition(handle); var accessors = eventDefinition.GetAccessors(); DisassembleEventHeaderInternal(module, handle, eventDefinition, accessors); } - private void DisassembleEventHeaderInternal(PEFile module, EventDefinitionHandle handle, EventDefinition eventDefinition, EventAccessors accessors) + private void DisassembleEventHeaderInternal(MetadataFile module, EventDefinitionHandle handle, EventDefinition eventDefinition, EventAccessors accessors) { TypeDefinitionHandle declaringType; if (!accessors.Adder.IsNil) @@ -1555,7 +1557,7 @@ namespace ICSharpCode.Decompiler.Disassembler { TypeAttributes.HasSecurity, null }, }; - public void DisassembleType(PEFile module, TypeDefinitionHandle type) + public void DisassembleType(MetadataFile module, TypeDefinitionHandle type) { var typeDefinition = module.Metadata.GetTypeDefinition(type); MetadataGenericContext genericContext = new MetadataGenericContext(type, module); @@ -1676,14 +1678,14 @@ namespace ICSharpCode.Decompiler.Disassembler isInType = oldIsInType; } - public void DisassembleTypeHeader(PEFile module, TypeDefinitionHandle type) + public void DisassembleTypeHeader(MetadataFile module, TypeDefinitionHandle type) { var typeDefinition = module.Metadata.GetTypeDefinition(type); MetadataGenericContext genericContext = new MetadataGenericContext(type, module); DisassembleTypeHeaderInternal(module, type, typeDefinition, genericContext); } - private void DisassembleTypeHeaderInternal(PEFile module, TypeDefinitionHandle handle, TypeDefinition typeDefinition, MetadataGenericContext genericContext) + private void DisassembleTypeHeaderInternal(MetadataFile module, TypeDefinitionHandle handle, TypeDefinition typeDefinition, MetadataGenericContext genericContext) { output.WriteReference(module, handle, ".class", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), @@ -1712,7 +1714,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - void WriteTypeParameters(ITextOutput output, PEFile module, MetadataGenericContext context, GenericParameterHandleCollection p) + void WriteTypeParameters(ITextOutput output, MetadataFile module, MetadataGenericContext context, GenericParameterHandleCollection p) { if (p.Count > 0) { @@ -1765,37 +1767,37 @@ namespace ICSharpCode.Decompiler.Disassembler #region Processing - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } - private IReadOnlyCollection Process(PEFile module, IReadOnlyCollection items) + private IReadOnlyCollection Process(MetadataFile module, IReadOnlyCollection items) { return EntityProcessor?.Process(module, items) ?? items; } @@ -1804,7 +1806,7 @@ namespace ICSharpCode.Decompiler.Disassembler #region Helper methods - void WriteAttributes(PEFile module, CustomAttributeHandleCollection attributes) + void WriteAttributes(MetadataFile module, CustomAttributeHandleCollection attributes) { var metadata = module.Metadata; foreach (CustomAttributeHandle a in Process(module, attributes)) @@ -1931,7 +1933,7 @@ namespace ICSharpCode.Decompiler.Disassembler } #endregion - public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable types) + public void DisassembleNamespace(string nameSpace, MetadataFile module, IEnumerable types) { if (!string.IsNullOrEmpty(nameSpace)) { @@ -1953,7 +1955,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - public void WriteAssemblyHeader(PEFile module) + public void WriteAssemblyHeader(MetadataFile module) { var metadata = module.Metadata; if (!metadata.IsAssembly) @@ -2016,7 +2018,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } - public void WriteModuleHeader(PEFile module, bool skipMVID = false) + public void WriteModuleHeader(MetadataFile module, bool skipMVID = false) { var metadata = module.Metadata; @@ -2083,17 +2085,20 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("// MVID: {0}", metadata.GetGuid(moduleDefinition.Mvid).ToString("B").ToUpperInvariant()); } - var headers = module.Reader.PEHeaders; - output.WriteLine(".imagebase 0x{0:x8}", headers.PEHeader.ImageBase); - output.WriteLine(".file alignment 0x{0:x8}", headers.PEHeader.FileAlignment); - output.WriteLine(".stackreserve 0x{0:x8}", headers.PEHeader.SizeOfStackReserve); - output.WriteLine(".subsystem 0x{0:x} // {1}", headers.PEHeader.Subsystem, headers.PEHeader.Subsystem.ToString()); - output.WriteLine(".corflags 0x{0:x} // {1}", headers.CorHeader.Flags, headers.CorHeader.Flags.ToString()); + if (module is PEFile peFile) + { + var headers = peFile.Reader.PEHeaders; + output.WriteLine(".imagebase 0x{0:x8}", headers.PEHeader.ImageBase); + output.WriteLine(".file alignment 0x{0:x8}", headers.PEHeader.FileAlignment); + output.WriteLine(".stackreserve 0x{0:x8}", headers.PEHeader.SizeOfStackReserve); + output.WriteLine(".subsystem 0x{0:x} // {1}", headers.PEHeader.Subsystem, headers.PEHeader.Subsystem.ToString()); + output.WriteLine(".corflags 0x{0:x} // {1}", headers.CorHeader.Flags, headers.CorHeader.Flags.ToString()); + } WriteAttributes(module, metadata.GetCustomAttributes(EntityHandle.ModuleDefinition)); } - public void WriteModuleContents(PEFile module) + public void WriteModuleContents(MetadataFile module) { foreach (var handle in Process(module, module.Metadata.GetTopLevelTypeDefinitions().ToArray())) { diff --git a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs index ce8cc84f5..754fe1f9a 100644 --- a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs +++ b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs @@ -79,7 +79,7 @@ namespace ICSharpCode.Decompiler.Documentation /// /// Either TypeDefinitionHandle, if the type is defined in the module or ExportedTypeHandle, /// if the module contains a type forwarder. Returns a nil handle, if the type was not found. - public EntityHandle ResolveInPEFile(PEFile module) + public EntityHandle ResolveInPEFile(MetadataFile module) { string[] parts = typeName.Split('.'); for (int i = parts.Length - 1; i >= 0; i--) diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs index 690eca689..ba2b1d95b 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation public static class XmlDocLoader { static readonly Lazy mscorlibDocumentation = new Lazy(LoadMscorlibDocumentation); - static readonly ConditionalWeakTable cache = new ConditionalWeakTable(); + static readonly ConditionalWeakTable cache = new(); static XmlDocumentationProvider LoadMscorlibDocumentation() { @@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.Documentation get { return mscorlibDocumentation.Value; } } - public static XmlDocumentationProvider LoadDocumentation(PEFile module) + public static XmlDocumentationProvider LoadDocumentation(MetadataFile module) { if (module == null) throw new ArgumentNullException(nameof(module)); diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 36513a754..7fe6df907 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -98,6 +98,7 @@ + @@ -146,6 +147,7 @@ + diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 377f9a24d..259367b2d 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -26,8 +26,8 @@ using System.Reflection.Metadata; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -53,11 +53,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; } - internal static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, MethodDefinitionHandle method) + internal static bool IsCompilerGeneratedMainMethod(MetadataFile module, MethodDefinitionHandle method) { var metadata = module.Metadata; var definition = metadata.GetMethodDefinition(method); - var entrypoint = System.Reflection.Metadata.Ecma335.MetadataTokens.MethodDefinitionHandle(module.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); + var entrypoint = System.Reflection.Metadata.Ecma335.MetadataTokens.MethodDefinitionHandle(module.CorHeader?.EntryPointTokenOrRelativeVirtualAddress ?? 0); return method == entrypoint && metadata.GetString(definition.Name).Equals("
", StringComparison.Ordinal); } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index 8c60690a6..dbea7d4cf 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -496,7 +496,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow classTypeParameters: (genericContext.ClassTypeParameters ?? EmptyList.Instance) .Concat(genericContext.MethodTypeParameters ?? EmptyList.Instance).ToArray(), methodTypeParameters: null); - var body = context.TypeSystem.MainModule.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = context.TypeSystem.MainModule.MetadataFile.GetMethodBody(methodDef.RelativeVirtualAddress); var il = context.CreateILReader() .ReadIL(method, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken); il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true), @@ -1438,7 +1438,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ITypeDefinition declaringTypeDefinition = call.Method.DeclaringTypeDefinition; if (declaringTypeDefinition.MetadataToken != this.enumeratorType) return false; - if (declaringTypeDefinition.ParentModule.PEFile.Metadata != metadata) + if (declaringTypeDefinition.ParentModule.MetadataFile.Metadata != metadata) return false; finallyMethod = call.Method; return !call.Method.MetadataToken.IsNil; diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 4aaa4a739..21f8e5290 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -690,7 +690,7 @@ namespace ICSharpCode.Decompiler.IL output.WriteLine(); } new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } - .WriteExceptionHandlers(module.PEFile, method, body); + .WriteExceptionHandlers(module.MetadataFile, method, body); } /// diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index 3a78c1ffc..bf8734357 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (genericContext == null) return null; var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDefinition.RelativeVirtualAddress); var function = ilReader.ReadIL((MethodDefinitionHandle)targetMethod.MetadataToken, body, genericContext.Value, ILFunctionKind.Delegate, context.CancellationToken); function.DelegateType = delegateType; // Embed the lambda into the parent function's ILAst, so that "Show steps" can show diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index 35c5fd7fb..6b0fcc3f0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms public DecompilerSettings Settings { get; } public CancellationToken CancellationToken { get; set; } public Stepper Stepper { get; set; } - public Metadata.PEFile PEFile => TypeSystem.MainModule.PEFile; + public Metadata.MetadataFile PEFile => TypeSystem.MainModule.MetadataFile; internal DecompileRun? DecompileRun { get; set; } internal ResolvedUsingScope? UsingScope => DecompileRun?.UsingScope.Resolve(TypeSystem); diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index ebc9a149a..bc0e209c4 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -80,7 +80,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Disable the transform if we are decompiling a display-class or local function method: // This happens if a local function or display class is selected in the ILSpy tree view. if (IsLocalFunctionMethod(function.Method, context) || IsLocalFunctionDisplayClass( - function.Method.ParentModule.PEFile, + function.Method.ParentModule.MetadataFile, (TypeDefinitionHandle)function.Method.DeclaringTypeDefinition.MetadataToken, context) ) @@ -462,7 +462,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms else { var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDefinition.RelativeVirtualAddress); function = ilReader.ReadIL((MethodDefinitionHandle)targetMethod.MetadataToken, body, genericContext.GetValueOrDefault(), ILFunctionKind.LocalFunction, @@ -755,10 +755,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (method.MetadataToken.IsNil) return false; - return IsLocalFunctionMethod(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken, context); + return IsLocalFunctionMethod(method.ParentModule.MetadataFile, (MethodDefinitionHandle)method.MetadataToken, context); } - public static bool IsLocalFunctionMethod(PEFile module, MethodDefinitionHandle methodHandle, ILTransformContext context = null) + public static bool IsLocalFunctionMethod(MetadataFile module, MethodDefinitionHandle methodHandle, ILTransformContext context = null) { if (context != null && context.PEFile != module) return false; @@ -776,7 +776,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } - public static bool LocalFunctionNeedsAccessibilityChange(PEFile module, MethodDefinitionHandle methodHandle) + public static bool LocalFunctionNeedsAccessibilityChange(MetadataFile module, MethodDefinitionHandle methodHandle) { if (!IsLocalFunctionMethod(module, methodHandle)) return false; @@ -797,7 +797,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; } - public static bool IsLocalFunctionDisplayClass(PEFile module, TypeDefinitionHandle typeHandle, ILTransformContext context = null) + public static bool IsLocalFunctionDisplayClass(MetadataFile module, TypeDefinitionHandle typeHandle, ILTransformContext context = null) { if (context != null && context.PEFile != module) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs index 2d82abd29..164b806e2 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var genericContext = new GenericContext(inst.Method); // partially copied from CSharpDecompiler var ilReader = context.CreateILReader(); - var body = context.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var body = context.PEFile.GetMethodBody(methodDef.RelativeVirtualAddress); var proxyFunction = ilReader.ReadIL(handle, body, genericContext, ILFunctionKind.TopLevelFunction, context.CancellationToken); var transformContext = new ILTransformContext(context, proxyFunction); proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs index 1944872a8..cc0027b0a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs @@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (context.Settings.Utf8StringLiterals && elementType.IsKnownType(KnownTypeCode.Byte) && DecodeUTF8String(initialValue, size, out string text)) @@ -311,7 +311,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { return false; } - blob = fd.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + blob = fd.GetInitialValue(context.PEFile, context.TypeSystem); return true; } @@ -720,7 +720,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (DecodeArrayInitializer(arrayType, initialValue, arrayLength, valuesList)) { values = valuesList.ToArray(); @@ -753,7 +753,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) return false; var valuesList = new List(); - var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); + var initialValue = field.GetInitialValue(context.PEFile, context.TypeSystem); if (!DecodeArrayInitializer(elementType, initialValue, arrayLength, valuesList)) return false; context.Step("InlineRuntimeHelpersInitializeArray: single-dim", inst); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index a62e16eb2..078faa381 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -413,11 +413,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (definition == null) return false; - if (definition.ParentModule.PEFile != context.PEFile) + if (definition.ParentModule.MetadataFile != context.PEFile) return false; // We do not want to accidentially transform state-machines and thus destroy them. var token = (TypeDefinitionHandle)definition.MetadataToken; - var metadata = definition.ParentModule.PEFile.Metadata; + var metadata = definition.ParentModule.MetadataFile.Metadata; if (YieldReturnDecompiler.IsCompilerGeneratorEnumerator(token, metadata)) return false; if (AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(token, metadata)) @@ -440,13 +440,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; var handle = (MethodDefinitionHandle)method.MetadataToken; var module = (MetadataModule)method.ParentModule; - var file = module.PEFile; + var file = module.MetadataFile; if (handle.IsNil || file != context.PEFile) return false; var def = file.Metadata.GetMethodDefinition(handle); if (def.RelativeVirtualAddress == 0) return false; - var body = file.Reader.GetMethodBody(def.RelativeVirtualAddress); + var body = file.GetMethodBody(def.RelativeVirtualAddress); // some compilers produce ctors with unused local variables // see https://github.com/icsharpcode/ILSpy/issues/2174 //if (!body.LocalSignature.IsNil) diff --git a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs index 983eaf0f5..557e80e88 100644 --- a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs +++ b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs @@ -61,10 +61,10 @@ namespace ICSharpCode.Decompiler.Metadata public interface IAssemblyResolver { #if !VSADDIN - PEFile? Resolve(IAssemblyReference reference); - PEFile? ResolveModule(PEFile mainModule, string moduleName); - Task ResolveAsync(IAssemblyReference reference); - Task ResolveModuleAsync(PEFile mainModule, string moduleName); + MetadataFile? Resolve(IAssemblyReference reference); + MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName); + Task ResolveAsync(IAssemblyReference reference); + Task ResolveModuleAsync(MetadataFile mainModule, string moduleName); #endif } @@ -323,7 +323,7 @@ namespace ICSharpCode.Decompiler.Metadata entry = metadata.GetAssemblyReference(handle); } - public AssemblyReference(PEFile module, AssemblyReferenceHandle handle) + public AssemblyReference(MetadataFile module, AssemblyReferenceHandle handle) { if (module == null) throw new ArgumentNullException(nameof(module)); diff --git a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs index 241996e0b..75a5187fb 100644 --- a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs +++ b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Metadata /// /// The module containing the code. /// - public PEFile Module { get; } + public MetadataFile Module { get; } /// /// The (parent) TypeDef containing the code. @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.Metadata /// /// Creates a instance using the given and . /// - public CodeMappingInfo(PEFile module, TypeDefinitionHandle type) + public CodeMappingInfo(MetadataFile module, TypeDefinitionHandle type) { this.Module = module; this.TypeDefinition = type; diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index 9e31cf9c9..692515ca9 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -18,7 +18,6 @@ using System; using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; using System.Text.RegularExpressions; using ICSharpCode.Decompiler.TypeSystem; @@ -40,7 +39,7 @@ namespace ICSharpCode.Decompiler.Metadata @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + @"|(packs[/\\](?[^/\\]+)\\(?[^/\\]+)\\ref([/\\].*)?[/\\])"; - public static string DetectTargetFrameworkId(this PEFile assembly) + public static string DetectTargetFrameworkId(this MetadataFile assembly) { return DetectTargetFrameworkId(assembly.Metadata, assembly.FileName); } @@ -178,17 +177,16 @@ namespace ICSharpCode.Decompiler.Metadata return string.Empty; } - public static bool IsReferenceAssembly(this PEFile assembly) + public static bool IsReferenceAssembly(this MetadataFile assembly) { - return IsReferenceAssembly(assembly.Reader, assembly.FileName); + return IsReferenceAssembly(assembly.Metadata, assembly.FileName); } - public static bool IsReferenceAssembly(this PEReader assembly, string assemblyPath) + public static bool IsReferenceAssembly(this MetadataReader metadata, string assemblyPath) { - if (assembly == null) - throw new ArgumentNullException(nameof(assembly)); + if (metadata == null) + throw new ArgumentNullException(nameof(metadata)); - var metadata = assembly.GetMetadataReader(); if (metadata.GetCustomAttributes(Handle.AssemblyDefinition).HasKnownAttribute(metadata, KnownAttribute.ReferenceAssembly)) return true; @@ -197,7 +195,7 @@ namespace ICSharpCode.Decompiler.Metadata return refPathMatch.Success; } - public static string DetectRuntimePack(this PEFile assembly) + public static string DetectRuntimePack(this MetadataFile assembly) { if (assembly is null) { diff --git a/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs b/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs index a2c1414b6..d914f8685 100644 --- a/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs +++ b/ICSharpCode.Decompiler/Metadata/EnumUnderlyingTypeResolveException.cs @@ -35,12 +35,12 @@ namespace ICSharpCode.Decompiler.Metadata } [Serializable] - public class PEFileNotSupportedException : Exception + public class MetadataFileNotSupportedException : Exception { - public PEFileNotSupportedException() { } - public PEFileNotSupportedException(string message) : base(message) { } - public PEFileNotSupportedException(string message, Exception inner) : base(message, inner) { } - protected PEFileNotSupportedException( + public MetadataFileNotSupportedException() { } + public MetadataFileNotSupportedException(string message) : base(message) { } + public MetadataFileNotSupportedException(string message, Exception inner) : base(message, inner) { } + protected MetadataFileNotSupportedException( SerializationInfo info, StreamingContext context) : base(info, context) { } } diff --git a/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs index 012525b1e..cb0c595f0 100644 --- a/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs +++ b/ICSharpCode.Decompiler/Metadata/FindTypeDecoder.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Metadata { public class FindTypeDecoder : ISignatureTypeProvider { - readonly PEFile declaringModule; + readonly MetadataFile declaringModule; readonly MetadataModule? currentModule; readonly TypeDefinitionHandle handle; readonly string? typeName; @@ -40,7 +40,7 @@ namespace ICSharpCode.Decompiler.Metadata /// Constructs a FindTypeDecoder that finds uses of a specific type-definition handle. /// This assumes that the module we are search in is the same as the module containing the type-definiton. /// - internal FindTypeDecoder(TypeDefinitionHandle handle, PEFile declaringModule) + internal FindTypeDecoder(TypeDefinitionHandle handle, MetadataFile declaringModule) { this.handle = handle; this.declaringModule = declaringModule; @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.Metadata public FindTypeDecoder(MetadataModule currentModule, ITypeDefinition type) { this.currentModule = currentModule; - this.declaringModule = type.ParentModule?.PEFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); + this.declaringModule = type.ParentModule?.MetadataFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); this.handle = (TypeDefinitionHandle)type.MetadataToken; this.primitiveType = type.KnownTypeCode == KnownTypeCode.None ? 0 : type.KnownTypeCode.ToPrimitiveTypeCode(); this.typeName = type.MetadataName; @@ -128,7 +128,7 @@ namespace ICSharpCode.Decompiler.Metadata if (td == null) return false; - return td.MetadataToken == this.handle && td.ParentModule?.PEFile == declaringModule; + return td.MetadataToken == this.handle && td.ParentModule?.MetadataFile == declaringModule; } public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index 8a7df4bee..90f44096a 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -1,6 +1,25 @@ -using System; +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; @@ -426,5 +445,23 @@ namespace ICSharpCode.Decompiler.Metadata return new(metadataReader.MetadataPointer, metadataReader.MetadataLength); } } + + public static uint ReadULEB128(this BinaryReader reader) + { + uint val = 0; + int shift = 0; + while (true) + { + byte b = reader.ReadByte(); + val |= (b & 0b0111_1111u) << shift; + if ((b & 0b1000_0000) == 0) + break; + shift += 7; + if (shift >= 35) + throw new OverflowException(); + } + return val; + } + } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataFile.cs b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs new file mode 100644 index 000000000..c92c0e061 --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/MetadataFile.cs @@ -0,0 +1,332 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + +namespace ICSharpCode.Decompiler.Metadata +{ + /// + /// MetadataFile is the main class the decompiler uses to represent a metadata assembly/module. + /// Every file on disk can be loaded into a standalone MetadataFile instance. + /// + /// A MetadataFile can be combined with its referenced assemblies/modules to form a type system, + /// in that case the class is used instead. + /// + /// + /// In addition to wrapping a System.Reflection.Metadata.MetadataReader, this class + /// contains a few decompiler-specific caches to allow efficiently constructing a type + /// system from multiple MetadataFiles. This allows the caches to be shared across multiple + /// decompiled type systems. + /// + [DebuggerDisplay("{Kind}: {FileName}")] + public class MetadataFile + { + public enum MetadataFileKind + { + PortableExecutable, + ProgramDebugDatabase, + WebCIL, + Metadata + } + + public string FileName { get; } + public MetadataFileKind Kind { get; } + public MetadataReader Metadata { get; } + + public virtual int MetadataOffset { get; } + public virtual bool IsEmbedded { get; } + + public bool IsAssembly => Metadata.IsAssembly; + + string? name; + + public string Name { + get { + var value = LazyInit.VolatileRead(ref name); + if (value == null) + { + var metadata = Metadata; + value = metadata.IsAssembly + ? metadata.GetString(metadata.GetAssemblyDefinition().Name) + : metadata.GetString(metadata.GetModuleDefinition().Name); + value = LazyInit.GetOrSet(ref name, value); + } + return value; + } + } + + string? fullName; + + public string FullName { + get { + var value = LazyInit.VolatileRead(ref fullName); + if (value == null) + { + var metadata = Metadata; + value = metadata.IsAssembly ? metadata.GetFullAssemblyName() : Name; + value = LazyInit.GetOrSet(ref fullName, value); + } + return value; + } + } + + public TargetRuntime GetRuntime() + { + string version = Metadata.MetadataVersion; + if (version == null || version.Length <= 1) + return TargetRuntime.Unknown; + switch (version[1]) + { + case '1': + if (version.Length <= 3) + return TargetRuntime.Unknown; + if (version[3] == 1) + return TargetRuntime.Net_1_0; + else + return TargetRuntime.Net_1_1; + case '2': + return TargetRuntime.Net_2_0; + case '4': + return TargetRuntime.Net_4_0; + default: + return TargetRuntime.Unknown; + } + } + + ImmutableArray assemblyReferences; + public ImmutableArray AssemblyReferences { + get { + var value = assemblyReferences; + if (value.IsDefault) + { + value = Metadata.AssemblyReferences.Select(r => new AssemblyReference(this.Metadata, r)).ToImmutableArray(); + assemblyReferences = value; + } + return value; + } + } + + ImmutableArray moduleReferences; + public ImmutableArray ModuleReferences { + get { + var value = moduleReferences; + if (value.IsDefault) + { + value = Metadata.GetModuleReferences() + .Select(m => new ModuleReferenceMetadata(this.Metadata, m)) + .ToImmutableArray(); + + moduleReferences = value; + } + return value; + } + } + + public ImmutableArray Resources => GetResources().ToImmutableArray(); + + IEnumerable GetResources() + { + var metadata = Metadata; + foreach (var h in metadata.ManifestResources) + { + yield return new MetadataResource(this, h); + } + } + + Dictionary? typeLookup; + + /// + /// Finds the top-level-type with the specified name. + /// + public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName) + { + var lookup = LazyInit.VolatileRead(ref typeLookup); + if (lookup == null) + { + lookup = new Dictionary(); + foreach (var handle in Metadata.TypeDefinitions) + { + var td = Metadata.GetTypeDefinition(handle); + if (!td.GetDeclaringType().IsNil) + { + continue; // nested type + } + var nsHandle = td.Namespace; + string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle); + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount); + lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle; + } + lookup = LazyInit.GetOrSet(ref typeLookup, lookup); + } + if (lookup.TryGetValue(typeName, out var resultHandle)) + return resultHandle; + else + return default; + } + + Dictionary? typeForwarderLookup; + + /// + /// Finds the type forwarder with the specified name. + /// + public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName) + { + var lookup = LazyInit.VolatileRead(ref typeForwarderLookup); + if (lookup == null) + { + lookup = new Dictionary(); + foreach (var handle in Metadata.ExportedTypes) + { + var td = Metadata.GetExportedType(handle); + lookup[td.GetFullTypeName(Metadata)] = handle; + } + lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup); + } + if (lookup.TryGetValue(typeName, out var resultHandle)) + return resultHandle; + else + return default; + } + + MethodSemanticsLookup? methodSemanticsLookup; + + internal MethodSemanticsLookup MethodSemanticsLookup { + get { + var r = LazyInit.VolatileRead(ref methodSemanticsLookup); + if (r != null) + return r; + else + return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata)); + } + } + + public MetadataFile(MetadataFileKind kind, string fileName, MetadataReaderProvider metadata, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default, int metadataOffset = 0, bool isEmbedded = false) + { + this.Kind = kind; + this.FileName = fileName; + this.Metadata = metadata.GetMetadataReader(metadataOptions); + this.MetadataOffset = metadataOffset; + this.IsEmbedded = isEmbedded; + } + + private protected MetadataFile(MetadataFileKind kind, string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + { + this.Kind = kind; + this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); + _ = reader ?? throw new ArgumentNullException(nameof(reader)); + if (!reader.HasMetadata) + throw new MetadataFileNotSupportedException("PE file does not contain any managed metadata."); + this.Metadata = reader.GetMetadataReader(metadataOptions); + } + + public virtual MethodBodyBlock GetMethodBody(int rva) + { + throw new BadImageFormatException("This metadata file does not contain method bodies."); + } + + public virtual SectionData GetSectionData(int rva) + { + throw new BadImageFormatException("This metadata file does not support sections."); + } + + public virtual int GetContainingSectionIndex(int rva) + { + throw new BadImageFormatException("This metadata file does not support sections."); + } + + public virtual ImmutableArray SectionHeaders => throw new BadImageFormatException("This metadata file does not support sections."); + + /// + /// Gets the CLI header or null if the image does not have one. + /// + public virtual CorHeader? CorHeader => null; + + public IModuleReference WithOptions(TypeSystemOptions options) + { + return new MetadataFileWithOptions(this, options); + } + + private class MetadataFileWithOptions : IModuleReference + { + readonly MetadataFile peFile; + readonly TypeSystemOptions options; + + public MetadataFileWithOptions(MetadataFile peFile, TypeSystemOptions options) + { + this.peFile = peFile; + this.options = options; + } + + IModule IModuleReference.Resolve(ITypeResolveContext context) + { + return new MetadataModule(context.Compilation, peFile, options); + } + } + } + + /// + /// Abstraction over PEMemoryBlock + /// + public readonly unsafe struct SectionData + { + public byte* Pointer { get; } + public int Length { get; } + + public SectionData(PEMemoryBlock block) + { + Pointer = block.Pointer; + Length = block.Length; + } + + public SectionData(byte* startPointer, int length) + { + Pointer = startPointer; + Length = length; + } + + public BlobReader GetReader() + { + return new BlobReader(Pointer, Length); + } + + internal BlobReader GetReader(int offset, int size) + { + return new BlobReader(Pointer + offset, size); + } + } + + public struct SectionHeader + { + public string Name; + public uint VirtualSize; + public uint VirtualAddress; + public uint RawDataSize; + public uint RawDataPtr; + } +} diff --git a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs index 44779d0d3..0b96627b2 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataGenericContext.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Metadata this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType(); } - public MetadataGenericContext(TypeDefinitionHandle declaringType, PEFile module) + public MetadataGenericContext(TypeDefinitionHandle declaringType, MetadataFile module) { this.metadata = module.Metadata; this.method = default; diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs index c180de179..9277ed71f 100644 --- a/ICSharpCode.Decompiler/Metadata/PEFile.cs +++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs @@ -19,7 +19,6 @@ #nullable enable using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.IO; @@ -28,62 +27,11 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.Metadata { - public class MetadataFile - { - public enum MetadataFileKind - { - PortableExecutable, - ProgramDebugDatabase, - Metadata - } - - public string FileName { get; } - public MetadataFileKind Kind { get; } - public MetadataReader Metadata { get; } - - public virtual int MetadataOffset { get; } - public virtual bool IsEmbedded { get; } - - public MetadataFile(string fileName, MetadataReaderProvider metadata, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default, int metadataOffset = 0, bool isEmbedded = false) - { - this.FileName = fileName; - this.Metadata = metadata.GetMetadataReader(metadataOptions); - this.MetadataOffset = metadataOffset; - this.IsEmbedded = isEmbedded; - this.Kind = isEmbedded || Path.GetExtension(fileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata; - } - - private protected MetadataFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) - { - this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); - _ = reader ?? throw new ArgumentNullException(nameof(reader)); - if (!reader.HasMetadata) - throw new PEFileNotSupportedException("PE file does not contain any managed metadata."); - this.Metadata = reader.GetMetadataReader(metadataOptions); - this.Kind = MetadataFileKind.PortableExecutable; - } - } - - - /// - /// PEFile is the main class the decompiler uses to represent a metadata assembly/module. - /// Every file on disk can be loaded into a standalone PEFile instance. - /// - /// A PEFile can be combined with its referenced assemblies/modules to form a type system, - /// in that case the class is used instead. - /// - /// - /// In addition to wrapping a System.Reflection.Metadata.PEReader, this class - /// contains a few decompiler-specific caches to allow efficiently constructing a type - /// system from multiple PEFiles. This allows the caches to be shared across multiple - /// decompiled type systems. - /// [DebuggerDisplay("{FileName}")] - public class PEFile : MetadataFile, IDisposable, TypeSystem.IModuleReference + public class PEFile : MetadataFile, IDisposable, IModuleReference { public PEReader Reader { get; } @@ -98,209 +46,59 @@ namespace ICSharpCode.Decompiler.Metadata } public PEFile(string fileName, PEReader reader, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) - : base(fileName, reader, metadataOptions) + : base(MetadataFileKind.PortableExecutable, fileName, reader, metadataOptions) { this.Reader = reader; } - public bool IsAssembly => Metadata.IsAssembly; - public override bool IsEmbedded => false; public override int MetadataOffset => Reader.PEHeaders.MetadataStartOffset; - string? name; - - public string Name { - get { - var value = LazyInit.VolatileRead(ref name); - if (value == null) - { - var metadata = Metadata; - value = metadata.IsAssembly - ? metadata.GetString(metadata.GetAssemblyDefinition().Name) - : metadata.GetString(metadata.GetModuleDefinition().Name); - value = LazyInit.GetOrSet(ref name, value); - } - return value; - } - } - - string? fullName; - - public string FullName { - get { - var value = LazyInit.VolatileRead(ref fullName); - if (value == null) - { - var metadata = Metadata; - value = metadata.IsAssembly ? metadata.GetFullAssemblyName() : Name; - value = LazyInit.GetOrSet(ref fullName, value); - } - return value; - } - } - - public TargetRuntime GetRuntime() - { - string version = Metadata.MetadataVersion; - if (version == null || version.Length <= 1) - return TargetRuntime.Unknown; - switch (version[1]) - { - case '1': - if (version.Length <= 3) - return TargetRuntime.Unknown; - if (version[3] == 1) - return TargetRuntime.Net_1_0; - else - return TargetRuntime.Net_1_1; - case '2': - return TargetRuntime.Net_2_0; - case '4': - return TargetRuntime.Net_4_0; - default: - return TargetRuntime.Unknown; - } - } - - ImmutableArray assemblyReferences; - - public ImmutableArray AssemblyReferences { - get { - var value = assemblyReferences; - if (value.IsDefault) - { - value = Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray(); - assemblyReferences = value; - } - return value; - } - } - - ImmutableArray moduleReferences; - public ImmutableArray ModuleReferences { - get { - var value = moduleReferences; - if (value.IsDefault) - { - value = Metadata.GetModuleReferences() - .Select(m => new ModuleReferenceMetadata(this, m)) - .ToImmutableArray(); - - moduleReferences = value; - } - return value; - } - } - - public ImmutableArray Resources => GetResources().ToImmutableArray(); - - IEnumerable GetResources() - { - var metadata = Metadata; - foreach (var h in metadata.ManifestResources) - { - yield return new MetadataResource(this, h); - } - } - public void Dispose() { Reader.Dispose(); } - Dictionary? typeLookup; - - /// - /// Finds the top-level-type with the specified name. - /// - public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName) + IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) { - var lookup = LazyInit.VolatileRead(ref typeLookup); - if (lookup == null) - { - lookup = new Dictionary(); - foreach (var handle in Metadata.TypeDefinitions) - { - var td = Metadata.GetTypeDefinition(handle); - if (!td.GetDeclaringType().IsNil) - { - continue; // nested type - } - var nsHandle = td.Namespace; - string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle); - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount); - lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle; - } - lookup = LazyInit.GetOrSet(ref typeLookup, lookup); - } - if (lookup.TryGetValue(typeName, out var resultHandle)) - return resultHandle; - else - return default; + return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); } - Dictionary? typeForwarderLookup; - - /// - /// Finds the type forwarder with the specified name. - /// - public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName) + public override MethodBodyBlock GetMethodBody(int rva) { - var lookup = LazyInit.VolatileRead(ref typeForwarderLookup); - if (lookup == null) - { - lookup = new Dictionary(); - foreach (var handle in Metadata.ExportedTypes) - { - var td = Metadata.GetExportedType(handle); - lookup[td.GetFullTypeName(Metadata)] = handle; - } - lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup); - } - if (lookup.TryGetValue(typeName, out var resultHandle)) - return resultHandle; - else - return default; + return Reader.GetMethodBody(rva); } - MethodSemanticsLookup? methodSemanticsLookup; - - internal MethodSemanticsLookup MethodSemanticsLookup { - get { - var r = LazyInit.VolatileRead(ref methodSemanticsLookup); - if (r != null) - return r; - else - return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata)); - } - } - - public TypeSystem.IModuleReference WithOptions(TypeSystemOptions options) + public override SectionData GetSectionData(int rva) { - return new PEFileWithOptions(this, options); + return new SectionData(Reader.GetSectionData(rva)); } - IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) + public override int GetContainingSectionIndex(int rva) { - return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); + return Reader.PEHeaders.GetContainingSectionIndex(rva); } - private class PEFileWithOptions : TypeSystem.IModuleReference - { - readonly PEFile peFile; - readonly TypeSystemOptions options; - - public PEFileWithOptions(PEFile peFile, TypeSystemOptions options) - { - this.peFile = peFile; - this.options = options; - } - - IModule TypeSystem.IModuleReference.Resolve(ITypeResolveContext context) - { - return new MetadataModule(context.Compilation, peFile, options); + ImmutableArray sectionHeaders; + public override ImmutableArray SectionHeaders { + get { + var value = sectionHeaders; + if (value.IsDefault) + { + value = Reader.PEHeaders.SectionHeaders + .Select(h => new SectionHeader { + Name = h.Name, + RawDataPtr = unchecked((uint)h.PointerToRawData), + RawDataSize = unchecked((uint)h.SizeOfRawData), + VirtualAddress = unchecked((uint)h.VirtualAddress), + VirtualSize = unchecked((uint)h.VirtualSize) + }).ToImmutableArray(); + sectionHeaders = value; + } + return value; } } + + public override CorHeader? CorHeader => Reader.PEHeaders.CorHeader; } } diff --git a/ICSharpCode.Decompiler/Metadata/Resource.cs b/ICSharpCode.Decompiler/Metadata/Resource.cs index ca3ece687..e1f22eb6a 100644 --- a/ICSharpCode.Decompiler/Metadata/Resource.cs +++ b/ICSharpCode.Decompiler/Metadata/Resource.cs @@ -23,7 +23,6 @@ using System.IO; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; namespace ICSharpCode.Decompiler.Metadata { @@ -67,11 +66,11 @@ namespace ICSharpCode.Decompiler.Metadata sealed class MetadataResource : Resource { - public PEFile Module { get; } + public MetadataFile Module { get; } public ManifestResourceHandle Handle { get; } public bool IsNil => Handle.IsNil; - public MetadataResource(PEFile module, ManifestResourceHandle handle) + public MetadataResource(MetadataFile module, ManifestResourceHandle handle) { this.Module = module ?? throw new ArgumentNullException(nameof(module)); this.Handle = handle; @@ -117,15 +116,13 @@ namespace ICSharpCode.Decompiler.Metadata // embedded resources cannot be read from this binary. if (ResourceType != ResourceType.Embedded) return false; - // get cor header - var headers = Module.Reader.PEHeaders; - if (headers.CorHeader == null) + if (Module.CorHeader == null) return false; - var resources = headers.CorHeader.ResourcesDirectory; + var resources = Module.CorHeader.ResourcesDirectory; // validate resources directory, GetSectionData throws on negative RVAs if (resources.RelativeVirtualAddress <= 0) return false; - var sectionData = Module.Reader.GetSectionData(resources.RelativeVirtualAddress); + var sectionData = Module.GetSectionData(resources.RelativeVirtualAddress); // validate section length: we need at least 4 bytes to extract // the actual length of the resource blob. if (sectionData.Length < 4) @@ -144,7 +141,7 @@ namespace ICSharpCode.Decompiler.Metadata { if (!TryReadResource(out var ptr, out var length)) return null; - return new ResourceMemoryStream(Module.Reader, ptr + sizeof(int), length); + return new ResourceMemoryStream(Module, ptr + sizeof(int), length); } public unsafe override long? TryGetLength() @@ -158,10 +155,10 @@ namespace ICSharpCode.Decompiler.Metadata sealed unsafe class ResourceMemoryStream : UnmanagedMemoryStream { #pragma warning disable IDE0052 // Remove unread private members - readonly PEReader peReader; + readonly MetadataFile peReader; #pragma warning restore IDE0052 // Remove unread private members - public ResourceMemoryStream(PEReader peReader, byte* data, long length) + public ResourceMemoryStream(MetadataFile peReader, byte* data, long length) : base(data, length, length, FileAccess.Read) { // Keep the PEReader alive while the stream in in use. diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 92fff14b0..ff27d30d6 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -209,13 +209,13 @@ namespace ICSharpCode.Decompiler.Metadata } #if !VSADDIN - public PEFile? Resolve(IAssemblyReference name) + public MetadataFile? Resolve(IAssemblyReference name) { var file = FindAssemblyFile(name); return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex)); } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { string? baseDirectory = Path.GetDirectoryName(mainModule.FileName); if (baseDirectory == null) @@ -224,7 +224,7 @@ namespace ICSharpCode.Decompiler.Metadata return CreatePEFileFromFileName(moduleFileName, ex => new ResolutionException(mainModule.FileName, moduleName, moduleFileName, ex)); } - private PEFile? CreatePEFileFromFileName(string? fileName, Func makeException) + private MetadataFile? CreatePEFileFromFileName(string? fileName, Func makeException) { if (fileName == null) { @@ -251,12 +251,12 @@ namespace ICSharpCode.Decompiler.Metadata return null; } - public Task ResolveAsync(IAssemblyReference name) + public Task ResolveAsync(IAssemblyReference name) { return Task.Run(() => Resolve(name)); } - public Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { return Task.Run(() => ResolveModule(mainModule, moduleName)); } diff --git a/ICSharpCode.Decompiler/Metadata/WebCilFile.cs b/ICSharpCode.Decompiler/Metadata/WebCilFile.cs new file mode 100644 index 000000000..291316085 --- /dev/null +++ b/ICSharpCode.Decompiler/Metadata/WebCilFile.cs @@ -0,0 +1,284 @@ +// Copyright (c) 2024 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.IO.MemoryMappedFiles; +using System.Reflection.Metadata; +using System.Text; + +using ICSharpCode.Decompiler.TypeSystem; + +#nullable enable + +namespace ICSharpCode.Decompiler.Metadata +{ + public class WebCilFile : MetadataFile, IDisposable, IModuleReference + { + readonly MemoryMappedViewAccessor view; + readonly long webcilOffset; + + private WebCilFile(string fileName, long webcilOffset, long metadataOffset, MemoryMappedViewAccessor view, ImmutableArray sectionHeaders, ImmutableArray wasmSections, MetadataReaderProvider provider, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + : base(MetadataFileKind.WebCIL, fileName, provider, metadataOptions, 0) + { + this.webcilOffset = webcilOffset; + this.MetadataOffset = (int)metadataOffset; + this.view = view; + this.SectionHeaders = sectionHeaders; + this.WasmSections = wasmSections; + } + + public static WebCilFile? FromStream(string fileName, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default) + { + using var memoryMappedFile = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); + var view = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); + try + { + // read magic "\0asm" + if (view.ReadUInt32(0) != WASM_MAGIC) + return null; + + // read version + if (view.ReadUInt32(4) != 1) + return null; + + using var stream = view.AsStream(); + using var reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen: true); + + stream.Position += 8; + + long metadataOffset = -1; + List sections = new List(); + + while (stream.Position < stream.Length) + { + WasmSectionId id = (WasmSectionId)reader.ReadByte(); + uint size = reader.ReadULEB128(); + sections.Add(new WasmSection(id, stream.Position, size, view)); + + if (id == WasmSectionId.Custom && size == 0) + { + break; + } + stream.Seek(size, SeekOrigin.Current); + } + + foreach (var section in sections) + { + if (section.Id != WasmSectionId.Data || metadataOffset > -1) + continue; + + stream.Seek(section.Offset, SeekOrigin.Begin); + + uint numSegments = reader.ReadULEB128(); + if (numSegments != 2) + continue; + + // skip the first segment + if (reader.ReadByte() != 1) + continue; + + long segmentLength = reader.ReadULEB128(); + long segmentStart = reader.BaseStream.Position; + + reader.BaseStream.Seek(segmentLength, SeekOrigin.Current); + + if (reader.ReadByte() != 1) + continue; + + segmentLength = reader.ReadULEB128(); + if (TryReadWebCilSegment(reader, out var header, out metadataOffset, out var webcilOffset, out var sectionHeaders)) + { + stream.Seek(metadataOffset, SeekOrigin.Begin); + var metadata = MetadataReaderProvider.FromMetadataStream(stream, MetadataStreamOptions.LeaveOpen | MetadataStreamOptions.PrefetchMetadata); + + var result = new WebCilFile(fileName, webcilOffset, metadataOffset, view, ImmutableArray.Create(sectionHeaders), sections.ToImmutableArray(), metadata, metadataOptions); + + view = null; // don't dispose the view, we're still using it in the sections + return result; + } + } + + return null; + } + finally + { + view?.Dispose(); + } + } + + static unsafe bool TryReadWebCilSegment(BinaryReader reader, out WebcilHeader webcilHeader, out long metadataOffset, out long webcilOffset, [NotNullWhen(true)] out SectionHeader[]? sectionHeaders) + { + webcilHeader = default; + metadataOffset = -1; + sectionHeaders = null; + + webcilOffset = reader.BaseStream.Position; + + if (reader.ReadUInt32() != WEBCIL_MAGIC) + return false; + + webcilHeader.VersionMajor = reader.ReadUInt16(); + webcilHeader.VersionMinor = reader.ReadUInt16(); + webcilHeader.CoffSections = reader.ReadUInt16(); + _ = reader.ReadUInt16(); // reserved0 + webcilHeader.PECliHeaderRVA = reader.ReadUInt32(); + webcilHeader.PECliHeaderSize = reader.ReadUInt32(); + webcilHeader.PEDebugRVA = reader.ReadUInt32(); + webcilHeader.PEDebugSize = reader.ReadUInt32(); + + sectionHeaders = new SectionHeader[webcilHeader.CoffSections]; + for (int i = 0; i < webcilHeader.CoffSections; i++) + { + sectionHeaders[i].VirtualSize = reader.ReadUInt32(); + sectionHeaders[i].VirtualAddress = reader.ReadUInt32(); + sectionHeaders[i].RawDataSize = reader.ReadUInt32(); + sectionHeaders[i].RawDataPtr = reader.ReadUInt32(); + } + + long corHeaderStart = TranslateRVA(sectionHeaders, webcilOffset, webcilHeader.PECliHeaderRVA); + if (reader.BaseStream.Seek(corHeaderStart, SeekOrigin.Begin) != corHeaderStart) + return false; + int byteCount = reader.ReadInt32(); + int majorVersion = reader.ReadUInt16(); + int minorVersion = reader.ReadUInt16(); + metadataOffset = TranslateRVA(sectionHeaders, webcilOffset, (uint)reader.ReadInt32()); + return reader.BaseStream.Seek(metadataOffset, SeekOrigin.Begin) == metadataOffset; + } + + public override int MetadataOffset { get; } + + private static int GetContainingSectionIndex(IEnumerable sections, int rva) + { + int i = 0; + foreach (var section in sections) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + return i; + } + i++; + } + return -1; + } + + private static long TranslateRVA(IEnumerable sections, long webcilOffset, uint rva) + { + foreach (var section in sections) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + return section.RawDataPtr + (rva - section.VirtualAddress) + webcilOffset; + } + } + throw new BadImageFormatException("RVA not found in any section"); + } + + public override MethodBodyBlock GetMethodBody(int rva) + { + var reader = GetSectionData(rva).GetReader(); + return MethodBodyBlock.Create(reader); + } + + public override int GetContainingSectionIndex(int rva) + { + return GetContainingSectionIndex(SectionHeaders, rva); + } + + public override unsafe SectionData GetSectionData(int rva) + { + foreach (var section in SectionHeaders) + { + if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize) + { + byte* ptr = (byte*)0; + view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); + return new SectionData(ptr + section.RawDataPtr + webcilOffset + (rva - section.VirtualAddress), (int)section.RawDataSize); + } + } + throw new BadImageFormatException("RVA not found in any section"); + } + + public override ImmutableArray SectionHeaders { get; } + + public ImmutableArray WasmSections { get; } + + IModule? IModuleReference.Resolve(ITypeResolveContext context) + { + return new MetadataModule(context.Compilation, this, TypeSystemOptions.Default); + } + + public void Dispose() + { + view.Dispose(); + } + + public struct WebcilHeader + { + public ushort VersionMajor; + public ushort VersionMinor; + public ushort CoffSections; + public uint PECliHeaderRVA; + public uint PECliHeaderSize; + public uint PEDebugRVA; + public uint PEDebugSize; + } + + const uint WASM_MAGIC = 0x6d736100u; // "\0asm" + const uint WEBCIL_MAGIC = 0x4c496257u; // "WbIL" + + [DebuggerDisplay("WasmSection {Id}: {Offset} {Size}")] + public class WasmSection + { + public WasmSectionId Id; + public long Offset; + public uint Size; + private MemoryMappedViewAccessor view; + + public WasmSection(WasmSectionId id, long offset, uint size, MemoryMappedViewAccessor view) + { + this.Id = id; + this.Size = size; + this.Offset = offset; + this.view = view; + } + } + + public enum WasmSectionId : byte + { + // order matters: enum values must match the WebAssembly spec + Custom = 0, + Type = 1, + Import = 2, + Function = 3, + Table = 4, + Memory = 5, + Global = 6, + Export = 7, + Start = 8, + Element = 9, + Code = 10, + Data = 11, + DataCount = 12, + } + } +} diff --git a/ICSharpCode.Decompiler/NRExtensions.cs b/ICSharpCode.Decompiler/NRExtensions.cs index 7d98e27b4..2d978a777 100644 --- a/ICSharpCode.Decompiler/NRExtensions.cs +++ b/ICSharpCode.Decompiler/NRExtensions.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler internal static string GetDocumentation(this IEntity entity) { - var docProvider = XmlDocLoader.LoadDocumentation(entity.ParentModule.PEFile); + var docProvider = XmlDocLoader.LoadDocumentation(entity.ParentModule.MetadataFile); if (docProvider == null) return null; return docProvider.GetDocumentation(entity); diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index dff5dcef2..750f49f42 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Immutable; +using System.IO; +using System.IO.MemoryMappedFiles; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -624,7 +627,7 @@ namespace ICSharpCode.Decompiler } #endregion - public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, + public static unsafe BlobReader GetInitialValue(this FieldDefinition field, MetadataFile pefile, ICompilation typeSystem) { if (!field.HasFlag(FieldAttributes.HasFieldRVA)) @@ -650,10 +653,10 @@ namespace ICSharpCode.Decompiler public FieldValueSizeDecoder(ICompilation typeSystem = null) { this.module = (MetadataModule)typeSystem?.MainModule; - if (module == null) + if (module?.MetadataFile is not PEFile pefile) this.pointerSize = IntPtr.Size; else - this.pointerSize = module.PEFile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; + this.pointerSize = pefile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; } public int GetArrayType(int elementType, ArrayShape shape) => @@ -710,7 +713,7 @@ namespace ICSharpCode.Decompiler var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition(); if (typeDef == null || typeDef.MetadataToken.IsNil) return 0; - reader = typeDef.ParentModule.PEFile.Metadata; + reader = typeDef.ParentModule.MetadataFile.Metadata; var td = reader.GetTypeDefinition((TypeDefinitionHandle)typeDef.MetadataToken); return td.GetLayout().Size; } @@ -747,5 +750,11 @@ namespace ICSharpCode.Decompiler _ => callConv.ToString().ToLowerInvariant() }; } + + public static UnmanagedMemoryStream AsStream(this MemoryMappedViewAccessor view) + { + long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength); + return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size); + } } } diff --git a/ICSharpCode.Decompiler/SingleFileBundle.cs b/ICSharpCode.Decompiler/SingleFileBundle.cs index c92af8b35..b898639ed 100644 --- a/ICSharpCode.Decompiler/SingleFileBundle.cs +++ b/ICSharpCode.Decompiler/SingleFileBundle.cs @@ -104,18 +104,12 @@ namespace ICSharpCode.Decompiler public string RelativePath; // Path of an embedded file, relative to the Bundle source-directory. } - static UnmanagedMemoryStream AsStream(MemoryMappedViewAccessor view) - { - long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength); - return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size); - } - /// /// Reads the manifest header from the memory mapping. /// public static Header ReadManifest(MemoryMappedViewAccessor view, long bundleHeaderOffset) { - using var stream = AsStream(view); + using var stream = view.AsStream(); stream.Seek(bundleHeaderOffset, SeekOrigin.Begin); return ReadManifest(stream); } diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 5a46088f6..536b00cac 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -208,17 +208,17 @@ namespace ICSharpCode.Decompiler.TypeSystem { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver) : this(mainModule, assemblyResolver, TypeSystemOptions.Default) { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings) : this(mainModule, assemblyResolver, GetOptions(settings ?? throw new ArgumentNullException(nameof(settings)))) { } - public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) + public DecompilerTypeSystem(MetadataFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) { if (mainModule == null) throw new ArgumentNullException(nameof(mainModule)); @@ -232,16 +232,16 @@ namespace ICSharpCode.Decompiler.TypeSystem "System.Runtime.CompilerServices.Unsafe" }; - private async Task InitializeAsync(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) + private async Task InitializeAsync(MetadataFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) { // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. - var referencedAssemblies = new List(); - var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference, Task ResolveTask)>(); - var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => + var referencedAssemblies = new List(); + var assemblyReferenceQueue = new Queue<(bool IsAssembly, MetadataFile MainModule, object Reference, Task ResolveTask)>(); + var comparer = KeyComparer.Create(((bool IsAssembly, MetadataFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); - var assemblyReferencesInQueue = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); + var assemblyReferencesInQueue = new HashSet<(bool IsAssembly, MetadataFile Parent, object Reference)>(comparer); var mainMetadata = mainModule.Metadata; var tfm = mainModule.DetectTargetFrameworkId(); var (identifier, version) = UniversalAssemblyResolver.ParseTargetFramework(tfm); @@ -334,13 +334,13 @@ namespace ICSharpCode.Decompiler.TypeSystem } this.mainModule = (MetadataModule)base.MainModule; - void AddToQueue(bool isAssembly, PEFile mainModule, object reference) + void AddToQueue(bool isAssembly, MetadataFile mainModule, object reference) { if (assemblyReferencesInQueue.Add((isAssembly, mainModule, reference))) { // Immediately start loading the referenced module as we add the entry to the queue. // This allows loading multiple modules in parallel. - Task asm; + Task asm; if (isAssembly) { asm = assemblyResolver.ResolveAsync((IAssemblyReference)reference); diff --git a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs index b14a5566d..d7845bc4b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Gets the underlying metadata file. May return null, if the IAssembly was not created from a PE file. /// - PEFile? PEFile { get; } + MetadataFile? MetadataFile { get; } /// /// Gets whether this assembly is the main assembly of the compilation. diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index ee86a531d..023276071 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -168,14 +168,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (obj is MetadataEvent ev) { - return handle == ev.handle && module.PEFile == ev.module.PEFile; + return handle == ev.handle && module.MetadataFile == ev.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x7937039a ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x7937039a ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index d561e3be2..4486c90f5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -299,14 +299,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (obj is MetadataField f) { - return handle == f.handle && module.PEFile == f.module.PEFile; + return handle == f.handle && module.MetadataFile == f.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x11dda32b ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x11dda32b ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index 7964a590e..83946c9fa 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.attributes = def.Attributes; this.symbolKind = SymbolKind.Method; - var (accessorOwner, semanticsAttribute) = module.PEFile.MethodSemanticsLookup.GetSemantics(handle); + var (accessorOwner, semanticsAttribute) = module.MetadataFile.MethodSemanticsLookup.GetSemantics(handle); const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig); this.typeParameters = MetadataTypeParameter.Create(module, this, def.GetGenericParameters()); if (semanticsAttribute != 0 && !accessorOwner.IsNil @@ -606,14 +606,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (obj is MetadataMethod m) { - return handle == m.handle && module.PEFile == m.module.PEFile; + return handle == m.handle && module.MetadataFile == m.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x5a00d671 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x5a00d671 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 0dd339b99..da2d8a4cf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // "protected internal" (ProtectedOrInternal) accessibility is "reduced" // to "protected" accessibility across assembly boundaries. if (baseMember.Accessibility == Accessibility.ProtectedOrInternal - && this.ParentModule?.PEFile != baseMember.ParentModule?.PEFile) + && this.ParentModule?.MetadataFile != baseMember.ParentModule?.MetadataFile) { return Accessibility.Protected; } @@ -302,14 +302,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (obj is MetadataProperty p) { - return handle == p.handle && module.PEFile == p.module.PEFile; + return handle == p.handle && module.MetadataFile == p.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x32b6a76c ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x32b6a76c ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index 3eff3c142..632a3e4cc 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -258,7 +258,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods(); var methodsList = new List(methodsCollection.Count); - var methodSemantics = module.PEFile.MethodSemanticsLookup; + var methodSemantics = module.MetadataFile.MethodSemanticsLookup; bool hasDefaultCtor = false; foreach (MethodDefinitionHandle h in methodsCollection) { @@ -553,14 +553,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (obj is MetadataTypeDefinition td) { - return handle == td.handle && module.PEFile == td.module.PEFile; + return handle == td.handle && module.MetadataFile == td.module.MetadataFile; } return false; } public override int GetHashCode() { - return 0x2e0520f2 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x2e0520f2 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } bool IEquatable.Equals(IType other) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index 58bc4ca1b..282e5c2bf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -248,12 +248,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override int GetHashCode() { - return 0x51fc5b83 ^ module.PEFile.GetHashCode() ^ handle.GetHashCode(); + return 0x51fc5b83 ^ module.MetadataFile.GetHashCode() ^ handle.GetHashCode(); } public override bool Equals(IType other) { - return other is MetadataTypeParameter tp && handle == tp.handle && module.PEFile == tp.module.PEFile; + return other is MetadataTypeParameter tp && handle == tp.handle && module.MetadataFile == tp.module.MetadataFile; } public override string ToString() diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs index 28737d670..4f1b9cc8a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation string ISymbol.Name => "corlib"; SymbolKind ISymbol.SymbolKind => SymbolKind.Module; - Metadata.PEFile IModule.PEFile => null; + Metadata.MetadataFile IModule.MetadataFile => null; INamespace IModule.RootNamespace => rootNamespace; public IEnumerable TopLevelTypeDefinitions => typeDefinitions.Where(td => td != null); diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index a7f494373..bc7ff1bb4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -51,10 +51,10 @@ namespace ICSharpCode.Decompiler.TypeSystem readonly MetadataEvent[] eventDefs; readonly IModule[] referencedAssemblies; - internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options) + internal MetadataModule(ICompilation compilation, MetadataFile peFile, TypeSystemOptions options) { this.Compilation = compilation; - this.PEFile = peFile; + this.MetadataFile = peFile; this.metadata = peFile.Metadata; this.options = options; this.TypeProvider = new TypeProvider(this); @@ -112,8 +112,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public TypeSystemOptions TypeSystemOptions => options; - #region IAssembly interface - public PEFile PEFile { get; } + #region IModule interface + public MetadataFile MetadataFile { get; } public bool IsMainModule => this == Compilation.MainModule; @@ -129,10 +129,10 @@ namespace ICSharpCode.Decompiler.TypeSystem public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) { - var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName); + var typeDefHandle = MetadataFile.GetTypeDefinition(topLevelTypeName); if (typeDefHandle.IsNil) { - var forwarderHandle = PEFile.GetTypeForwarder(topLevelTypeName); + var forwarderHandle = MetadataFile.GetTypeForwarder(topLevelTypeName); if (!forwarderHandle.IsNil) { var forwarder = metadata.GetExportedType(forwarderHandle); diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 3ce5d0180..e26781cfb 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -699,14 +699,14 @@ namespace ICSharpCode.Decompiler.TypeSystem public static bool IsDirectImportOf(this ITypeDefinition type, IModule module) { var moduleReference = type.ParentModule; - foreach (var asmRef in module.PEFile.AssemblyReferences) + foreach (var asmRef in module.MetadataFile.AssemblyReferences) { if (asmRef.FullName == moduleReference.FullAssemblyName) return true; if (asmRef.Name == "netstandard" && asmRef.GetPublicKeyToken() != null) { var referencedModule = module.Compilation.FindModuleByReference(asmRef); - if (referencedModule != null && !referencedModule.PEFile.GetTypeForwarder(type.FullTypeName).IsNil) + if (referencedModule != null && !referencedModule.MetadataFile.GetTypeForwarder(type.FullTypeName).IsNil) return true; } } diff --git a/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs b/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs index 1947b0cc3..c5c4879aa 100644 --- a/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs +++ b/ICSharpCode.ILSpyX/Abstractions/ILanguage.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.ILSpyX.Abstractions public interface ILanguage { bool ShowMember(IEntity member); - string GetEntityName(PEFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics); + string GetEntityName(MetadataFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics); string GetTooltip(IEntity entity); string TypeToString(IType type, bool includeNamespace); diff --git a/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs b/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs index 836e43e22..b3732ae78 100644 --- a/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs +++ b/ICSharpCode.ILSpyX/Abstractions/ITreeNode.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpyX.Abstractions public interface ITreeNodeFactory { - ITreeNode CreateResourcesList(PEFile module); + ITreeNode CreateResourcesList(MetadataFile module); ITreeNode Create(Resource resource); } } diff --git a/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs index 7f6821eda..7daf2d24c 100644 --- a/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs +++ b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs @@ -33,9 +33,9 @@ namespace ICSharpCode.ILSpyX class AssemblyListSnapshot { readonly ImmutableArray assemblies; - Dictionary? asmLookupByFullName; - Dictionary? asmLookupByShortName; - Dictionary>? asmLookupByShortNameGrouped; + Dictionary? asmLookupByFullName; + Dictionary? asmLookupByShortName; + Dictionary>? asmLookupByShortNameGrouped; public ImmutableArray Assemblies => assemblies; public AssemblyListSnapshot(ImmutableArray assemblies) @@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpyX this.assemblies = assemblies; } - public async Task TryGetModuleAsync(IAssemblyReference reference, string tfm) + public async Task TryGetModuleAsync(IAssemblyReference reference, string tfm) { bool isWinRT = reference.IsWindowsRuntime; if (tfm.StartsWith(".NETFramework,Version=v4.", StringComparison.Ordinal)) @@ -57,12 +57,12 @@ namespace ICSharpCode.ILSpyX lookup = await CreateLoadedAssemblyLookupAsync(shortNames: isWinRT).ConfigureAwait(false); lookup = LazyInit.GetOrSet(ref isWinRT ? ref asmLookupByShortName : ref asmLookupByFullName, lookup); } - if (lookup.TryGetValue(key, out PEFile? module)) + if (lookup.TryGetValue(key, out MetadataFile? module)) return module; return null; } - public async Task TryGetSimilarModuleAsync(IAssemblyReference reference) + public async Task TryGetSimilarModuleAsync(IAssemblyReference reference) { var lookup = LazyInit.VolatileRead(ref asmLookupByShortNameGrouped); if (lookup == null) @@ -76,14 +76,14 @@ namespace ICSharpCode.ILSpyX return candidates.FirstOrDefault(c => c.version >= reference.Version).module ?? candidates.Last().module; } - private async Task> CreateLoadedAssemblyLookupAsync(bool shortNames) + private async Task> CreateLoadedAssemblyLookupAsync(bool shortNames) { - var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (LoadedAssembly loaded in assemblies) { try { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); if (module == null) continue; var reader = module.Metadata; @@ -109,15 +109,15 @@ namespace ICSharpCode.ILSpyX return result; } - private async Task>> CreateLoadedAssemblyShortNameGroupLookupAsync() + private async Task>> CreateLoadedAssemblyShortNameGroupLookupAsync() { - var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); + var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (LoadedAssembly loaded in assemblies) { try { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); var reader = module?.Metadata; if (reader == null || !reader.IsAssembly) continue; @@ -128,7 +128,7 @@ namespace ICSharpCode.ILSpyX if (!result.TryGetValue(asmDefName, out var existing)) { - existing = new List<(PEFile module, Version version)>(); + existing = new List<(MetadataFile module, Version version)>(); result.Add(asmDefName, existing); existing.Add(line); continue; @@ -170,7 +170,7 @@ namespace ICSharpCode.ILSpyX { AddDescendants(result.Package.RootFolder); } - else if (result.PEFile != null) + else if (result.MetadataFile != null) { results.Add(asm); } diff --git a/ICSharpCode.ILSpyX/LoadedAssembly.cs b/ICSharpCode.ILSpyX/LoadedAssembly.cs index ed9a3fae4..19509df00 100644 --- a/ICSharpCode.ILSpyX/LoadedAssembly.cs +++ b/ICSharpCode.ILSpyX/LoadedAssembly.cs @@ -35,6 +35,9 @@ using ICSharpCode.ILSpyX.PdbProvider; using K4os.Compression.LZ4; +using static ICSharpCode.Decompiler.Metadata.MetadataFile; + + #nullable enable namespace ICSharpCode.ILSpyX @@ -133,7 +136,7 @@ namespace ICSharpCode.ILSpyX var value = LazyInit.VolatileRead(ref targetFrameworkId); if (value == null) { - var assembly = await GetPEFileAsync().ConfigureAwait(false); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); value = assembly.DetectTargetFrameworkId() ?? string.Empty; value = LazyInit.GetOrSet(ref targetFrameworkId, value); } @@ -148,7 +151,7 @@ namespace ICSharpCode.ILSpyX var value = LazyInit.VolatileRead(ref runtimePack); if (value == null) { - var assembly = await GetPEFileAsync().ConfigureAwait(false); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); value = assembly.DetectRuntimePack() ?? string.Empty; value = LazyInit.GetOrSet(ref runtimePack, value); } @@ -169,13 +172,13 @@ namespace ICSharpCode.ILSpyX } /// - /// Gets the . + /// Gets the . /// - public async Task GetPEFileAsync() + public async Task GetMetadataFileAsync() { var loadResult = await loadingTask.ConfigureAwait(false); - if (loadResult.PEFile != null) - return loadResult.PEFile; + if (loadResult.MetadataFile != null) + return loadResult.MetadataFile; else throw loadResult.FileLoadException!; } @@ -184,12 +187,12 @@ namespace ICSharpCode.ILSpyX /// Gets the . /// Returns null in case of load errors. /// - public PEFile? GetPEFileOrNull() + public MetadataFile? GetMetadataFileOrNull() { try { var loadResult = loadingTask.GetAwaiter().GetResult(); - return loadResult.PEFile; + return loadResult.MetadataFile; } catch (Exception ex) { @@ -199,15 +202,15 @@ namespace ICSharpCode.ILSpyX } /// - /// Gets the . + /// Gets the . /// Returns null in case of load errors. /// - public async Task GetPEFileOrNullAsync() + public async Task GetMetadataFileOrNullAsync() { try { var loadResult = await loadingTask.ConfigureAwait(false); - return loadResult.PEFile; + return loadResult.MetadataFile; } catch (Exception ex) { @@ -228,7 +231,7 @@ namespace ICSharpCode.ILSpyX public ICompilation? GetTypeSystemOrNull() { return LazyInitializer.EnsureInitialized(ref this.typeSystem, () => { - var module = GetPEFileOrNull(); + var module = GetMetadataFileOrNull(); if (module == null) return null!; return new SimpleCompilation( @@ -247,7 +250,7 @@ namespace ICSharpCode.ILSpyX { if (typeSystemWithOptions != null && options == currentTypeSystemOptions) return typeSystemWithOptions; - var module = GetPEFileOrNull(); + var module = GetMetadataFileOrNull(); if (module == null) return null; currentTypeSystemOptions = options; @@ -312,7 +315,7 @@ namespace ICSharpCode.ILSpyX /// public bool IsLoadedAsValidAssembly { get { - return loadingTask.Status == TaskStatus.RanToCompletion && loadingTask.Result.PEFile != null; + return loadingTask.Status == TaskStatus.RanToCompletion && loadingTask.Result.MetadataFile != null; } } @@ -356,7 +359,7 @@ namespace ICSharpCode.ILSpyX return LoadAssembly(fileStream, PEStreamOptions.PrefetchEntireImage, applyWinRTProjections); } } - catch (PEFileNotSupportedException ex) + catch (MetadataFileNotSupportedException ex) { loadAssemblyException = ex; } @@ -380,6 +383,16 @@ namespace ICSharpCode.ILSpyX bundle.LoadedAssembly = this; return new LoadResult(loadAssemblyException, bundle); } + // If it's not a .NET module, maybe it's a WASM module + var wasm = WebCilFile.FromStream(fileName); + if (wasm != null) + { + lock (loadedAssemblies) + { + loadedAssemblies.Add(wasm, this); + } + return new LoadResult(loadAssemblyException, wasm); + } // If it's not a .NET module, maybe it's a zip archive (e.g. .nupkg) try { @@ -396,8 +409,9 @@ namespace ICSharpCode.ILSpyX { using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { + var kind = Path.GetExtension(fileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata; var metadata = MetadataReaderProvider.FromMetadataStream(fileStream, MetadataStreamOptions.PrefetchMetadata); - var metadataFile = new MetadataFile(fileName, metadata); + var metadataFile = new MetadataFile(kind, fileName, metadata); lock (loadedAssemblies) { loadedAssemblies.Add(metadataFile, this); @@ -463,8 +477,12 @@ namespace ICSharpCode.ILSpyX } } - IDebugInfoProvider? LoadDebugInfo(PEFile module) + IDebugInfoProvider? LoadDebugInfo(PEFile? module) { + if (module == null) + { + return null; + } if (useDebugSymbols) { try @@ -489,8 +507,8 @@ namespace ICSharpCode.ILSpyX public async Task LoadDebugInfo(string fileName) { this.PdbFileName = fileName; - var assembly = await GetPEFileAsync().ConfigureAwait(false); - debugInfoProvider = await Task.Run(() => LoadDebugInfo(assembly)); + var assembly = await GetMetadataFileAsync().ConfigureAwait(false); + debugInfoProvider = await Task.Run(() => LoadDebugInfo(assembly as PEFile)); return debugInfoProvider; } @@ -525,7 +543,7 @@ namespace ICSharpCode.ILSpyX this.referenceLoadInfo = parent.LoadedAssemblyReferencesInfo; } - public PEFile? Resolve(IAssemblyReference reference) + public MetadataFile? Resolve(IAssemblyReference reference) { return ResolveAsync(reference).GetAwaiter().GetResult(); } @@ -542,9 +560,9 @@ namespace ICSharpCode.ILSpyX /// 8) search C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /// 9) try to find match by asm name (no tfm/version) in loaded assemblies /// - public async Task ResolveAsync(IAssemblyReference reference) + public async Task ResolveAsync(IAssemblyReference reference) { - PEFile? module; + MetadataFile? module; // 0) if we're inside a package, look for filename.dll in parent directories if (providedAssemblyResolver != null) { @@ -580,7 +598,7 @@ namespace ICSharpCode.ILSpyX if (asm != null) { referenceLoadInfo.AddMessage(reference.FullName, MessageKind.Info, "Success - Loading from: " + file); - return await asm.GetPEFileOrNullAsync().ConfigureAwait(false); + return await asm.GetMetadataFileOrNullAsync().ConfigureAwait(false); } return null; } @@ -600,12 +618,12 @@ namespace ICSharpCode.ILSpyX } } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { return ResolveModuleAsync(mainModule, moduleName).GetAwaiter().GetResult(); } - public async Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public async Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { if (providedAssemblyResolver != null) { @@ -632,7 +650,7 @@ namespace ICSharpCode.ILSpyX } if (asm != null) { - return await asm.GetPEFileOrNullAsync().ConfigureAwait(false); + return await asm.GetMetadataFileOrNullAsync().ConfigureAwait(false); } } } @@ -640,7 +658,7 @@ namespace ICSharpCode.ILSpyX // Module does not exist on disk, look for one with a matching name in the assemblylist: foreach (LoadedAssembly loaded in alreadyLoadedAssemblies.Assemblies) { - var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); + var module = await loaded.GetMetadataFileOrNullAsync().ConfigureAwait(false); var reader = module?.Metadata; if (reader == null || reader.IsAssembly) continue; @@ -694,7 +712,7 @@ namespace ICSharpCode.ILSpyX /// public IDebugInfoProvider? GetDebugInfoOrNull() { - if (GetPEFileOrNull() == null) + if (GetMetadataFileOrNull() == null) return null; return debugInfoProvider; } diff --git a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs index d35c6c752..0f07f6c10 100644 --- a/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs +++ b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs @@ -27,27 +27,27 @@ namespace ICSharpCode.ILSpyX return Mono.Cecil.ModuleDefinition.ReadModule(new UnmanagedMemoryStream(image.Pointer, image.Length)); } - public static IAssemblyResolver GetAssemblyResolver(this PEFile file, bool loadOnDemand = true) + public static IAssemblyResolver GetAssemblyResolver(this MetadataFile file, bool loadOnDemand = true) { return GetLoadedAssembly(file).GetAssemblyResolver(loadOnDemand); } - internal static IAssemblyResolver GetAssemblyResolver(this PEFile file, AssemblyListSnapshot snapshot, bool loadOnDemand = true) + internal static IAssemblyResolver GetAssemblyResolver(this MetadataFile file, AssemblyListSnapshot snapshot, bool loadOnDemand = true) { return GetLoadedAssembly(file).GetAssemblyResolver(snapshot, loadOnDemand); } - public static IDebugInfoProvider? GetDebugInfoOrNull(this PEFile file) + public static IDebugInfoProvider? GetDebugInfoOrNull(this MetadataFile file) { return GetLoadedAssembly(file).GetDebugInfoOrNull(); } - public static ICompilation? GetTypeSystemOrNull(this PEFile file) + public static ICompilation? GetTypeSystemOrNull(this MetadataFile file) { return GetLoadedAssembly(file).GetTypeSystemOrNull(); } - public static ICompilation? GetTypeSystemWithDecompilerSettingsOrNull(this PEFile file, DecompilerSettings settings) + public static ICompilation? GetTypeSystemWithDecompilerSettingsOrNull(this MetadataFile file, DecompilerSettings settings) { return GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(settings)); } diff --git a/ICSharpCode.ILSpyX/LoadedPackage.cs b/ICSharpCode.ILSpyX/LoadedPackage.cs index 1f8e9be36..f75b9f282 100644 --- a/ICSharpCode.ILSpyX/LoadedPackage.cs +++ b/ICSharpCode.ILSpyX/LoadedPackage.cs @@ -273,52 +273,52 @@ namespace ICSharpCode.ILSpyX public List Folders { get; } = new List(); public List Entries { get; } = new List(); - public PEFile? Resolve(IAssemblyReference reference) + public MetadataFile? Resolve(IAssemblyReference reference) { var asm = ResolveFileName(reference.Name + ".dll"); if (asm != null) { - return asm.GetPEFileOrNull(); + return asm.GetMetadataFileOrNull(); } return parent?.Resolve(reference); } - public Task ResolveAsync(IAssemblyReference reference) + public Task ResolveAsync(IAssemblyReference reference) { var asm = ResolveFileName(reference.Name + ".dll"); if (asm != null) { - return asm.GetPEFileOrNullAsync(); + return asm.GetMetadataFileOrNullAsync(); } if (parent != null) { return parent.ResolveAsync(reference); } - return Task.FromResult(null); + return Task.FromResult(null); } - public PEFile? ResolveModule(PEFile mainModule, string moduleName) + public MetadataFile? ResolveModule(MetadataFile mainModule, string moduleName) { var asm = ResolveFileName(moduleName + ".dll"); if (asm != null) { - return asm.GetPEFileOrNull(); + return asm.GetMetadataFileOrNull(); } return parent?.ResolveModule(mainModule, moduleName); } - public Task ResolveModuleAsync(PEFile mainModule, string moduleName) + public Task ResolveModuleAsync(MetadataFile mainModule, string moduleName) { var asm = ResolveFileName(moduleName + ".dll"); if (asm != null) { - return asm.GetPEFileOrNullAsync(); + return asm.GetMetadataFileOrNullAsync(); } if (parent != null) { return parent.ResolveModuleAsync(mainModule, moduleName); } - return Task.FromResult(null); + return Task.FromResult(null); } readonly Dictionary assemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs index 32583ed62..8ebdba9d1 100644 --- a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs @@ -26,6 +26,8 @@ using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; +using static ICSharpCode.Decompiler.Metadata.MetadataFile; + #nullable enable namespace ICSharpCode.ILSpyX.PdbProvider @@ -240,7 +242,8 @@ namespace ICSharpCode.ILSpyX.PdbProvider public MetadataFile ToMetadataFile() { - return new MetadataFile(SourceFileName, provider, options, 0, IsEmbedded); + var kind = IsEmbedded || Path.GetExtension(SourceFileName).Equals(".pdb", StringComparison.OrdinalIgnoreCase) ? MetadataFileKind.ProgramDebugDatabase : MetadataFileKind.Metadata; + return new MetadataFile(kind, SourceFileName, provider, options, 0, IsEmbedded); } } } diff --git a/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs index 803c5f952..933ef3eba 100644 --- a/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AbstractEntitySearchStrategy.cs @@ -67,8 +67,8 @@ namespace ICSharpCode.ILSpyX.Search { if (searchRequest.InAssembly != null) { - if (entity.ParentModule?.PEFile == null || - !(Path.GetFileName(entity.ParentModule.PEFile.FileName).Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase) + if (entity.ParentModule?.MetadataFile == null || + !(Path.GetFileName(entity.ParentModule.MetadataFile.FileName).Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase) || entity.ParentModule.FullAssemblyName.Contains(searchRequest.InAssembly, StringComparison.OrdinalIgnoreCase))) { return false; diff --git a/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs index 0607a71e5..61de7b714 100644 --- a/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.ILSpyX.Search this.omitGenerics = request.OmitGenerics; } - public abstract void Search(PEFile module, CancellationToken cancellationToken); + public abstract void Search(MetadataFile module, CancellationToken cancellationToken); protected virtual bool IsMatch(string name) { diff --git a/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs b/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs index 3d0b1fb87..c164f4374 100644 --- a/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/AssemblySearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.IO; using System.Threading; @@ -35,7 +34,7 @@ namespace ICSharpCode.ILSpyX.Search this.searchKind = searchKind; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -61,7 +60,7 @@ namespace ICSharpCode.ILSpyX.Search OnFoundResult(module); } - string? GetNameToMatch(PEFile module, AssemblySearchKind kind) + string? GetNameToMatch(MetadataFile module, AssemblySearchKind kind) { switch (kind) { @@ -98,7 +97,7 @@ namespace ICSharpCode.ILSpyX.Search return null; } - void OnFoundResult(PEFile module) + void OnFoundResult(MetadataFile module) { OnFoundResult(searchRequest.SearchResultFactory.Create(module)); } diff --git a/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs index dfb83fc69..f0c0c20f8 100644 --- a/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/LiteralSearchStrategy.cs @@ -28,8 +28,6 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpyX.Abstractions; -using static System.Reflection.Metadata.PEReaderExtensions; - using ILOpCode = System.Reflection.Metadata.ILOpCode; namespace ICSharpCode.ILSpyX.Search @@ -78,7 +76,7 @@ namespace ICSharpCode.ILSpyX.Search // Note: if searchTermLiteralType remains TypeCode.Empty, we'll do a substring search via base.IsMatch } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; @@ -143,9 +141,9 @@ namespace ICSharpCode.ILSpyX.Search } } - bool MethodIsLiteralMatch(PEFile module, MethodDefinition methodDefinition) + bool MethodIsLiteralMatch(MetadataFile module, MethodDefinition methodDefinition) { - var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); + var blob = module.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); if (searchTermLiteralType == TypeCode.Int64) { Debug.Assert(searchTermLiteralValue != null); diff --git a/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs index 3af2e86f8..4d28fa27e 100644 --- a/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/MemberSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Threading; @@ -36,7 +35,7 @@ namespace ICSharpCode.ILSpyX.Search this.searchKind = searchKind; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; diff --git a/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs index b9a4a86eb..f1f48480d 100644 --- a/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/MetadataTokenSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Globalization; using System.Reflection.Metadata; @@ -44,7 +43,7 @@ namespace ICSharpCode.ILSpyX.Search } } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (searchTermToken.IsNil) diff --git a/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs index b9090b34d..030caa947 100644 --- a/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/NamespaceSearchStrategy.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.ILSpyX.Search { } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var typeSystem = module.GetTypeSystemWithDecompilerSettingsOrNull(searchRequest.DecompilerSettings); @@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpyX.Search Search(module, root); } - private void Search(PEFile module, INamespace ns) + private void Search(MetadataFile module, INamespace ns) { if (ns.Types.Any()) { @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpyX.Search Search(module, child); } - void OnFoundResult(PEFile module, INamespace ns) + void OnFoundResult(MetadataFile module, INamespace ns) { OnFoundResult(searchRequest.SearchResultFactory.Create(module, ns)); } diff --git a/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs b/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs index 46c4558b8..a0419f50f 100644 --- a/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs +++ b/ICSharpCode.ILSpyX/Search/ResourceSearchStrategy.cs @@ -15,7 +15,6 @@ // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Concurrent; using System.Reflection; using System.Threading; @@ -50,7 +49,7 @@ namespace ICSharpCode.ILSpyX.Search return true; } - public override void Search(PEFile module, CancellationToken cancellationToken) + public override void Search(MetadataFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var resourcesNode = treeNodeFactory.CreateResourcesList(module); @@ -59,7 +58,7 @@ namespace ICSharpCode.ILSpyX.Search Search(module, resource, resourcesNode, treeNodeFactory.Create(resource), cancellationToken); } - void Search(PEFile module, Resource resource, ITreeNode parent, ITreeNode node, CancellationToken cancellationToken) + void Search(MetadataFile module, Resource resource, ITreeNode parent, ITreeNode node, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -81,7 +80,7 @@ namespace ICSharpCode.ILSpyX.Search Search(module, resource, node, child, cancellationToken); } - void OnFoundResult(PEFile module, Resource resource, ITreeNode node, ITreeNode parent) + void OnFoundResult(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent) { OnFoundResult(searchRequest.SearchResultFactory.Create(module, resource, node, parent)); } diff --git a/ICSharpCode.ILSpyX/Search/SearchResult.cs b/ICSharpCode.ILSpyX/Search/SearchResult.cs index abe18ae0d..98e856010 100644 --- a/ICSharpCode.ILSpyX/Search/SearchResult.cs +++ b/ICSharpCode.ILSpyX/Search/SearchResult.cs @@ -28,9 +28,9 @@ namespace ICSharpCode.ILSpyX.Search public interface ISearchResultFactory { MemberSearchResult Create(IEntity entity); - ResourceSearchResult Create(PEFile module, Resource resource, ITreeNode node, ITreeNode parent); - AssemblySearchResult Create(PEFile module); - NamespaceSearchResult Create(PEFile module, INamespace @namespace); + ResourceSearchResult Create(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent); + AssemblySearchResult Create(MetadataFile module); + NamespaceSearchResult Create(MetadataFile module, INamespace @namespace); } public class SearchResult @@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpyX.Search public class AssemblySearchResult : SearchResult { #nullable disable - public PEFile Module { get; set; } + public MetadataFile Module { get; set; } public override object Reference => Module; #nullable enable } diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index 47470d32a..788b32ce1 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -66,7 +66,7 @@ namespace ILSpy.BamlDecompiler { var asm = this.Ancestors().OfType().First().LoadedAssembly; using var data = OpenStream(); - BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetPEFileOrNull(), asm.GetAssemblyResolver()); + BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetMetadataFileOrNull(), asm.GetAssemblyResolver()); var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings()); decompiler.CancellationToken = cancellationToken; var result = decompiler.Decompile(data); diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs index f6af42c98..32f71afa9 100644 --- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -51,7 +51,7 @@ namespace ILSpy.BamlDecompiler public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, ResourceFileHandlerContext context) { - BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetPEFileOrNull(), assembly.GetAssemblyResolver()); + BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetMetadataFileOrNull(), assembly.GetAssemblyResolver()); var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings() { ThrowOnAssemblyResolveErrors = context.DecompilationOptions.DecompilerSettings.ThrowOnAssemblyResolveErrors }); diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 95b0f3c76..cadd1217b 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -30,7 +30,6 @@ using System.Runtime.CompilerServices; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; @@ -98,7 +97,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun [Export(typeof(Language))] internal class ReadyToRunLanguage : Language { - private static readonly ConditionalWeakTable readyToRunReaders = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable readyToRunReaders = new ConditionalWeakTable(); public override string Name => "ReadyToRun"; @@ -113,7 +112,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { - PEFile module = assembly.GetPEFileAsync().GetAwaiter().GetResult(); + PEFile module = assembly.GetMetadataFileAsync().GetAwaiter().GetResult() as PEFile; ReadyToRunReaderCacheEntry cacheEntry = GetReader(assembly, module); if (cacheEntry.readyToRunReader == null) { @@ -136,7 +135,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - PEFile module = method.ParentModule.PEFile; + PEFile module = method.ParentModule.MetadataFile as PEFile; ReadyToRunReaderCacheEntry cacheEntry = GetReader(module.GetLoadedAssembly(), module); if (cacheEntry.readyToRunReader == null) { @@ -196,7 +195,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun if (cacheEntry.compositeReadyToRunReader == null) { disassemblingReader = reader; - file = method.ParentModule.PEFile; + file = method.ParentModule.MetadataFile as PEFile; } else { @@ -220,33 +219,41 @@ namespace ICSharpCode.ILSpy.ReadyToRun return Languages.ILLanguage.GetRichTextTooltip(entity); } - private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, PEFile module) + private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, MetadataFile file) { ReadyToRunReaderCacheEntry result; lock (readyToRunReaders) { - if (!readyToRunReaders.TryGetValue(module, out result)) + if (!readyToRunReaders.TryGetValue(file, out result)) { result = new ReadyToRunReaderCacheEntry(); try { - result.readyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), new StandaloneAssemblyMetadata(module.Reader), module.Reader, module.FileName); - if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) + if (file is not PEFile module) { - result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; result.readyToRunReader = null; + result.failureReason = "File is not a valid PE file."; } - else if (result.readyToRunReader.OwnerCompositeExecutable != null) + else { - string compositePath = Path.Combine(Path.GetDirectoryName(module.FileName), result.readyToRunReader.OwnerCompositeExecutable); - result.compositeReadyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), compositePath); + result.readyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), new StandaloneAssemblyMetadata(module.Reader), module.Reader, module.FileName); + if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) + { + result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; + result.readyToRunReader = null; + } + else if (result.readyToRunReader.OwnerCompositeExecutable != null) + { + string compositePath = Path.Combine(Path.GetDirectoryName(module.FileName), result.readyToRunReader.OwnerCompositeExecutable); + result.compositeReadyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), compositePath); + } } } catch (BadImageFormatException e) { result.failureReason = e.Message; } - readyToRunReaders.Add(module, result); + readyToRunReaders.Add(file, result); } } return result; @@ -270,18 +277,18 @@ namespace ICSharpCode.ILSpy.ReadyToRun public IAssemblyMetadata FindAssembly(string simpleName, string parentFile) { - return GetAssemblyMetadata(assemblyResolver.ResolveModule(loadedAssembly.GetPEFileOrNull(), simpleName + ".dll")); + return GetAssemblyMetadata(assemblyResolver.ResolveModule(loadedAssembly.GetMetadataFileOrNull(), simpleName + ".dll")); } - private IAssemblyMetadata GetAssemblyMetadata(PEFile module) + private IAssemblyMetadata GetAssemblyMetadata(MetadataFile module) { - if (module.Reader == null) + if (module is not PEFile peFile || peFile.Reader == null) { return null; } else { - return new IlSpyAssemblyMetadata(module); + return new IlSpyAssemblyMetadata(peFile); } } } diff --git a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs index b89a02d48..79a5eb558 100644 --- a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs @@ -16,16 +16,9 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; using ICSharpCode.ILSpyX; @@ -47,7 +40,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers { assemblyList = new AssemblyList(); testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); - testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetPEFileOrNull(), testAssembly.GetAssemblyResolver()); + testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetMetadataFileOrNull(), testAssembly.GetAssemblyResolver()); language = new CSharpLanguage(); } diff --git a/ILSpy/Analyzers/AnalyzerContext.cs b/ILSpy/Analyzers/AnalyzerContext.cs index 2e3657103..6c7510554 100644 --- a/ILSpy/Analyzers/AnalyzerContext.cs +++ b/ILSpy/Analyzers/AnalyzerContext.cs @@ -55,11 +55,11 @@ namespace ICSharpCode.ILSpy.Analyzers { if (!method.HasBody || method.MetadataToken.IsNil) return null; - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); try { - return module.Reader.GetMethodBody(md.RelativeVirtualAddress); + return module.GetMethodBody(md.RelativeVirtualAddress); } catch (BadImageFormatException) { @@ -72,9 +72,9 @@ namespace ICSharpCode.ILSpy.Analyzers return new AnalyzerScope(AssemblyList, entity); } - readonly ConcurrentDictionary typeSystemCache = new ConcurrentDictionary(); + readonly ConcurrentDictionary typeSystemCache = new(); - public DecompilerTypeSystem GetOrCreateTypeSystem(PEFile module) + public DecompilerTypeSystem GetOrCreateTypeSystem(MetadataFile module) { return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); } diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index 930cb382c..38d94c1c5 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -41,14 +41,14 @@ namespace ICSharpCode.ILSpy.Analyzers MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); return; } - MainWindow.Instance.JumpToReference(new EntityReference(this.Member.ParentModule.PEFile, this.Member.MetadataToken)); + MainWindow.Instance.JumpToReference(new EntityReference(this.Member.ParentModule.MetadataFile, this.Member.MetadataToken)); } public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { foreach (LoadedAssembly asm in removedAssemblies) { - if (this.Member.ParentModule.PEFile == asm.GetPEFileOrNull()) + if (this.Member.ParentModule.MetadataFile == asm.GetMetadataFileOrNull()) return false; // remove this node } this.Children.RemoveAll( diff --git a/ILSpy/Analyzers/AnalyzerHelpers.cs b/ILSpy/Analyzers/AnalyzerHelpers.cs index 9126dd615..b7070dedb 100644 --- a/ILSpy/Analyzers/AnalyzerHelpers.cs +++ b/ILSpy/Analyzers/AnalyzerHelpers.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.Analyzers { internal static class AnalyzerHelpers { - public static bool IsPossibleReferenceTo(EntityHandle member, PEFile module, IMethod analyzedMethod) + public static bool IsPossibleReferenceTo(EntityHandle member, MetadataFile module, IMethod analyzedMethod) { if (member.IsNil) return false; @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Analyzers { case HandleKind.MethodDefinition: return member == analyzedMethod.MetadataToken - && module == analyzedMethod.ParentModule.PEFile; + && module == analyzedMethod.ParentModule.MetadataFile; case HandleKind.MemberReference: var mr = metadata.GetMemberReference((MemberReferenceHandle)member); if (mr.GetKind() != MemberReferenceKind.Method) @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.Analyzers public static ISymbol GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute) { - var metadata = ts.MainModule.PEFile.Metadata; + var metadata = ts.MainModule.MetadataFile.Metadata; switch (customAttribute.Parent.Kind) { case HandleKind.MethodDefinition: diff --git a/ILSpy/Analyzers/AnalyzerScope.cs b/ILSpy/Analyzers/AnalyzerScope.cs index 881fc6e98..1116e408c 100644 --- a/ILSpy/Analyzers/AnalyzerScope.cs +++ b/ILSpy/Analyzers/AnalyzerScope.cs @@ -58,25 +58,25 @@ namespace ICSharpCode.ILSpy.Analyzers IsLocal = effectiveAccessibility.LessThanOrEqual(Accessibility.Private); } - public IEnumerable GetModulesInScope(CancellationToken ct) + public IEnumerable GetModulesInScope(CancellationToken ct) { if (IsLocal) - return new[] { TypeScope.ParentModule.PEFile }; + return new[] { TypeScope.ParentModule.MetadataFile }; if (effectiveAccessibility.LessThanOrEqual(Accessibility.Internal)) return GetModuleAndAnyFriends(TypeScope, ct); - return GetReferencingModules(TypeScope.ParentModule.PEFile, ct); + return GetReferencingModules(TypeScope.ParentModule.MetadataFile, ct); } - public IEnumerable GetAllModules() + public IEnumerable GetAllModules() { return assemblyListSnapshot.GetAllAssembliesAsync().GetAwaiter().GetResult() - .Select(asm => asm.GetPEFileOrNull()) + .Select(asm => asm.GetMetadataFileOrNull()) .Where(x => x != null); } - public DecompilerTypeSystem ConstructTypeSystem(PEFile module) + public DecompilerTypeSystem ConstructTypeSystem(MetadataFile module) { return new DecompilerTypeSystem(module, module.GetAssemblyResolver(assemblyListSnapshot, loadOnDemand: false)); } @@ -132,7 +132,7 @@ namespace ICSharpCode.ILSpy.Analyzers } #region Find modules - IEnumerable GetReferencingModules(PEFile self, CancellationToken ct) + IEnumerable GetReferencingModules(MetadataFile self, CancellationToken ct) { yield return self; @@ -140,8 +140,8 @@ namespace ICSharpCode.ILSpy.Analyzers if (typeScope.TypeParameterCount > 0) reflectionTypeScopeName += "`" + typeScope.TypeParameterCount; - var toWalkFiles = new Stack(); - var checkedFiles = new HashSet(); + var toWalkFiles = new Stack(); + var checkedFiles = new HashSet(); toWalkFiles.Push(self); checkedFiles.Add(self); @@ -149,12 +149,12 @@ namespace ICSharpCode.ILSpy.Analyzers do { - PEFile curFile = toWalkFiles.Pop(); + MetadataFile curFile = toWalkFiles.Pop(); foreach (var assembly in assemblies) { ct.ThrowIfCancellationRequested(); bool found = false; - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null || !module.IsAssembly) continue; if (checkedFiles.Contains(module)) @@ -179,9 +179,9 @@ namespace ICSharpCode.ILSpy.Analyzers } while (toWalkFiles.Count > 0); } - IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct) + IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct) { - var self = typeScope.ParentModule.PEFile; + var self = typeScope.ParentModule.MetadataFile; yield return self; @@ -206,7 +206,7 @@ namespace ICSharpCode.ILSpy.Analyzers ct.ThrowIfCancellationRequested(); if (friendAssemblies.Contains(assembly.ShortName)) { - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null) continue; if (ModuleReferencesScopeType(module.Metadata, typeScope.Name, typeScope.Namespace)) diff --git a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs index 4e87a0f30..5afde0525 100644 --- a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs @@ -46,15 +46,15 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var @event in type.Events) { var baseMembers = InheritanceHelper.GetBaseMembers(@event, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module)) yield return @event; } } diff --git a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs index f6c41dc18..d4f8cdda6 100644 --- a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs @@ -46,9 +46,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var @event in type.Events) @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!@event.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(@event, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module)) { yield return @event; } diff --git a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs index 38228bc72..c392bc1d2 100644 --- a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs @@ -17,20 +17,15 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; -using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.ILSpy.Analyzers; using ILOpCode = System.Reflection.Metadata.ILOpCode; @@ -79,7 +74,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var scope = context.GetScopeOf((IEntity)analyzedSymbol); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { - var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); + var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -126,7 +121,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { if (method.MetadataToken.IsNil) return false; - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; foreach (var part in mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken)) { var md = module.Metadata.GetMethodDefinition(part); @@ -135,7 +130,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin MethodBodyBlock body; try { - body = module.Reader.GetMethodBody(md.RelativeVirtualAddress); + body = module.GetMethodBody(md.RelativeVirtualAddress); } catch (BadImageFormatException) { @@ -188,7 +183,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin continue; if (field.MetadataToken == analyzedField.MetadataToken - && field.ParentModule.PEFile == analyzedField.ParentModule.PEFile) + && field.ParentModule.MetadataFile == analyzedField.ParentModule.MetadataFile) return true; } diff --git a/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs b/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs index 1431e3cee..45c1e73ee 100644 --- a/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs +++ b/ILSpy/Analyzers/Builtin/FindTypeInAttributeDecoder.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin class FindTypeInAttributeDecoder : ICustomAttributeTypeProvider { - readonly PEFile declaringModule; + readonly MetadataFile declaringModule; readonly MetadataModule currentModule; readonly TypeDefinitionHandle handle; readonly PrimitiveTypeCode primitiveType; @@ -65,7 +65,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin public FindTypeInAttributeDecoder(MetadataModule currentModule, ITypeDefinition type) { this.currentModule = currentModule; - this.declaringModule = type.ParentModule?.PEFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); + this.declaringModule = type.ParentModule?.MetadataFile ?? throw new InvalidOperationException("Cannot use MetadataModule without PEFile as context."); this.handle = (TypeDefinitionHandle)type.MetadataToken; this.primitiveType = type.KnownTypeCode == KnownTypeCode.None ? 0 : type.KnownTypeCode.ToPrimitiveTypeCode(); } @@ -138,7 +138,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { result = TokenSearchResult.SystemType; } - if (td.MetadataToken == this.handle && td.ParentModule?.PEFile == declaringModule) + if (td.MetadataToken == this.handle && td.ParentModule?.MetadataFile == declaringModule) { result |= TokenSearchResult.Found; } diff --git a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs index db9073e2a..4105e185c 100644 --- a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs @@ -49,15 +49,15 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var method in type.Methods) { var baseMembers = InheritanceHelper.GetBaseMembers(method, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module)) yield return method; } } diff --git a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs index 7a90f48fa..2fe6677fa 100644 --- a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs @@ -48,9 +48,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var method in type.Methods) @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!method.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(method, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module)) { yield return method; } diff --git a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs index a2b698080..290c9e5e9 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs @@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var analyzedMethod = (IMethod)analyzedSymbol; var analyzedBaseMethod = (IMethod)InheritanceHelper.GetBaseMember(analyzedMethod); var mapping = context.Language - .GetCodeMappingInfo(analyzedMethod.ParentModule.PEFile, + .GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile, analyzedMethod.DeclaringTypeDefinition.MetadataToken); var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken); @@ -64,7 +64,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { if (IsUsedInMethod(analyzedMethod, analyzedBaseMethod, method, context)) { - mapping ??= context.Language.GetCodeMappingInfo(parentModule.PEFile, type.MetadataToken); + mapping ??= context.Language.GetCodeMappingInfo(parentModule.MetadataFile, type.MetadataToken); var parent = mapping.GetParentMethod((MethodDefinitionHandle)method.MetadataToken); yield return parentModule.GetDefinition(parent); } @@ -137,9 +137,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin return false; // unexpected end of blob } var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (!AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.PEFile, analyzedMethod)) + if (!AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.MetadataFile, analyzedMethod)) { - if (analyzedBaseMethod == null || !AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.PEFile, analyzedBaseMethod)) + if (analyzedBaseMethod == null || !AnalyzerHelpers.IsPossibleReferenceTo(member, mainModule.MetadataFile, analyzedBaseMethod)) { continue; } @@ -192,7 +192,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin static bool IsSameMember(IMember analyzedMethod, IMember m) { return m.MetadataToken == analyzedMethod.MetadataToken - && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile; + && m.ParentModule.MetadataFile == analyzedMethod.ParentModule.MetadataFile; } } } diff --git a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs index c3e892419..c35593d69 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs @@ -38,10 +38,10 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin public IEnumerable Analyze(ISymbol symbol, AnalyzerContext context) { - if (symbol is IMethod method) + if (symbol is IMethod method && method.ParentModule.MetadataFile is MetadataFile corFile) { - var typeSystem = context.GetOrCreateTypeSystem(method.ParentModule.PEFile); - return context.Language.GetCodeMappingInfo(method.ParentModule.PEFile, method.MetadataToken) + var typeSystem = context.GetOrCreateTypeSystem(corFile); + return context.Language.GetCodeMappingInfo(corFile, method.MetadataToken) .GetMethodParts((MethodDefinitionHandle)method.MetadataToken) .SelectMany(h => ScanMethod(h, typeSystem)).Distinct(); } @@ -51,14 +51,14 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin IEnumerable ScanMethod(MethodDefinitionHandle handle, DecompilerTypeSystem typeSystem) { var module = typeSystem.MainModule; - var md = module.PEFile.Metadata.GetMethodDefinition(handle); + var md = module.MetadataFile.Metadata.GetMethodDefinition(handle); if (!md.HasBody()) yield break; BlobReader blob; try { - blob = module.PEFile.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); + blob = module.MetadataFile.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); } catch (BadImageFormatException) { diff --git a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs index bf806416c..b3102de19 100644 --- a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin Debug.Assert(analyzedSymbol is IMethod); var analyzedMethod = (IMethod)analyzedSymbol; var mapping = context.Language - .GetCodeMappingInfo(analyzedMethod.ParentModule.PEFile, + .GetCodeMappingInfo(analyzedMethod.ParentModule.MetadataFile, analyzedMethod.DeclaringTypeDefinition.MetadataToken); var parentMethod = mapping.GetParentMethod((MethodDefinitionHandle)analyzedMethod.MetadataToken); @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { var parentModule = (MetadataModule)type.ParentModule; - mapping = context.Language.GetCodeMappingInfo(parentModule.PEFile, type.MetadataToken); + mapping = context.Language.GetCodeMappingInfo(parentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -131,7 +131,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin case HandleKind.MethodSpecification: case HandleKind.MemberReference: var m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; - if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile) + if (m != null && m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.MetadataFile == analyzedMethod.ParentModule.MetadataFile) { return true; } diff --git a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs index 2b8cb8f84..241e26b88 100644 --- a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs @@ -46,15 +46,15 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var property in type.Properties) { var baseMembers = InheritanceHelper.GetBaseMembers(property, true); - if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) + if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.MetadataFile == module)) yield return property; } } diff --git a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs index 7ec8b5cee..475628ce5 100644 --- a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs @@ -49,9 +49,9 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var token = analyzedEntity.MetadataToken; var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken; - var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile; + var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.MetadataFile; var allTypes = type.GetAllBaseTypeDefinitions(); - if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) + if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.MetadataFile == module)) yield break; foreach (var property in type.Properties) @@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!property.IsOverride) continue; var baseMembers = InheritanceHelper.GetBaseMembers(property, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.MetadataFile == module)) { yield return property; } diff --git a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs index 2b9109638..54828654e 100644 --- a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { if (analyzedType.Kind == TypeKind.Enum && type.MetadataToken == analyzedType.MetadataToken - && type.ParentModule.PEFile == analyzedType.ParentModule.PEFile) + && type.ParentModule.MetadataFile == analyzedType.ParentModule.MetadataFile) yield break; if (!context.Language.ShowMember(type)) diff --git a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs index 4d1d5bc30..2bd75dfb7 100644 --- a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var firstParamType = method.Parameters[0].Type.GetDefinition(); if (firstParamType != null && firstParamType.MetadataToken == analyzedType.MetadataToken && - firstParamType.ParentModule.PEFile == analyzedType.ParentModule.PEFile) + firstParamType.ParentModule.MetadataFile == analyzedType.ParentModule.MetadataFile) yield return method; } } diff --git a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs index cd5b68f1f..500923bc6 100644 --- a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { - var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); + var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.MetadataFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); foreach (var method in methods) { @@ -134,7 +134,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin continue; if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken - && ctor.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile) + && ctor.ParentModule.MetadataFile == analyzedEntity.ParentModule.MetadataFile) return true; } diff --git a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs index ef7ef3fee..0f7926766 100644 --- a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs @@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin .AsParallel().AsOrdered() .SelectMany(AnalyzeModuleAndFilter); - IEnumerable AnalyzeModuleAndFilter(PEFile module) + IEnumerable AnalyzeModuleAndFilter(MetadataFile module) { return AnalyzeModule(analyzedType, scope, module) .Distinct() @@ -55,7 +55,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin } } - static IEnumerable AnalyzeModule(ITypeDefinition analyzedType, AnalyzerScope scope, PEFile module) + static IEnumerable AnalyzeModule(ITypeDefinition analyzedType, AnalyzerScope scope, MetadataFile module) { var metadata = module.Metadata; var typeSystem = scope.ConstructTypeSystem(module); @@ -241,12 +241,12 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin } } - static bool ScanMethodBody(ITypeDefinition analyzedType, PEFile module, in MethodDefinition md, FindTypeDecoder decoder) + static bool ScanMethodBody(ITypeDefinition analyzedType, MetadataFile module, in MethodDefinition md, FindTypeDecoder decoder) { if (!md.HasBody()) return false; - var methodBody = module.Reader.GetMethodBody(md.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(md.RelativeVirtualAddress); var metadata = module.Metadata; if (!methodBody.LocalSignature.IsNil) @@ -408,7 +408,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin public override IType VisitTypeDefinition(ITypeDefinition type) { Found |= TypeDefinition.MetadataToken == type.MetadataToken - && TypeDefinition.ParentModule.PEFile == type.ParentModule.PEFile; + && TypeDefinition.ParentModule.MetadataFile == type.ParentModule.MetadataFile; return base.VisitTypeDefinition(type); } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs index 5718a85bc..1879c7e04 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs @@ -54,12 +54,12 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes public override void ActivateItem(RoutedEventArgs e) { e.Handled = true; - if (analyzedModule.PEFile == null) + if (analyzedModule.MetadataFile == null) { MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); return; } - MainWindow.Instance.JumpToReference(analyzedModule.PEFile); + MainWindow.Instance.JumpToReference(analyzedModule.MetadataFile); } public override IEntity Member => null; diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index 64e8acfef..773c7cd4c 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -27,6 +27,7 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; @@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy internal static void GeneratePdbForAssembly(LoadedAssembly assembly) { - var file = assembly.GetPEFileOrNull(); + var file = assembly.GetMetadataFileOrNull() as PEFile; if (!PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file)) { MessageBox.Show(string.Format(Resources.CannotCreatePDBFile, Path.GetFileName(assembly.FileName))); diff --git a/ILSpy/Commands/IProtocolHandler.cs b/ILSpy/Commands/IProtocolHandler.cs index 251b6b5f5..53f6e7ef3 100644 --- a/ILSpy/Commands/IProtocolHandler.cs +++ b/ILSpy/Commands/IProtocolHandler.cs @@ -1,18 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Linq; +// Copyright (c) 2018 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + using System.Reflection.Metadata; -using System.Text; -using System.Threading.Tasks; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy { public interface IProtocolHandler { - ILSpyTreeNode Resolve(string protocol, PEFile module, Handle handle, out bool newTabPage); + ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage); } } diff --git a/ILSpy/EntityReference.cs b/ILSpy/EntityReference.cs index d74448aa5..d5cfff404 100644 --- a/ILSpy/EntityReference.cs +++ b/ILSpy/EntityReference.cs @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy public MetadataFile? ResolveAssembly(AssemblyList context) { - return peFile ?? context.FindAssembly(Module)?.GetPEFileOrNull(); + return peFile ?? context.FindAssembly(Module)?.GetMetadataFileOrNull(); } } } diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index 5b48f10bc..49dfde0fd 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -59,6 +59,7 @@ namespace ICSharpCode.ILSpy public static readonly ImageSource ReferenceFolder = Load("ReferenceFolder"); public static readonly ImageSource NuGet = Load(null, "Images/NuGet.png"); public static readonly ImageSource MetadataFile = Load("MetadataFile"); + public static readonly ImageSource WebAssemblyFile = Load("WebAssembly"); public static readonly ImageSource ProgramDebugDatabase = Load("ProgramDebugDatabase"); public static readonly ImageSource Metadata = Load("Metadata"); diff --git a/ILSpy/Images/WebAssembly.svg b/ILSpy/Images/WebAssembly.svg new file mode 100644 index 000000000..f2d67d77a --- /dev/null +++ b/ILSpy/Images/WebAssembly.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ILSpy/Images/WebAssembly.xaml b/ILSpy/Images/WebAssembly.xaml new file mode 100644 index 000000000..302c83825 --- /dev/null +++ b/ILSpy/Images/WebAssembly.xaml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index b54a161ba..6ad3bb54e 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -23,8 +23,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection.Metadata; -using System.Threading; -using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Highlighting; @@ -64,7 +62,7 @@ namespace ICSharpCode.ILSpy }; } - static CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options) + static CSharpDecompiler CreateDecompiler(MetadataFile module, DecompilationOptions options) { CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(), options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; @@ -93,7 +91,7 @@ namespace ICSharpCode.ILSpy this.options = options; } - public override void Disassemble(PEFile module, MethodDefinitionHandle handle) + public override void Disassemble(MetadataFile module, MethodDefinitionHandle handle) { try { @@ -113,7 +111,7 @@ namespace ICSharpCode.ILSpy } } - protected override void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) + protected override void WriteInstruction(ITextOutput output, MetadataFile metadata, MethodDefinitionHandle methodHandle, ref BlobReader blob, int methodRva) { int index = sequencePoints.BinarySearch(blob.Offset, seq => seq.Offset); if (index >= 0) diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index fbf2a1ce0..d83a412ba 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -120,7 +120,7 @@ namespace ICSharpCode.ILSpy } } - CSharpDecompiler CreateDecompiler(PEFile module, DecompilationOptions options) + CSharpDecompiler CreateDecompiler(MetadataFile module, DecompilationOptions options) { CSharpDecompiler decompiler = new CSharpDecompiler(module, module.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences), options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; @@ -148,7 +148,7 @@ namespace ICSharpCode.ILSpy public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - PEFile assembly = method.ParentModule.PEFile; + MetadataFile assembly = method.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -230,7 +230,7 @@ namespace ICSharpCode.ILSpy public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options) { - PEFile assembly = property.ParentModule.PEFile; + MetadataFile assembly = property.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -241,7 +241,7 @@ namespace ICSharpCode.ILSpy public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options) { - PEFile assembly = field.ParentModule.PEFile; + MetadataFile assembly = field.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -310,7 +310,7 @@ namespace ICSharpCode.ILSpy public override void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options) { - PEFile assembly = @event.ParentModule.PEFile; + MetadataFile assembly = @event.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -321,7 +321,7 @@ namespace ICSharpCode.ILSpy public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options) { - PEFile assembly = type.ParentModule.PEFile; + MetadataFile assembly = type.ParentModule.MetadataFile; CSharpDecompiler decompiler = CreateDecompiler(assembly, options); AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); @@ -330,9 +330,9 @@ namespace ICSharpCode.ILSpy WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type.MetadataToken), decompiler.TypeSystem); } - void AddReferenceWarningMessage(PEFile module, ITextOutput output) + void AddReferenceWarningMessage(MetadataFile module, ITextOutput output) { - var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetPEFileOrNull() == module); + var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetMetadataFileOrNull() == module); if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.HasErrors) return; string line1 = Properties.Resources.WarningSomeAssemblyReference; @@ -344,7 +344,7 @@ namespace ICSharpCode.ILSpy }); } - void AddReferenceAssemblyWarningMessage(PEFile module, ITextOutput output) + void AddReferenceAssemblyWarningMessage(MetadataFile module, ITextOutput output) { var metadata = module.Metadata; if (!metadata.GetCustomAttributes(Handle.AssemblyDefinition).HasKnownAttribute(metadata, KnownAttribute.ReferenceAssembly)) @@ -353,7 +353,7 @@ namespace ICSharpCode.ILSpy AddWarningMessage(module, output, line1); } - void AddWarningMessage(PEFile module, ITextOutput output, string line1, string line2 = null, + void AddWarningMessage(MetadataFile module, ITextOutput output, string line1, string line2 = null, string buttonText = null, System.Windows.Media.ImageSource buttonImage = null, RoutedEventHandler buttonClickHandler = null) { if (output is ISmartTextOutput fancyOutput) @@ -393,7 +393,7 @@ namespace ICSharpCode.ILSpy public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { - var module = assembly.GetPEFileOrNull(); + var module = assembly.GetMetadataFileOrNull(); if (module == null) { return null; @@ -426,39 +426,50 @@ namespace ICSharpCode.ILSpy output.WriteLine(); } var metadata = module.Metadata; - var corHeader = module.Reader.PEHeaders.CorHeader; - var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); - if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) + var corHeader = module.CorHeader; + if (module is PEFile peFile && corHeader != null) { - var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); - if (entrypoint != null) + var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); + if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) { - output.Write("// Entry point: "); - output.WriteReference(entrypoint, EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name)); - output.WriteLine(); + var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); + if (entrypoint != null) + { + output.Write("// Entry point: "); + output.WriteReference(entrypoint, EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name)); + output.WriteLine(); + } + } + output.WriteLine("// Architecture: " + GetPlatformDisplayName(peFile)); + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) + { + output.WriteLine("// This assembly contains unmanaged code."); + } + string runtimeName = GetRuntimeDisplayName(module); + if (runtimeName != null) + { + output.WriteLine("// Runtime: " + runtimeName); + } + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) + { + output.WriteLine("// This assembly is signed with a strong name key."); + } + if (peFile.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible)) + { + output.WriteLine("// This assembly was compiled using the /deterministic option."); + } + if (module.Metadata.MetadataKind != MetadataKind.Ecma335) + { + output.WriteLine("// This assembly was loaded with Windows Runtime projections applied."); } } - output.WriteLine("// Architecture: " + GetPlatformDisplayName(module)); - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) - { - output.WriteLine("// This assembly contains unmanaged code."); - } - string runtimeName = GetRuntimeDisplayName(module); - if (runtimeName != null) - { - output.WriteLine("// Runtime: " + runtimeName); - } - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) - { - output.WriteLine("// This assembly is signed with a strong name key."); - } - if (module.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible)) - { - output.WriteLine("// This assembly was compiled using the /deterministic option."); - } - if (module.Metadata.MetadataKind != MetadataKind.Ecma335) + else { - output.WriteLine("// This assembly was loaded with Windows Runtime projections applied."); + string runtimeName = GetRuntimeDisplayName(module); + if (runtimeName != null) + { + output.WriteLine("// Runtime: " + runtimeName); + } } if (metadata.IsAssembly) { @@ -664,7 +675,7 @@ namespace ICSharpCode.ILSpy } } - public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) + public override string GetEntityName(MetadataFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; switch (handle.Kind) @@ -737,7 +748,7 @@ namespace ICSharpCode.ILSpy public override bool ShowMember(IEntity member) { - PEFile assembly = member.ParentModule.PEFile; + MetadataFile assembly = member.ParentModule.MetadataFile; return showAllMembers || !CSharpDecompiler.MemberIsHidden(assembly, member.MetadataToken, MainWindow.Instance.CurrentDecompilerSettings); } @@ -782,7 +793,7 @@ namespace ICSharpCode.ILSpy return new RichText(output.ToString(), writer.HighlightingModel); } - public override CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public override CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { return CSharpDecompiler.GetCodeMappingInfo(module, member); } diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index 918558451..b0f467b4b 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -18,8 +18,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; @@ -31,8 +29,6 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; -using static System.Reflection.Metadata.PEReaderExtensions; - using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy @@ -77,7 +73,7 @@ namespace ICSharpCode.ILSpy { base.DecompileMethod(method, output, options); new ReflectionDisassembler(output, options.CancellationToken) - .DisassembleMethodHeader(method.ParentModule.PEFile, (SRM.MethodDefinitionHandle)method.MetadataToken); + .DisassembleMethodHeader(method.ParentModule.MetadataFile, (SRM.MethodDefinitionHandle)method.MetadataToken); output.WriteLine(); output.WriteLine(); } @@ -89,13 +85,13 @@ namespace ICSharpCode.ILSpy public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { base.DecompileMethod(method, output, options); - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; var methodDef = module.Metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken); if (!methodDef.HasBody()) return; var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); ILReader reader = new ILReader(typeSystem.MainModule); - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); reader.WriteTypedIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, output, cancellationToken: options.CancellationToken); } } @@ -112,7 +108,7 @@ namespace ICSharpCode.ILSpy public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { base.DecompileMethod(method, output, options); - var module = method.ParentModule.PEFile; + var module = method.ParentModule.MetadataFile; var metadata = module.Metadata; var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)method.MetadataToken); if (!methodDef.HasBody()) @@ -121,7 +117,7 @@ namespace ICSharpCode.ILSpy var typeSystem = new DecompilerTypeSystem(module, assemblyResolver); var reader = new ILReader(typeSystem.MainModule); reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols; - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); ILFunction il = reader.ReadIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, kind: ILFunctionKind.TopLevelFunction, cancellationToken: options.CancellationToken); var decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings) { CancellationToken = options.CancellationToken }; ILTransformContext context = decompiler.CreateILTransformContext(il); diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs index 711778581..95c881bb4 100644 --- a/ILSpy/Languages/ILLanguage.cs +++ b/ILSpy/Languages/ILLanguage.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = method.ParentModule.PEFile; + MetadataFile module = method.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleMethod(module, (MethodDefinitionHandle)method.MetadataToken); @@ -80,7 +80,7 @@ namespace ICSharpCode.ILSpy public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = field.ParentModule.PEFile; + MetadataFile module = field.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleField(module, (FieldDefinitionHandle)field.MetadataToken); @@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = property.ParentModule.PEFile; + MetadataFile module = property.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleProperty(module, (PropertyDefinitionHandle)property.MetadataToken); @@ -115,7 +115,7 @@ namespace ICSharpCode.ILSpy public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = ev.ParentModule.PEFile; + MetadataFile module = ev.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleEvent(module, (EventDefinitionHandle)ev.MetadataToken); @@ -146,7 +146,7 @@ namespace ICSharpCode.ILSpy public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = type.ParentModule.PEFile; + MetadataFile module = type.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleType(module, (TypeDefinitionHandle)type.MetadataToken); @@ -155,7 +155,7 @@ namespace ICSharpCode.ILSpy public override void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); - PEFile module = types.FirstOrDefault()?.ParentModule.PEFile; + MetadataFile module = types.FirstOrDefault()?.ParentModule.MetadataFile; dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken)); @@ -165,15 +165,16 @@ namespace ICSharpCode.ILSpy { output.WriteLine("// " + assembly.FileName); output.WriteLine(); - var module = assembly.GetPEFileAsync().GetAwaiter().GetResult(); - var metadata = module.Metadata; - var dis = CreateDisassembler(output, options); + var module = assembly.GetMetadataFileOrNull(); if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { throw new NotSupportedException($"Language '{Name}' does not support exporting assemblies as projects!"); } + var metadata = module.Metadata; + var dis = CreateDisassembler(output, options); + // don't automatically load additional assemblies when an assembly node is selected in the tree view dis.AssemblyResolver = module.GetAssemblyResolver(loadOnDemand: options.FullDecompilation); dis.DebugInfo = module.GetDebugInfoOrNull(); @@ -196,7 +197,7 @@ namespace ICSharpCode.ILSpy { var output = new AvalonEditTextOutput() { IgnoreNewLineAndIndent = true }; var disasm = CreateDisassembler(output, MainWindow.Instance.CreateDecompilationOptions()); - PEFile module = entity.ParentModule?.PEFile; + MetadataFile module = entity.ParentModule?.MetadataFile; if (module == null) { return null; diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs index b47acbaad..26410fe24 100644 --- a/ILSpy/Languages/Language.cs +++ b/ILSpy/Languages/Language.cs @@ -110,7 +110,7 @@ namespace ICSharpCode.ILSpy public virtual ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, assembly.FileName); - var asm = assembly.GetPEFileOrNull(); + var asm = assembly.GetMetadataFileOrNull(); if (asm == null) return null; if (options.FullDecompilation && options.SaveAsProjectDirectory != null) @@ -442,7 +442,7 @@ namespace ICSharpCode.ILSpy string entityName; if (entity is ITypeDefinition t && !t.MetadataToken.IsNil) { - MetadataReader metadata = t.ParentModule.PEFile.Metadata; + MetadataReader metadata = t.ParentModule.MetadataFile.Metadata; var typeDef = metadata.GetTypeDefinition((TypeDefinitionHandle)t.MetadataToken); entityName = EscapeName(metadata.GetString(typeDef.Name)); } @@ -478,7 +478,7 @@ namespace ICSharpCode.ILSpy /// /// This should produce a string representation of the entity for search to match search strings against. /// - public virtual string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) + public virtual string GetEntityName(MetadataFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; switch (handle.Kind) @@ -522,7 +522,7 @@ namespace ICSharpCode.ILSpy } } - public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) + public virtual CodeMappingInfo GetCodeMappingInfo(MetadataFile module, EntityHandle member) { var declaringType = (TypeDefinitionHandle)member.GetDeclaringType(module.Metadata); @@ -561,7 +561,7 @@ namespace ICSharpCode.ILSpy } } - public static string GetRuntimeDisplayName(PEFile module) + public static string GetRuntimeDisplayName(MetadataFile module) { return module.Metadata.MetadataVersion; } diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 3b8a62cab..4f2180953 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -710,7 +710,7 @@ namespace ICSharpCode.ILSpy { // FindNamespaceNode() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. - await asm.GetPEFileAsync().Catch(ex => { }); + await asm.GetMetadataFileAsync().Catch(ex => { }); NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName); if (nsNode != null) { @@ -736,7 +736,7 @@ namespace ICSharpCode.ILSpy // Make sure we wait for assemblies being loaded... // BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal await Dispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal); - if (mr != null && mr.ParentModule.PEFile != null) + if (mr != null && mr.ParentModule.MetadataFile != null) { found = true; if (AssemblyTreeView.SelectedItem == initialSelection) @@ -773,7 +773,7 @@ namespace ICSharpCode.ILSpy { // FindNodeByPath() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. - await asm.GetPEFileAsync().Catch(ex => { }); + await asm.GetMetadataFileAsync().Catch(ex => { }); } } node = FindNodeByPath(activeTreeViewPath, true); @@ -810,12 +810,12 @@ namespace ICSharpCode.ILSpy } foreach (LoadedAssembly asm in relevantAssemblies.ToList()) { - var module = asm.GetPEFileOrNull(); + var module = asm.GetMetadataFileOrNull(); if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) { ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType ? new DecompilerTypeSystem(module, module.GetAssemblyResolver()) - : new SimpleCompilation(module, MinimalCorlib.Instance); + : new SimpleCompilation((PEFile)module, MinimalCorlib.Instance); return memberRef == null ? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition : (IEntity)memberRef.Resolve(new SimpleTypeResolveContext(compilation)); @@ -824,14 +824,8 @@ namespace ICSharpCode.ILSpy return null; } - static bool CanResolveTypeInPEFile(PEFile module, ITypeReference typeRef, out EntityHandle typeHandle) + static bool CanResolveTypeInPEFile(MetadataFile module, ITypeReference typeRef, out EntityHandle typeHandle) { - if (module == null) - { - typeHandle = default; - return false; - } - // We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition. if (module.IsReferenceAssembly()) { @@ -1259,7 +1253,7 @@ namespace ICSharpCode.ILSpy { case LoadedAssembly lasm: return assemblyListTreeNode.FindAssemblyNode(lasm); - case PEFile asm: + case MetadataFile asm: return assemblyListTreeNode.FindAssemblyNode(asm); case Resource res: return assemblyListTreeNode.FindResourceNode(res); @@ -1314,7 +1308,7 @@ namespace ICSharpCode.ILSpy break; case EntityReference unresolvedEntity: string protocol = unresolvedEntity.Protocol ?? "decompile"; - PEFile file = unresolvedEntity.ResolveAssembly(assemblyList) as PEFile; + var file = unresolvedEntity.ResolveAssembly(assemblyList); if (file == null) { break; @@ -1385,7 +1379,7 @@ namespace ICSharpCode.ILSpy { e.Handled = true; OpenFileDialog dlg = new OpenFileDialog(); - dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*"; + dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*"; dlg.Multiselect = true; dlg.RestoreDirectory = true; if (dlg.ShowDialog() == true) diff --git a/ILSpy/Metadata/DebugDirectoryTreeNode.cs b/ILSpy/Metadata/DebugDirectoryTreeNode.cs index d5ee10435..3acc16475 100644 --- a/ILSpy/Metadata/DebugDirectoryTreeNode.cs +++ b/ILSpy/Metadata/DebugDirectoryTreeNode.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.Metadata case DebugDirectoryEntryType.EmbeddedPortablePdb: var embeddedPortablePdbProvider = module.Reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry); - var embeddedPortablePdbMetadataFile = new MetadataFile(module.FileName, embeddedPortablePdbProvider, isEmbedded: true); + var embeddedPortablePdbMetadataFile = new MetadataFile(MetadataFile.MetadataFileKind.ProgramDebugDatabase, module.FileName, embeddedPortablePdbProvider, isEmbedded: true); this.Children.Add(new MetadataTreeNode(embeddedPortablePdbMetadataFile, "Debug Metadata (Embedded)")); break; diff --git a/ILSpy/Metadata/GoToTokenCommand.cs b/ILSpy/Metadata/GoToTokenCommand.cs index d8963ce60..ae0fa1657 100644 --- a/ILSpy/Metadata/GoToTokenCommand.cs +++ b/ILSpy/Metadata/GoToTokenCommand.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy.Commands { public void Execute(TextViewContext context) { - int token = GetSelectedToken(context.DataGrid, out PEFile module).Value; + int token = GetSelectedToken(context.DataGrid, out MetadataFile module).Value; MainWindow.Instance.JumpToReference(new EntityReference(module, MetadataTokens.Handle(token), protocol: "metadata")); } @@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy.Commands return context.DataGrid?.Name == "MetadataView" && GetSelectedToken(context.DataGrid, out _) != null; } - private int? GetSelectedToken(DataGrid grid, out PEFile module) + private int? GetSelectedToken(DataGrid grid, out MetadataFile module) { module = null; if (grid == null) @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.Commands var moduleField = type.GetField("module", BindingFlags.NonPublic | BindingFlags.Instance); if (property == null || property.PropertyType != typeof(int) || !property.GetCustomAttributes(false).Any(a => a is ColumnInfoAttribute { Kind: ColumnKind.Token } c)) return null; - module = (PEFile)moduleField.GetValue(cell.Item); + module = (MetadataFile)moduleField.GetValue(cell.Item); return (int)property.GetValue(cell.Item); } } diff --git a/ILSpy/Metadata/MetadataProtocolHandler.cs b/ILSpy/Metadata/MetadataProtocolHandler.cs index 3fb5219d9..e4fc4bbec 100644 --- a/ILSpy/Metadata/MetadataProtocolHandler.cs +++ b/ILSpy/Metadata/MetadataProtocolHandler.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.Metadata [Export(typeof(IProtocolHandler))] class MetadataProtocolHandler : IProtocolHandler { - public ILSpyTreeNode Resolve(string protocol, PEFile module, Handle handle, out bool newTabPage) + public ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage) { newTabPage = true; if (protocol != "metadata") diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index 0bd418539..995c9303e 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -21,7 +21,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; @@ -34,7 +33,6 @@ using System.Windows.Media; using System.Windows.Threading; using ICSharpCode.ILSpy.Docking; -using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX.Extensions; @@ -467,7 +465,7 @@ namespace ICSharpCode.ILSpy.Search { foreach (var loadedAssembly in assemblies) { - var module = loadedAssembly.GetPEFileOrNull(); + var module = loadedAssembly.GetMetadataFileOrNull(); if (module == null) continue; searcher.Search(module, cts.Token); diff --git a/ILSpy/Search/SearchResultFactory.cs b/ILSpy/Search/SearchResultFactory.cs index 63db8e909..f466436c7 100644 --- a/ILSpy/Search/SearchResultFactory.cs +++ b/ILSpy/Search/SearchResultFactory.cs @@ -105,14 +105,14 @@ namespace ICSharpCode.ILSpy.Search Name = GetLanguageSpecificName(entity), Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : entity.Namespace, Assembly = entity.ParentModule.FullAssemblyName, - ToolTip = entity.ParentModule.PEFile?.FileName, + ToolTip = entity.ParentModule.MetadataFile?.FileName, Image = GetIcon(entity), LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace, AssemblyImage = Images.Assembly, }; } - public ResourceSearchResult Create(PEFile module, Resource resource, ITreeNode node, ITreeNode parent) + public ResourceSearchResult Create(MetadataFile module, Resource resource, ITreeNode node, ITreeNode parent) { return new ResourceSearchResult { Resource = resource, @@ -127,7 +127,7 @@ namespace ICSharpCode.ILSpy.Search }; } - public AssemblySearchResult Create(PEFile module) + public AssemblySearchResult Create(MetadataFile module) { return new AssemblySearchResult { Module = module, @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Search }; } - public NamespaceSearchResult Create(PEFile module, INamespace ns) + public NamespaceSearchResult Create(MetadataFile module, INamespace ns) { var name = ns.FullName.Length == 0 ? "-" : ns.FullName; return new NamespaceSearchResult { @@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy.Search return ResourceTreeNode.Create(resource); } - public ITreeNode CreateResourcesList(PEFile module) + public ITreeNode CreateResourcesList(MetadataFile module) { return new ResourceListTreeNode(module); } diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index a1f2cbc7e..00ce4204b 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -51,7 +51,6 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.Documentation; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.AvalonEdit; using ICSharpCode.ILSpy.Options; @@ -411,7 +410,7 @@ namespace ICSharpCode.ILSpy.TextView } else if (segment.Reference is EntityReference unresolvedEntity) { - var module = unresolvedEntity.ResolveAssembly(MainWindow.Instance.CurrentAssemblyList) as PEFile; + var module = unresolvedEntity.ResolveAssembly(MainWindow.Instance.CurrentAssemblyList); if (module == null) return null; var typeSystem = new DecompilerTypeSystem(module, @@ -451,9 +450,9 @@ namespace ICSharpCode.ILSpy.TextView renderer.AddSignatureBlock(richText.Text, richText.ToRichTextModel()); try { - if (resolved.ParentModule == null || resolved.ParentModule.PEFile == null) + if (resolved.ParentModule == null || resolved.ParentModule.MetadataFile == null) return null; - var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentModule.PEFile); + var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentModule.MetadataFile); if (docProvider != null) { string documentation = docProvider.GetDocumentation(resolved.GetIdString()); diff --git a/ILSpy/TreeNodes/AssemblyListTreeNode.cs b/ILSpy/TreeNodes/AssemblyListTreeNode.cs index 4d29f8fe8..e5ba90658 100644 --- a/ILSpy/TreeNodes/AssemblyListTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyListTreeNode.cs @@ -165,10 +165,10 @@ namespace ICSharpCode.ILSpy.TreeNodes public AssemblyTreeNode FindAssemblyNode(IModule module) { - return FindAssemblyNode(module.PEFile); + return FindAssemblyNode(module.MetadataFile); } - public AssemblyTreeNode FindAssemblyNode(PEFile module) + public AssemblyTreeNode FindAssemblyNode(MetadataFile module) { if (module == null) return null; diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index fa692d284..04b179a3d 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -103,6 +103,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return loadResult.MetadataFile.Kind switch { MetadataFile.MetadataFileKind.PortableExecutable => Images.Assembly, MetadataFile.MetadataFileKind.ProgramDebugDatabase => Images.ProgramDebugDatabase, + MetadataFile.MetadataFileKind.WebCIL => Images.WebAssemblyFile, _ => Images.MetadataFile, }; } @@ -128,7 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes if (tooltip == null && LoadedAssembly.IsLoaded) { tooltip = new TextBlock(); - var module = LoadedAssembly.GetPEFileOrNull(); + var module = LoadedAssembly.GetMetadataFileOrNull(); var metadata = module?.Metadata; if (metadata?.IsAssembly == true && metadata.TryGetFullAssemblyName(out var assemblyName)) { @@ -140,9 +141,12 @@ namespace ICSharpCode.ILSpy.TreeNodes tooltip.Inlines.Add(new Run(LoadedAssembly.FileName)); if (module != null) { - tooltip.Inlines.Add(new LineBreak()); - tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); - tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(module))); + if (module is PEFile peFile) + { + tooltip.Inlines.Add(new LineBreak()); + tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); + tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(peFile))); + } string runtimeName = Language.GetRuntimeDisplayName(module); if (runtimeName != null) { @@ -196,24 +200,31 @@ namespace ICSharpCode.ILSpy.TreeNodes } try { - if (loadResult.PEFile != null) + if (loadResult.MetadataFile != null) { - LoadChildrenForPEFile(loadResult.PEFile); + switch (loadResult.MetadataFile.Kind) + { + case MetadataFile.MetadataFileKind.PortableExecutable: + LoadChildrenForPEFile(loadResult.PEFile); + break; + case MetadataFile.MetadataFileKind.WebCIL: + LoadChildrenForWebCilFile((WebCilFile)loadResult.MetadataFile); + break; + default: + var metadata = loadResult.MetadataFile; + this.Children.Add(new MetadataTablesTreeNode(metadata)); + this.Children.Add(new StringHeapTreeNode(metadata)); + this.Children.Add(new UserStringHeapTreeNode(metadata)); + this.Children.Add(new GuidHeapTreeNode(metadata)); + this.Children.Add(new BlobHeapTreeNode(metadata)); + break; + } } else if (loadResult.Package != null) { var package = loadResult.Package; this.Children.AddRange(PackageFolderTreeNode.LoadChildrenForFolder(package.RootFolder)); } - else if (loadResult.MetadataFile != null) - { - var metadata = loadResult.MetadataFile; - this.Children.Add(new MetadataTablesTreeNode(metadata)); - this.Children.Add(new StringHeapTreeNode(metadata)); - this.Children.Add(new UserStringHeapTreeNode(metadata)); - this.Children.Add(new GuidHeapTreeNode(metadata)); - this.Children.Add(new BlobHeapTreeNode(metadata)); - } } catch (Exception ex) { @@ -221,7 +232,73 @@ namespace ICSharpCode.ILSpy.TreeNodes } } - void LoadChildrenForPEFile(PEFile module) + void LoadChildrenForPEFile(MetadataFile module) + { + typeSystem = LoadedAssembly.GetTypeSystemOrNull(); + var assembly = (MetadataModule)typeSystem.MainModule; + this.Children.Add(new MetadataTreeNode(module, Resources.Metadata)); + Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull(); + if (debugInfo is PortableDebugInfoProvider ppdb + && ppdb.GetMetadataReader() is System.Reflection.Metadata.MetadataReader reader) + { + this.Children.Add(new MetadataTreeNode(ppdb.ToMetadataFile(), $"Debug Metadata ({(ppdb.IsEmbedded ? "Embedded" : "From portable PDB")})")); + } + this.Children.Add(new ReferenceFolderTreeNode(module, this)); + if (module.Resources.Any()) + this.Children.Add(new ResourceListTreeNode(module)); + foreach (NamespaceTreeNode ns in namespaces.Values) + { + ns.Children.Clear(); + } + namespaces.Clear(); + bool useNestedStructure = MainWindow.Instance.CurrentDisplaySettings.UseNestedNamespaceNodes; + foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) + { + var ns = GetOrCreateNamespaceTreeNode(type.Namespace); + TypeTreeNode node = new TypeTreeNode(type, this); + typeDict[(TypeDefinitionHandle)type.MetadataToken] = node; + ns.Children.Add(node); + } + foreach (NamespaceTreeNode ns in namespaces.Values + .Where(ns => ns.Children.Count > 0 && ns.Parent == null) + .OrderBy(n => n.Name, NaturalStringComparer.Instance)) + { + this.Children.Add(ns); + SetPublicAPI(ns); + } + + NamespaceTreeNode GetOrCreateNamespaceTreeNode(string @namespace) + { + if (!namespaces.TryGetValue(@namespace, out NamespaceTreeNode ns)) + { + if (useNestedStructure) + { + int decimalIndex = @namespace.LastIndexOf('.'); + if (decimalIndex < 0) + { + var escapedNamespace = Language.EscapeName(@namespace); + ns = new NamespaceTreeNode(escapedNamespace); + } + else + { + var parentNamespaceTreeNode = GetOrCreateNamespaceTreeNode(@namespace.Substring(0, decimalIndex)); + var escapedInnerNamespace = Language.EscapeName(@namespace.Substring(decimalIndex + 1)); + ns = new NamespaceTreeNode(escapedInnerNamespace); + parentNamespaceTreeNode.Children.Add(ns); + } + } + else + { + var escapedNamespace = Language.EscapeName(@namespace); + ns = new NamespaceTreeNode(escapedNamespace); + } + namespaces.Add(@namespace, ns); + } + return ns; + } + } + + void LoadChildrenForWebCilFile(WebCilFile module) { typeSystem = LoadedAssembly.GetTypeSystemOrNull(); var assembly = (MetadataModule)typeSystem.MainModule; @@ -400,7 +477,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } else { - LoadedAssembly.GetPEFileOrNullAsync().GetAwaiter().GetResult(); + LoadedAssembly.GetMetadataFileOrNullAsync().GetAwaiter().GetResult(); } } catch (BadImageFormatException badImage) @@ -415,7 +492,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { HandleException(dirNotFound, "The directory was not found."); } - catch (PEFileNotSupportedException notSupported) + catch (MetadataFileNotSupportedException notSupported) { HandleException(notSupported, notSupported.Message); } @@ -569,7 +646,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { var la = ((AssemblyTreeNode)node).LoadedAssembly; var resolver = la.GetAssemblyResolver(); - var module = la.GetPEFileOrNull(); + var module = la.GetMetadataFileOrNull(); if (module != null) { var metadata = module.Metadata; diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs index d2d79650c..4b8100747 100644 --- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs +++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs @@ -34,10 +34,10 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class BaseTypesTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; readonly ITypeDefinition type; - public BaseTypesTreeNode(PEFile module, ITypeDefinition type) + public BaseTypesTreeNode(MetadataFile module, ITypeDefinition type) { this.module = module; this.type = type; @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes AddBaseTypes(this.Children, module, type); } - internal static void AddBaseTypes(SharpTreeNodeCollection children, PEFile module, ITypeDefinition typeDefinition) + internal static void AddBaseTypes(SharpTreeNodeCollection children, MetadataFile module, ITypeDefinition typeDefinition) { TypeDefinitionHandle handle = (TypeDefinitionHandle)typeDefinition.MetadataToken; DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver(), diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs index 46dcbf6d7..7a0b7accd 100644 --- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs @@ -64,10 +64,10 @@ namespace ICSharpCode.ILSpy.TreeNodes internal static IEnumerable FindDerivedTypes(AssemblyList list, ITypeDefinition type, CancellationToken cancellationToken) { - var definitionMetadata = type.ParentModule.PEFile.Metadata; + var definitionMetadata = type.ParentModule.MetadataFile.Metadata; var metadataToken = (SRM.TypeDefinitionHandle)type.MetadataToken; var assemblies = list.GetAllAssemblies().GetAwaiter().GetResult() - .Select(node => node.GetPEFileOrNull()).Where(asm => asm != null).ToArray(); + .Select(node => node.GetMetadataFileOrNull()).Where(asm => asm != null).ToArray(); foreach (var module in assemblies) { var metadata = module.Metadata; diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs index 9f73940f9..0499f5dff 100644 --- a/ILSpy/TreeNodes/EventTreeNode.cs +++ b/ILSpy/TreeNodes/EventTreeNode.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes private IEvent GetEventDefinition() { - return ((MetadataModule)EventDefinition.ParentModule.PEFile + return ((MetadataModule)EventDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((EventDefinitionHandle)EventDefinition.MetadataToken) ?? EventDefinition; } diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index 3219abcd5..4df85b89f 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes private IField GetFieldDefinition() { - return ((MetadataModule)FieldDefinition.ParentModule.PEFile + return ((MetadataModule)FieldDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((FieldDefinitionHandle)FieldDefinition.MetadataToken) ?? FieldDefinition; } diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index 03bd8bd1e..c805d5a83 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes private IMethod GetMethodDefinition() { - return ((MetadataModule)MethodDefinition.ParentModule.PEFile + return ((MetadataModule)MethodDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((MethodDefinitionHandle)MethodDefinition.MetadataToken) ?? MethodDefinition; } diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs index c0c37654a..e3c248131 100644 --- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs @@ -17,13 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Linq; using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.Metadata; namespace ICSharpCode.ILSpy.TreeNodes { @@ -32,7 +29,7 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ModuleReferenceTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; readonly AssemblyTreeNode parentAssembly; readonly MetadataReader metadata; readonly ModuleReferenceHandle handle; @@ -42,7 +39,7 @@ namespace ICSharpCode.ILSpy.TreeNodes readonly string moduleName; readonly bool containsMetadata; - public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, PEFile module) + public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataFile module) { this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly)); if (r.IsNil) @@ -78,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes if (assemblyListNode != null && containsMetadata) { var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(); - var mainModule = parentAssembly.LoadedAssembly.GetPEFileOrNull(); + var mainModule = parentAssembly.LoadedAssembly.GetMetadataFileOrNull(); if (mainModule != null) { assemblyListNode.Select(assemblyListNode.FindAssemblyNode(resolver.ResolveModule(mainModule, metadata.GetString(reference.Name)))); diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs index a495c6e79..ab437f8d4 100644 --- a/ILSpy/TreeNodes/PropertyTreeNode.cs +++ b/ILSpy/TreeNodes/PropertyTreeNode.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes private IProperty GetPropertyDefinition() { - return ((MetadataModule)PropertyDefinition.ParentModule.PEFile + return ((MetadataModule)PropertyDefinition.ParentModule.MetadataFile ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule)?.GetDefinition((PropertyDefinitionHandle)PropertyDefinition.MetadataToken) ?? PropertyDefinition; } diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs index e978a7e8a..2f3942083 100644 --- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs +++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs @@ -32,10 +32,10 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ReferenceFolderTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; readonly AssemblyTreeNode parentAssembly; - public ReferenceFolderTreeNode(PEFile module, AssemblyTreeNode parentAssembly) + public ReferenceFolderTreeNode(MetadataFile module, AssemblyTreeNode parentAssembly) { this.module = module; this.parentAssembly = parentAssembly; diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs index 5b5b80b33..d812b7966 100644 --- a/ILSpy/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs @@ -23,7 +23,6 @@ using System.Windows.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; -using ICSharpCode.ILSpyX.Abstractions; namespace ICSharpCode.ILSpy.TreeNodes { @@ -32,9 +31,9 @@ namespace ICSharpCode.ILSpy.TreeNodes /// sealed class ResourceListTreeNode : ILSpyTreeNode { - readonly PEFile module; + readonly MetadataFile module; - public ResourceListTreeNode(PEFile module) + public ResourceListTreeNode(MetadataFile module) { this.LazyLoading = true; this.module = module; diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 83126d88c..5917f35e0 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes private ITypeDefinition GetTypeDefinition() { return ((MetadataModule)ParentAssemblyNode.LoadedAssembly - .GetPEFileOrNull() + .GetMetadataFileOrNull() ?.GetTypeSystemWithCurrentOptionsOrNull() ?.MainModule).GetDefinition((SRM.TypeDefinitionHandle)TypeDefinition.MetadataToken); } @@ -87,7 +87,7 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void LoadChildren() { if (TypeDefinition.DirectBaseTypes.Any()) - this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetPEFileOrNull(), TypeDefinition)); + this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetMetadataFileOrNull(), TypeDefinition)); if (!TypeDefinition.IsSealed) this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition)); foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) diff --git a/TestPlugin/ContextMenuCommand.cs b/TestPlugin/ContextMenuCommand.cs index 6bbf3475b..9dc672fe5 100644 --- a/TestPlugin/ContextMenuCommand.cs +++ b/TestPlugin/ContextMenuCommand.cs @@ -6,8 +6,6 @@ using System.Linq; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TreeNodes; -using Microsoft.Win32; - namespace TestPlugin { [ExportContextMenuEntryAttribute(Header = "_Save Assembly")] @@ -28,7 +26,7 @@ namespace TestPlugin if (context.SelectedTreeNodes == null) return; AssemblyTreeNode node = (AssemblyTreeNode)context.SelectedTreeNodes[0]; - var asm = node.LoadedAssembly.GetPEFileOrNull(); + var asm = node.LoadedAssembly.GetMetadataFileOrNull(); if (asm != null) { /*SaveFileDialog dlg = new SaveFileDialog(); diff --git a/TestPlugin/CustomLanguage.cs b/TestPlugin/CustomLanguage.cs index 4914edc26..e41ea015e 100644 --- a/TestPlugin/CustomLanguage.cs +++ b/TestPlugin/CustomLanguage.cs @@ -6,7 +6,6 @@ using System.Reflection.Metadata; using System.Windows.Controls; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy; @@ -34,11 +33,11 @@ namespace TestPlugin // There are several methods available to override; in this sample, we deal with methods only public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { - var module = ((MetadataModule)method.ParentModule).PEFile; + var module = ((MetadataModule)method.ParentModule).MetadataFile; var methodDef = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); if (methodDef.HasBody()) { - var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var methodBody = module.GetMethodBody(methodDef.RelativeVirtualAddress); output.WriteLine("Size of method: {0} bytes", methodBody.GetCodeSize()); ISmartTextOutput smartOutput = output as ISmartTextOutput;