Browse Source

Port BAML decompiler to SRM.

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
8884306244
  1. 2
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  2. 21
      ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs
  3. 1
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
  4. 12
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  5. 4
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  6. 15
      ILSpy.BamlDecompiler/CecilTypeResolver.cs
  7. 35
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  8. 4
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  9. 2
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs
  10. 4
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs
  11. 12
      ILSpy.sln

2
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// <summary> /// <summary>
/// Provides XML documentation tags. /// Provides XML documentation tags.
/// </summary> /// </summary>
public sealed class XmlDocKeyProvider public static class XmlDocKeyProvider
{ {
#region GetKey #region GetKey
public static string GetKey(Entity entity) public static string GetKey(Entity entity)

21
ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs

@ -8,8 +8,8 @@ using System.Linq;
using System.Resources; using System.Resources;
using System.Threading; using System.Threading;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Tests.Helpers;
using Mono.Cecil;
using NUnit.Framework; using NUnit.Framework;
namespace ILSpy.BamlDecompiler.Tests namespace ILSpy.BamlDecompiler.Tests
@ -112,16 +112,20 @@ namespace ILSpy.BamlDecompiler.Tests
void RunTest(string name, string asmPath, string sourcePath) void RunTest(string name, string asmPath, string sourcePath)
{ {
var resolver = new DefaultAssemblyResolver(); using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) {
var module = new PEFile(asmPath, fileStream, System.Reflection.PortableExecutable.PEStreamOptions.Default);
var resolver = new UniversalAssemblyResolver(asmPath, false, true, module.Reader.DetectTargetFrameworkId(), System.Reflection.PortableExecutable.PEStreamOptions.Default);
resolver.RemoveSearchDirectory("."); resolver.RemoveSearchDirectory(".");
resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath));
var assembly = AssemblyDefinition.ReadAssembly(asmPath, new ReaderParameters { AssemblyResolver = resolver, InMemory = true }); module.AssemblyResolver = resolver;
Resource res = assembly.MainModule.Resources.First(); var res = module.Resources.First();
Stream bamlStream = LoadBaml(res, name + ".baml"); Stream bamlStream = LoadBaml(res, name + ".baml");
Assert.IsNotNull(bamlStream); Assert.IsNotNull(bamlStream);
XDocument document = BamlResourceEntryNode.LoadIntoDocument(resolver, assembly, bamlStream, CancellationToken.None); XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, bamlStream, CancellationToken.None);
XamlIsEqual(File.ReadAllText(sourcePath), document.ToString()); XamlIsEqual(File.ReadAllText(sourcePath), document.ToString());
}
} }
void XamlIsEqual(string input1, string input2) void XamlIsEqual(string input1, string input2)
@ -139,9 +143,8 @@ namespace ILSpy.BamlDecompiler.Tests
Stream LoadBaml(Resource res, string name) Stream LoadBaml(Resource res, string name)
{ {
EmbeddedResource er = res as EmbeddedResource; if (res.ResourceType != ResourceType.Embedded) return null;
if (er != null) { Stream s = res.TryOpenStream();
Stream s = er.GetResourceStream();
s.Position = 0; s.Position = 0;
ResourceReader reader; ResourceReader reader;
try { try {
@ -157,8 +160,6 @@ namespace ILSpy.BamlDecompiler.Tests
return new MemoryStream((byte[])entry.Value); return new MemoryStream((byte[])entry.Value);
} }
} }
}
return null; return null;
} }
#endregion #endregion

1
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -38,6 +38,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj" /> <ProjectReference Include="..\ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj" />
<ProjectReference Include="..\ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj" />
<ProjectReference Include="..\ILSpy\ILSpy.csproj" /> <ProjectReference Include="..\ILSpy\ILSpy.csproj" />
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" /> <ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj" />
</ItemGroup> </ItemGroup>

