internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options) { this.Compilation = compilation; this.PEFile = peFile; this.metadata = peFile.Metadata; this.options = options; this.TypeProvider = new TypeProvider(this); // assembly metadata if (metadata.IsAssembly) { var asmdef = metadata.GetAssemblyDefinition(); this.AssemblyName = metadata.GetString(asmdef.Name); this.FullAssemblyName = metadata.GetFullAssemblyName(); } else { var moddef = metadata.GetModuleDefinition(); this.AssemblyName = metadata.GetString(moddef.Name); this.FullAssemblyName = this.AssemblyName; } this.rootNamespace = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot()); if (!options.HasFlag(TypeSystemOptions.Uncached)) { // create arrays for resolved entities, indexed by row index this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1]; this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1]; this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1]; this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1]; this.eventDefs = new MetadataEvent[metadata.EventDefinitions.Count + 1]; } }
public static string GetPlatformName(Metadata.PEFile module) { var headers = module.Reader.PEHeaders; switch (headers.CoffHeader.Machine) { case Machine.I386: if ((headers.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) { return("AnyCPU"); } else if ((headers.CorHeader.Flags & CorFlags.Requires32Bit) != 0) { return("x86"); } else { return("AnyCPU"); } case Machine.Amd64: return("x64"); case Machine.IA64: return("Itanium"); default: return(headers.CoffHeader.Machine.ToString()); } }
internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options) { this.Compilation = compilation; this.PEFile = peFile; this.metadata = peFile.Metadata; this.options = options; this.TypeProvider = new TypeProvider(this); // assembly metadata if (metadata.IsAssembly) { var asmdef = metadata.GetAssemblyDefinition(); try { this.AssemblyName = metadata.GetString(asmdef.Name); this.AssemblyVersion = asmdef.Version; this.FullAssemblyName = metadata.GetFullAssemblyName(); } catch (BadImageFormatException) { this.AssemblyName = "<ERR: invalid assembly name>"; this.FullAssemblyName = "<ERR: invalid assembly name>"; } } else { try { var moddef = metadata.GetModuleDefinition(); this.AssemblyName = metadata.GetString(moddef.Name); } catch (BadImageFormatException) { this.AssemblyName = "<ERR: invalid assembly name>"; } this.FullAssemblyName = this.AssemblyName; } var customAttrs = metadata.GetModuleDefinition().GetCustomAttributes(); this.NullableContext = customAttrs.GetNullableContext(metadata) ?? Nullability.Oblivious; this.minAccessibilityForNRT = FindMinimumAccessibilityForNRT(metadata, customAttrs); this.rootNamespace = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot()); if (!options.HasFlag(TypeSystemOptions.Uncached)) { // create arrays for resolved entities, indexed by row index this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1]; this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1]; this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1]; this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1]; this.eventDefs = new MetadataEvent[metadata.EventDefinitions.Count + 1]; this.referencedAssemblies = new IModule[metadata.AssemblyReferences.Count + 1]; } }
protected virtual bool IncludeTypeWhenDecompilingProject(Metadata.PEFile module, TypeDefinitionHandle type) { var metadata = module.Metadata; var typeDef = metadata.GetTypeDefinition(type); if (metadata.GetString(typeDef.Name) == "<Module>" || CSharpDecompiler.MemberIsHidden(module, type, settings)) { return(false); } if (metadata.GetString(typeDef.Namespace) == "XamlGeneratedNamespace" && metadata.GetString(typeDef.Name) == "GeneratedInternalTypeHelper") { return(false); } return(true); }
IEnumerable <Tuple <string, string> > WriteCodeFilesInProject(Metadata.PEFile module, CancellationToken cancellationToken) { var metadata = module.Metadata; var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy( delegate(TypeDefinitionHandle h) { var type = metadata.GetTypeDefinition(h); string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs"; if (string.IsNullOrEmpty(metadata.GetString(type.Namespace))) { return(file); } else { string dir = CleanUpFileName(metadata.GetString(type.Namespace)); if (directories.Add(dir)) { Directory.CreateDirectory(Path.Combine(targetDirectory, dir)); } return(Path.Combine(dir, file)); } }, StringComparer.OrdinalIgnoreCase).ToList(); int total = files.Count; var progress = this.ProgressIndicator; DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, settings); Parallel.ForEach( files, new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, CancellationToken = cancellationToken }, delegate(IGrouping <string, TypeDefinitionHandle> file) { using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) { try { CSharpDecompiler decompiler = CreateDecompiler(ts); decompiler.CancellationToken = cancellationToken; var syntaxTree = decompiler.DecompileTypes(file.ToArray()); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions)); } catch (Exception innerException) when(!(innerException is OperationCanceledException || innerException is DecompilerException)) { throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException); } } progress?.Report(new DecompilationProgress(total, file.Key)); }); return(files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken))); }
public static string GetPlatformName(Metadata.PEFile module) { var headers = module.Reader.PEHeaders; var architecture = headers.CoffHeader.Machine; var characteristics = headers.CoffHeader.Characteristics; var corflags = headers.CorHeader.Flags; switch (architecture) { case Machine.I386: if ((corflags & CorFlags.Prefers32Bit) != 0) { return("AnyCPU"); } if ((corflags & CorFlags.Requires32Bit) != 0) { return("x86"); } // According to ECMA-335, II.25.3.3.1 CorFlags.Requires32Bit and Characteristics.Bit32Machine must be in sync // for assemblies containing managed code. However, this is not true for C++/CLI assemblies. if ((corflags & CorFlags.ILOnly) == 0 && (characteristics & Characteristics.Bit32Machine) != 0) { return("x86"); } return("AnyCPU"); case Machine.Amd64: return("x64"); case Machine.IA64: return("Itanium"); default: return(architecture.ToString()); } }
public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, GenericContext context, ITextOutput writer) { writer.Write(".try "); WriteOffsetReference(writer, exceptionHandler.TryOffset); writer.Write('-'); WriteOffsetReference(writer, exceptionHandler.TryOffset + exceptionHandler.TryLength); writer.Write(' '); writer.Write(exceptionHandler.Kind.ToString().ToLowerInvariant()); if (exceptionHandler.FilterOffset != -1) { writer.Write(' '); WriteOffsetReference(writer, exceptionHandler.FilterOffset); writer.Write(" handler "); } if (!exceptionHandler.CatchType.IsNil) { writer.Write(' '); exceptionHandler.CatchType.WriteTo(module, writer, context); } writer.Write(' '); WriteOffsetReference(writer, exceptionHandler.HandlerOffset); writer.Write('-'); WriteOffsetReference(writer, exceptionHandler.HandlerOffset + exceptionHandler.HandlerLength); }
protected virtual IEnumerable <Tuple <string, string> > WriteResourceFilesInProject(Metadata.PEFile module) { foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded)) { Stream stream = r.TryOpenStream(); stream.Position = 0; if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { bool decodedIntoIndividualFiles; var individualResources = new List <Tuple <string, string> >(); try { var resourcesFile = new ResourcesFile(stream); if (resourcesFile.AllEntriesAreStreams()) { foreach (var(name, value) in resourcesFile) { string fileName = Path.Combine(name.Split('/').Select(p => CleanUpFileName(p)).ToArray()); string dirName = Path.GetDirectoryName(fileName); if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) { Directory.CreateDirectory(Path.Combine(targetDirectory, dirName)); } Stream entryStream = (Stream)value; entryStream.Position = 0; individualResources.AddRange( WriteResourceToFile(fileName, (string)name, entryStream)); } decodedIntoIndividualFiles = true; } else { decodedIntoIndividualFiles = false; } } catch (BadImageFormatException) { decodedIntoIndividualFiles = false; } catch (EndOfStreamException) { decodedIntoIndividualFiles = false; } if (decodedIntoIndividualFiles) { foreach (var entry in individualResources) { yield return(entry); } } else { stream.Position = 0; string fileName = GetFileNameForResource(r.Name); foreach (var entry in WriteResourceToFile(fileName, r.Name, stream)) { yield return(entry); } } } else { string fileName = GetFileNameForResource(r.Name); using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) { stream.Position = 0; stream.CopyTo(fs); } yield return(Tuple.Create("EmbeddedResource", fileName)); } } }
protected virtual bool IsGacAssembly(Metadata.IAssemblyReference r, Metadata.PEFile asm) { return(false); }
void WriteProjectFile(TextWriter writer, IEnumerable <Tuple <string, string> > files, Metadata.PEFile module) { const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; string platformName = GetPlatformName(module); Guid guid = this.ProjectGuid ?? Guid.NewGuid(); using (XmlTextWriter w = new XmlTextWriter(writer)) { w.Formatting = Formatting.Indented; w.WriteStartDocument(); w.WriteStartElement("Project", ns); w.WriteAttributeString("ToolsVersion", "4.0"); w.WriteAttributeString("DefaultTargets", "Build"); w.WriteStartElement("PropertyGroup"); w.WriteElementString("ProjectGuid", guid.ToString("B").ToUpperInvariant()); w.WriteStartElement("Configuration"); w.WriteAttributeString("Condition", " '$(Configuration)' == '' "); w.WriteValue("Debug"); w.WriteEndElement(); // </Configuration> w.WriteStartElement("Platform"); w.WriteAttributeString("Condition", " '$(Platform)' == '' "); w.WriteValue(platformName); w.WriteEndElement(); // </Platform> if (module.Reader.PEHeaders.IsDll) { w.WriteElementString("OutputType", "Library"); } else { 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; } } w.WriteElementString("LangVersion", LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); w.WriteElementString("AssemblyName", module.Name); bool useTargetFrameworkAttribute = false; LanguageTargets languageTargets = LanguageTargets.None; string targetFramework = module.Reader.DetectTargetFrameworkId(); if (!string.IsNullOrEmpty(targetFramework)) { string[] frameworkParts = targetFramework.Split(','); string frameworkIdentifier = frameworkParts.FirstOrDefault(a => !a.StartsWith("Version=", StringComparison.OrdinalIgnoreCase) && !a.StartsWith("Profile=", StringComparison.OrdinalIgnoreCase)); if (frameworkIdentifier != null) { w.WriteElementString("TargetFrameworkIdentifier", frameworkIdentifier); switch (frameworkIdentifier) { case ".NETPortable": languageTargets = LanguageTargets.Portable; break; } } string frameworkVersion = frameworkParts.FirstOrDefault(a => a.StartsWith("Version=", StringComparison.OrdinalIgnoreCase)); if (frameworkVersion != null) { w.WriteElementString("TargetFrameworkVersion", frameworkVersion.Substring("Version=".Length)); useTargetFrameworkAttribute = true; } string frameworkProfile = frameworkParts.FirstOrDefault(a => a.StartsWith("Profile=", StringComparison.OrdinalIgnoreCase)); if (frameworkProfile != null) { w.WriteElementString("TargetFrameworkProfile", frameworkProfile.Substring("Profile=".Length)); } } if (!useTargetFrameworkAttribute) { switch (module.GetRuntime()) { case Metadata.TargetRuntime.Net_1_0: w.WriteElementString("TargetFrameworkVersion", "v1.0"); break; case Metadata.TargetRuntime.Net_1_1: w.WriteElementString("TargetFrameworkVersion", "v1.1"); break; case Metadata.TargetRuntime.Net_2_0: w.WriteElementString("TargetFrameworkVersion", "v2.0"); // TODO: Detect when .NET 3.0/3.5 is required break; default: w.WriteElementString("TargetFrameworkVersion", "v4.0"); break; } } w.WriteElementString("WarningLevel", "4"); w.WriteElementString("AllowUnsafeBlocks", "True"); w.WriteEndElement(); // </PropertyGroup> w.WriteStartElement("PropertyGroup"); // platform-specific w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); w.WriteElementString("PlatformTarget", platformName); if ((module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) { w.WriteElementString("Prefer32Bit", "True"); } w.WriteEndElement(); // </PropertyGroup> (platform-specific) w.WriteStartElement("PropertyGroup"); // Debug w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' "); w.WriteElementString("OutputPath", "bin\\Debug\\"); w.WriteElementString("DebugSymbols", "true"); w.WriteElementString("DebugType", "full"); w.WriteElementString("Optimize", "false"); w.WriteEndElement(); // </PropertyGroup> (Debug) w.WriteStartElement("PropertyGroup"); // Release w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' "); w.WriteElementString("OutputPath", "bin\\Release\\"); w.WriteElementString("DebugSymbols", "true"); w.WriteElementString("DebugType", "pdbonly"); w.WriteElementString("Optimize", "true"); w.WriteEndElement(); // </PropertyGroup> (Release) w.WriteStartElement("ItemGroup"); // References foreach (var r in module.AssemblyReferences) { if (r.Name != "mscorlib") { w.WriteStartElement("Reference"); w.WriteAttributeString("Include", r.Name); var asm = AssemblyResolver.Resolve(r); if (!IsGacAssembly(r, asm)) { if (asm != null) { w.WriteElementString("HintPath", asm.FileName); } } w.WriteEndElement(); } } w.WriteEndElement(); // </ItemGroup> (References) foreach (IGrouping <string, string> gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g)) { w.WriteStartElement("ItemGroup"); foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { w.WriteStartElement(gr.Key); w.WriteAttributeString("Include", file); w.WriteEndElement(); } w.WriteEndElement(); } switch (languageTargets) { case LanguageTargets.Portable: w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"); w.WriteEndElement(); break; default: w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"); w.WriteEndElement(); break; } w.WriteEndDocument(); } }
ProjectId WriteProjectFile(TextWriter writer, IEnumerable <Tuple <string, string> > files, Metadata.PEFile module) { const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; string platformName = GetPlatformName(module); Guid guid = this.ProjectGuid ?? Guid.NewGuid(); var targetFramework = DetectTargetFramework(module); List <Guid> typeGuids = new List <Guid>(); if (targetFramework.IsPortableClassLibrary) { typeGuids.Add(ProjectTypeGuids.PortableLibrary); } typeGuids.Add(ProjectTypeGuids.CSharpWindows); // TODO: .NET core support using (XmlTextWriter w = new XmlTextWriter(writer)) { w.Formatting = Formatting.Indented; w.WriteStartDocument(); w.WriteStartElement("Project", ns); w.WriteAttributeString("ToolsVersion", "4.0"); w.WriteAttributeString("DefaultTargets", "Build"); w.WriteStartElement("PropertyGroup"); w.WriteElementString("ProjectGuid", guid.ToString("B").ToUpperInvariant()); w.WriteElementString("ProjectTypeGuids", string.Join(";", typeGuids.Select(g => g.ToString("B").ToUpperInvariant()))); w.WriteStartElement("Configuration"); w.WriteAttributeString("Condition", " '$(Configuration)' == '' "); w.WriteValue("Debug"); w.WriteEndElement(); // </Configuration> w.WriteStartElement("Platform"); w.WriteAttributeString("Condition", " '$(Platform)' == '' "); w.WriteValue(platformName); w.WriteEndElement(); // </Platform> if (module.Reader.PEHeaders.IsDll) { w.WriteElementString("OutputType", "Library"); } else { 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; } } w.WriteElementString("LangVersion", LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); w.WriteElementString("AssemblyName", module.Name); if (targetFramework.TargetFrameworkIdentifier != null) { w.WriteElementString("TargetFrameworkIdentifier", targetFramework.TargetFrameworkIdentifier); } if (targetFramework.TargetFrameworkVersion != null) { w.WriteElementString("TargetFrameworkVersion", targetFramework.TargetFrameworkVersion); } if (targetFramework.TargetFrameworkProfile != null) { w.WriteElementString("TargetFrameworkProfile", targetFramework.TargetFrameworkProfile); } w.WriteElementString("WarningLevel", "4"); w.WriteElementString("AllowUnsafeBlocks", "True"); if (StrongNameKeyFile != null) { w.WriteElementString("SignAssembly", "True"); w.WriteElementString("AssemblyOriginatorKeyFile", Path.GetFileName(StrongNameKeyFile)); } w.WriteEndElement(); // </PropertyGroup> 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) { w.WriteElementString("Prefer32Bit", "false"); } w.WriteEndElement(); // </PropertyGroup> (platform-specific) w.WriteStartElement("PropertyGroup"); // Debug w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' "); w.WriteElementString("OutputPath", "bin\\Debug\\"); w.WriteElementString("DebugSymbols", "true"); w.WriteElementString("DebugType", "full"); w.WriteElementString("Optimize", "false"); w.WriteEndElement(); // </PropertyGroup> (Debug) w.WriteStartElement("PropertyGroup"); // Release w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' "); w.WriteElementString("OutputPath", "bin\\Release\\"); w.WriteElementString("DebugSymbols", "true"); w.WriteElementString("DebugType", "pdbonly"); w.WriteElementString("Optimize", "true"); w.WriteEndElement(); // </PropertyGroup> (Release) w.WriteStartElement("ItemGroup"); // References foreach (var r in module.AssemblyReferences) { if (r.Name != "mscorlib") { w.WriteStartElement("Reference"); w.WriteAttributeString("Include", r.Name); var asm = AssemblyResolver.Resolve(r); if (!IsGacAssembly(r, asm)) { if (asm != null) { w.WriteElementString("HintPath", asm.FileName); } } w.WriteEndElement(); } } w.WriteEndElement(); // </ItemGroup> (References) foreach (IGrouping <string, string> gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g)) { w.WriteStartElement("ItemGroup"); foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { w.WriteStartElement(gr.Key); w.WriteAttributeString("Include", file); w.WriteEndElement(); } w.WriteEndElement(); } if (targetFramework.IsPortableClassLibrary) { w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"); w.WriteEndElement(); } else { w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"); w.WriteEndElement(); } w.WriteEndDocument(); } return(new ProjectId(platformName, guid, ProjectTypeGuids.CSharpWindows)); }