Browse Source

Fix ConnectMethodDecompiler

pull/728/merge
Siegfried Pammer 10 years ago
parent
commit
bc7032a869
  1. 10
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  2. 155
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  3. 4
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

10
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -3,12 +3,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
@ -110,7 +110,7 @@ namespace ILSpy.BamlDecompiler
} }
} }
static void RemoveConnectionIds(XElement element, Dictionary<int, EventRegistration[]> eventMappings) static void RemoveConnectionIds(XElement element, Dictionary<long, EventRegistration[]> eventMappings)
{ {
foreach (var child in element.Elements()) foreach (var child in element.Elements())
RemoveConnectionIds(child, eventMappings); RemoveConnectionIds(child, eventMappings);
@ -123,12 +123,8 @@ namespace ILSpy.BamlDecompiler
var map = eventMappings[id]; var map = eventMappings[id];
foreach (var entry in map) { foreach (var entry in map) {
string xmlns = ""; // TODO : implement xmlns resolver! string xmlns = ""; // TODO : implement xmlns resolver!
if (entry.IsAttached) {
addableAttrs.Add(new XAttribute(xmlns + entry.AttachSourceType.Name + "." + entry.EventName, entry.MethodName));
} else {
addableAttrs.Add(new XAttribute(xmlns + entry.EventName, entry.MethodName)); addableAttrs.Add(new XAttribute(xmlns + entry.EventName, entry.MethodName));
} }
}
removableAttrs.Add(attr); removableAttrs.Add(attr);
} }
} }