12
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -10,7 +10,7 @@ using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
@ -50,7 +50,7 @@ namespace ILSpy.BamlDecompiler
{ {
var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly; var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly;
Data.Position = 0; Data.Position = 0;
XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.GetPEFileOrNull(), Data, cancellationToken); XDocument xamlDocument = LoadIntoDocument(asm.GetPEFileOrNull(), Data, cancellationToken);
output.Write(xamlDocument.ToString()); output.Write(xamlDocument.ToString());
return true; return true;
} }
@ -59,21 +59,21 @@ namespace ILSpy.BamlDecompiler
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
XDocument xamlDocument; XDocument xamlDocument;
using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(resolver, asm))) { using (XmlBamlReader reader = new XmlBamlReader(stream, new NRTypeResolver(module))) {
xamlDocument = XDocument.Load(reader); xamlDocument = XDocument.Load(reader);
ConvertConnectionIds(xamlDocument, asm, cancellationToken); ConvertConnectionIds(xamlDocument, module, cancellationToken);
ConvertToEmptyElements(xamlDocument.Root); ConvertToEmptyElements(xamlDocument.Root);
MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions); MoveNamespacesToRoot(xamlDocument, reader.XmlnsDefinitions);
return xamlDocument; return xamlDocument;
} }
} }
static void ConvertConnectionIds(XDocument xamlDocument, AssemblyDefinition asm, CancellationToken cancellationToken) static void ConvertConnectionIds(XDocument xamlDocument, PEFile asm, CancellationToken cancellationToken)
{ {
var attr = xamlDocument.Root.Attribute(XName.Get("Class", XmlBamlReader.XWPFNamespace)); var attr = xamlDocument.Root.Attribute(XName.Get("Class", XmlBamlReader.XWPFNamespace));
if (attr != null) { if (attr != null) {
string fullTypeName = attr.Value; string fullTypeName = attr.Value;
var mappings = new ConnectMethodDecompiler(asm).DecompileEventMappings(fullTypeName, cancellationToken); var mappings = new ConnectMethodDecompiler().DecompileEventMappings(asm, fullTypeName, cancellationToken);
RemoveConnectionIds(xamlDocument.Root, mappings); RemoveConnectionIds(xamlDocument.Root, mappings);
} }
} }

4
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -7,7 +7,7 @@ using System.IO;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
{ {
@ -36,7 +36,7 @@ namespace ILSpy.BamlDecompiler
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options) public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{ {
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.GetPEFileOrNull(), stream, options.CancellationToken); var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetPEFileOrNull(), stream, options.CancellationToken);
fileName = Path.ChangeExtension(fileName, ".xaml"); fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName)); document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName; return fileName;

15
ILSpy.BamlDecompiler/CecilTypeResolver.cs

@ -2,8 +2,8 @@
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) // This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System; using System;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection; using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
@ -13,11 +13,15 @@ namespace ILSpy.BamlDecompiler
/// </summary> /// </summary>
public class NRTypeResolver : IDotNetTypeResolver public class NRTypeResolver : IDotNetTypeResolver
{ {
readonly PEFile module;
readonly DecompilerTypeSystem typeSystem;
readonly ICompilation compilation; readonly ICompilation compilation;
public NRTypeResolver(ICompilation compilation) public NRTypeResolver(PEFile module)
{ {
this.compilation = compilation; this.module = module;
this.typeSystem = new DecompilerTypeSystem(module);
this.compilation = typeSystem.Compilation;
} }
public bool IsLocalAssembly(string name) public bool IsLocalAssembly(string name)
@ -66,10 +70,9 @@ namespace ILSpy.BamlDecompiler
throw new ArgumentException("Invalid IType: " + ownerType.GetType()); throw new ArgumentException("Invalid IType: " + ownerType.GetType());
} }
public string RuntimeVersion { public TargetRuntime RuntimeVersion {
get { get {
throw new NotImplementedException(); return module.GetRuntime();
//return thisAssembly.MainModule.Runtime.ToString();
} }
} }
} }