155
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -6,6 +6,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
namespace ILSpy.BamlDecompiler namespace ILSpy.BamlDecompiler
@ -16,8 +20,6 @@ namespace ILSpy.BamlDecompiler
sealed class EventRegistration sealed class EventRegistration
{ {
public string EventName, MethodName; public string EventName, MethodName;
public TypeDefinition AttachSourceType;
public bool IsAttached;
} }
/// <summary> /// <summary>
@ -32,141 +34,132 @@ namespace ILSpy.BamlDecompiler
this.assembly = assembly; this.assembly = assembly;
} }
public Dictionary<int, EventRegistration[]> DecompileEventMappings(string fullTypeName) public Dictionary<long, EventRegistration[]> DecompileEventMappings(string fullTypeName)
{ {
var result = new Dictionary<int, EventRegistration[]>(); var result = new Dictionary<long, EventRegistration[]>();
TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName); TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName);
if (type == null) if (type == null)
return result; return result;
MethodDefinition def = null; MethodDefinition method = null;
foreach (var method in type.Methods) { foreach (var m in type.Methods) {
if (method.Name == "System.Windows.Markup.IComponentConnector.Connect") { if (m.Name == "System.Windows.Markup.IComponentConnector.Connect") {
def = method; method = m;
break; break;
} }
} }
if (def == null) if (method == null)
return result; return result;
throw new NotImplementedException();
/*
// decompile method and optimize the switch // decompile method and optimize the switch
ILBlock ilMethod = new ILBlock(); var typeSystem = new DecompilerTypeSystem(method.Module);
ILAstBuilder astBuilder = new ILAstBuilder(); ILFunction function = ILFunction.Read(typeSystem, method);
ILAstOptimizer optimizer = new ILAstOptimizer();
var context = new DecompilerContext(type.Module) { CurrentMethod = def, CurrentType = type };
ilMethod.Body = astBuilder.Build(def, true, context);
optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.RemoveRedundantCode3);
ILSwitch ilSwitch = ilMethod.Body.OfType<ILSwitch>().FirstOrDefault(); var context = new ILTransformContext { Settings = new DecompilerSettings(), TypeSystem = typeSystem };
ILCondition condition = ilMethod.Body.OfType<ILCondition>().FirstOrDefault(); function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);
var block = function.Body.Children.OfType<Block>().First();
var ilSwitch = block.Children.OfType<SwitchInstruction>().FirstOrDefault();
if (ilSwitch != null) { if (ilSwitch != null) {
foreach (var caseBlock in ilSwitch.CaseBlocks) { foreach (var section in ilSwitch.Sections) {
if (caseBlock.Values == null) var events = FindEvents(section.Body);
foreach (long id in section.Labels.Range())
result.Add(id, events);
}
} else {
foreach (var ifInst in function.Descendants.OfType<IfInstruction>()) {
var comp = ifInst.Condition as Comp;
if (comp.Kind != ComparisonKind.Inequality && comp.Kind != ComparisonKind.Equality)
continue; continue;
var events = FindEvents(caseBlock); int id;
foreach (int id in caseBlock.Values) if (!comp.Right.MatchLdcI4(out id))
continue;
var events = FindEvents(comp.Kind == ComparisonKind.Inequality ? ifInst.FalseInst : ifInst.TrueInst);
result.Add(id, events); result.Add(id, events);
} }
} else if (condition != null) {
result.Add(1, FindEvents(condition.FalseBlock));
} }
return result;*/ return result;
} }
/*
EventRegistration[] FindEvents(ILBlock block) EventRegistration[] FindEvents(ILInstruction inst)
{ {
var events = new List<EventRegistration>(); var events = new List<EventRegistration>();
foreach (var node in block.Body) { if (inst is Block) {
var expr = node as ILExpression; foreach (var node in ((Block)inst).Instructions) {
string eventName, handlerName; FindEvents(node, events);
TypeDefinition attachSource; }
if (IsAddEvent(expr, out eventName, out handlerName)) FindEvents(((Block)inst).FinalInstruction, events);
events.Add(new EventRegistration { } else {
EventName = eventName, FindEvents(inst, events);
MethodName = handlerName
});
else if (IsAddAttachedEvent(expr, out eventName, out handlerName, out attachSource))
events.Add(new EventRegistration {
EventName = eventName,
MethodName = handlerName,
AttachSourceType = attachSource,
IsAttached = true
});
} }
return events.ToArray(); return events.ToArray();
} }
bool IsAddAttachedEvent(ILExpression expr, out string eventName, out string handlerName, out TypeDefinition attachSource) void FindEvents(ILInstruction inst, List<EventRegistration> events)
{
CallInstruction call = inst as CallInstruction;
if (call == null || call.OpCode == OpCode.NewObj)
return;
string eventName, handlerName;
if (IsAddEvent(call, out eventName, out handlerName) || IsAddAttachedEvent(call, out eventName, out handlerName))
events.Add(new EventRegistration { EventName = eventName, MethodName = handlerName });
}
bool IsAddAttachedEvent(CallInstruction call, out string eventName, out string handlerName)
{ {
eventName = ""; eventName = "";
handlerName = ""; handlerName = "";
attachSource = null;
if (expr == null || !(expr.Code == ILCode.Callvirt || expr.Code == ILCode.Call))
return false;
if (expr.Operand is MethodReference && expr.Arguments.Count == 3) { if (call.Arguments.Count == 3) {
var addMethod = expr.Operand as MethodReference; var addMethod = call.Method;
if (addMethod.Name != "AddHandler" || addMethod.Parameters.Count != 2) if (addMethod.Name != "AddHandler" || addMethod.Parameters.Count != 2)
return false; return false;
var arg = expr.Arguments[1]; IField field;
if (arg.Code != ILCode.Ldsfld || arg.Arguments.Any() || !(arg.Operand is FieldReference)) if (!call.Arguments[1].MatchLdsFld(out field))
return false; return false;
FieldReference fldRef = (FieldReference)arg.Operand; eventName = field.DeclaringType.Name + "." + field.Name;
attachSource = fldRef.DeclaringType.Resolve(); if (eventName.EndsWith("Event", StringComparison.Ordinal) && eventName.Length > "Event".Length)
eventName = fldRef.Name;
if (eventName.EndsWith("Event") && eventName.Length > "Event".Length)
eventName = eventName.Remove(eventName.Length - "Event".Length); eventName = eventName.Remove(eventName.Length - "Event".Length);
var arg1 = expr.Arguments[2]; var newObj = call.Arguments[2] as NewObj;
if (arg1.Code != ILCode.Newobj) if (newObj == null || newObj.Arguments.Count != 2)
return false; return false;
var arg2 = arg1.Arguments[1]; var ldftn = newObj.Arguments[1];
if (arg2.Code != ILCode.Ldftn && arg2.Code != ILCode.Ldvirtftn) if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn)
return false; return false;
if (arg2.Operand is MethodReference) { handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name;
var m = arg2.Operand as MethodReference;
handlerName = m.Name;
return true; return true;
} }
}
return false; return false;
} }
bool IsAddEvent(ILExpression expr, out string eventName, out string handlerName) bool IsAddEvent(CallInstruction call, out string eventName, out string handlerName)
{ {
eventName = ""; eventName = "";
handlerName = ""; handlerName = "";
if (expr == null || !(expr.Code == ILCode.Callvirt || expr.Code == ILCode.Call)) if (call.Arguments.Count == 2) {
var addMethod = call.Method;
if (!addMethod.Name.StartsWith("add_", StringComparison.Ordinal) || addMethod.Parameters.Count != 1)
return false; return false;
if (expr.Operand is MethodReference && expr.Arguments.Count == 2) {
var addMethod = expr.Operand as MethodReference;
if (addMethod.Name.StartsWith("add_") && addMethod.Parameters.Count == 1)
eventName = addMethod.Name.Substring("add_".Length); eventName = addMethod.Name.Substring("add_".Length);
var arg = expr.Arguments[1]; var newObj = call.Arguments[1] as NewObj;
if (arg.Code != ILCode.Newobj || arg.Arguments.Count != 2) if (newObj == null || newObj.Arguments.Count != 2)
return false; return false;
var arg1 = arg.Arguments[1]; var ldftn = newObj.Arguments[1];
if (arg1.Code != ILCode.Ldftn && arg1.Code != ILCode.Ldvirtftn) if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn)
return false; return false;
if (arg1.Operand is MethodReference) { handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name;
var m = arg1.Operand as MethodReference;
handlerName = m.Name;
return true; return true;
} }
}
return false; return false;
}*/ }
} }
} }

4
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -131,6 +131,10 @@
<Name>Mono.Cecil</Name> <Name>Mono.Cecil</Name>
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj"> <ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project> <Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name> <Name>ICSharpCode.TreeView</Name>

Loading…
Cancel
Save