35
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -5,14 +5,16 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using Mono.Cecil; using Metadata = ICSharpCode.Decompiler.Metadata;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
{ {
@ -29,37 +31,36 @@ namespace ILSpy.BamlDecompiler
/// </summary> /// </summary>
sealed class ConnectMethodDecompiler sealed class ConnectMethodDecompiler
{ {
AssemblyDefinition assembly; public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module, string fullTypeName, CancellationToken cancellationToken)
public ConnectMethodDecompiler(AssemblyDefinition assembly)
{
this.assembly = assembly;
}
public List<(LongSet, EventRegistration[])> DecompileEventMappings(string fullTypeName, CancellationToken cancellationToken)
{ {
var result = new List<(LongSet, EventRegistration[])>(); var result = new List<(LongSet, EventRegistration[])>();
TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName);
if (type == null) var typeDefinition = (Metadata.TypeDefinition)XmlDocKeyProvider.FindMemberByKey(module, "T:" + fullTypeName);
if (typeDefinition.IsNil)
return result; return result;
MethodDefinition method = null; var metadata = module.GetMetadataReader();
TypeDefinition type = metadata.GetTypeDefinition(typeDefinition.Handle);
MethodDefinition method = default;
MethodDefinitionHandle handle = default;
foreach (var m in type.Methods) { foreach (var h in type.GetMethods()) {
if (m.Name == "System.Windows.Markup.IComponentConnector.Connect") { var m = metadata.GetMethodDefinition(h);
if (metadata.GetString(m.Name) == "System.Windows.Markup.IComponentConnector.Connect") {
handle = h;
method = m; method = m;
break; break;
} }
} }
if (method == null) if (handle.IsNil)
return result; return result;
// decompile method and optimize the switch // decompile method and optimize the switch
var typeSystem = new DecompilerTypeSystem(method.Module); var typeSystem = new DecompilerTypeSystem(typeDefinition.Module);
var ilReader = new ILReader(typeSystem); var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(method.Body, cancellationToken); var function = ilReader.ReadIL(typeDefinition.Module, handle, typeDefinition.Module.Reader.GetMethodBody(method.RelativeVirtualAddress), cancellationToken);
var context = new ILTransformContext(function, typeSystem) { var context = new ILTransformContext(function, typeSystem) {
CancellationToken = cancellationToken CancellationToken = cancellationToken

4
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -28,6 +28,10 @@
<OutputPath>..\ILSpy\bin\$(Configuration)\</OutputPath> <OutputPath>..\ILSpy\bin\$(Configuration)\</OutputPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />

2
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs

@ -6,7 +6,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
public interface IDotNetTypeResolver public interface IDotNetTypeResolver
{ {
string RuntimeVersion { get; } ICSharpCode.Decompiler.Metadata.TargetRuntime RuntimeVersion { get; }
bool IsLocalAssembly(string name); bool IsLocalAssembly(string name);
IDotNetType GetTypeByAssemblyQualifiedName(string name); IDotNetType GetTypeByAssemblyQualifiedName(string name);
IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IDotNetType ownerType, IDotNetType targetType); IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IDotNetType ownerType, IDotNetType targetType);

4
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs

@ -34,10 +34,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public KnownInfo(IDotNetTypeResolver resolver) public KnownInfo(IDotNetTypeResolver resolver)
{ {
switch (resolver.RuntimeVersion) { switch (resolver.RuntimeVersion) {
case "Net_2_0": case ICSharpCode.Decompiler.Metadata.TargetRuntime.Net_2_0:
LoadKnownAssemblies30(); LoadKnownAssemblies30();
break; break;
case "Net_4_0": case ICSharpCode.Decompiler.Metadata.TargetRuntime.Net_4_0:
LoadKnownAssemblies40(); LoadKnownAssemblies40();
break; break;
default: default:

12
ILSpy.sln

@ -24,6 +24,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\Te
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler.Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ILSpy.AddIn.csproj", "{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ILSpy.AddIn.csproj", "{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0A344E19-D1FC-4F4C-8883-0844AC669113}"
@ -65,6 +69,14 @@ Global
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.Build.0 = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU

Loading…
Cancel
Save