Restore events

This commit is contained in:
de4dot 2011-11-23 06:41:28 +01:00
parent 76420f4736
commit f7b117fe18
5 changed files with 213 additions and 3 deletions

View File

@ -352,6 +352,7 @@ namespace de4dot {
return;
var renamer = new Renamer(theFiles) {
RestorePropertiesFromNames = options.RestorePropsEvents,
RestoreEventsFromNames = options.RestorePropsEvents,
};
renamer.rename();
}

View File

@ -250,6 +250,10 @@ namespace de4dot.renamer {
allPropertyInfos[prop] = new PropertyInfo(prop);
}
public void add(EventDef evt) {
allEventInfos[evt] = new EventInfo(evt);
}
public void initialize(Modules modules) {
foreach (var type in modules.AllTypes) {
allTypeInfos[type] = new TypeInfo(type, this);
@ -261,7 +265,7 @@ namespace de4dot.renamer {
allFieldInfos[field] = new FieldInfo(field);
foreach (var evt in type.AllEvents)
allEventInfos[evt] = new EventInfo(evt);
add(evt);
foreach (var prop in type.AllProperties)
add(prop);

View File

@ -37,6 +37,8 @@ namespace de4dot.renamer {
public bool RenameGenericParams { get; set; }
public bool RestoreProperties { get; set; }
public bool RestorePropertiesFromNames { get; set; }
public bool RestoreEvents { get; set; }
public bool RestoreEventsFromNames { get; set; }
Modules modules = new Modules();
MemberInfos memberInfos = new MemberInfos();
@ -59,6 +61,9 @@ namespace de4dot.renamer {
RenameGenericParams = true;
RestoreProperties = true;
RestorePropertiesFromNames = true;
RestoreEvents = true;
RestoreEventsFromNames = true;
isDelegateClass = new DerivedFrom(delegateClasses);
mergeStateHelper = new MergeStateHelper(memberInfos);
@ -77,7 +82,7 @@ namespace de4dot.renamer {
renameTypeDefinitions();
renameTypeReferences();
modules.onTypesRenamed();
restoreProperties(scopes);
restorePropertiesAndEvents(scopes);
prepareRenameMemberDefinitions(scopes);
renameMemberDefinitions();
renameMemberReferences();
@ -445,10 +450,12 @@ namespace de4dot.renamer {
}
}
void restoreProperties(MethodNameScopes scopes) {
void restorePropertiesAndEvents(MethodNameScopes scopes) {
var allScopes = scopes.getAllScopes();
restoreVirtualProperties(allScopes);
restorePropertiesFromNames(allScopes);
restoreVirtualEvents(allScopes);
restoreEventsFromNames(allScopes);
}
void restoreVirtualProperties(IEnumerable<MethodNameScope> allScopes) {
@ -601,6 +608,182 @@ namespace de4dot.renamer {
return propDef;
}
void restoreVirtualEvents(IEnumerable<MethodNameScope> allScopes) {
if (!RestoreEvents)
return;
foreach (var scope in allScopes)
restoreVirtualEvents(scope);
}
enum EventMethodType {
None,
Other,
Adder,
Remover,
Raiser,
}
void restoreVirtualEvents(MethodNameScope scope) {
if (scope.Methods.Count <= 1 || !scope.hasEvent())
return;
EventMethodType methodType = EventMethodType.None;
EventDef evt = null;
List<MethodDef> missingEvents = null;
foreach (var method in scope.Methods) {
if (method.Event == null) {
if (missingEvents == null)
missingEvents = new List<MethodDef>();
missingEvents.Add(method);
}
else if (evt == null) {
evt = method.Event;
if (evt.AddMethod == method)
methodType = EventMethodType.Adder;
else if (evt.RemoveMethod == method)
methodType = EventMethodType.Remover;
else if (evt.RaiseMethod == method)
methodType = EventMethodType.Raiser;
else
methodType = EventMethodType.Other;
}
}
if (evt == null)
return; // Should never happen
if (missingEvents == null)
return;
foreach (var method in missingEvents) {
if (!method.Owner.HasModule)
continue;
switch (methodType) {
case EventMethodType.Adder:
createEventAdder(evt.EventDefinition.Name, method);
break;
case EventMethodType.Remover:
createEventRemover(evt.EventDefinition.Name, method);
break;
}
}
}
void restoreEventsFromNames(IEnumerable<MethodNameScope> allScopes) {
if (!RestoreEventsFromNames)
return;
foreach (var scope in allScopes) {
var scopeMethod = scope.Methods[0];
var methodName = scopeMethod.MethodDefinition.Name;
bool onlyRenamableMethods = !scope.hasNonRenamableMethod();
if (Utils.StartsWith(methodName, "add_", StringComparison.Ordinal)) {
var eventName = methodName.Substring(4);
foreach (var method in scope.Methods) {
if (onlyRenamableMethods && !memberInfos.type(method.Owner).NameChecker.isValidEventName(eventName))
continue;
createEventAdder(eventName, method);
}
}
else if (Utils.StartsWith(methodName, "remove_", StringComparison.Ordinal)) {
var eventName = methodName.Substring(7);
foreach (var method in scope.Methods) {
if (onlyRenamableMethods && !memberInfos.type(method.Owner).NameChecker.isValidEventName(eventName))
continue;
createEventRemover(eventName, method);
}
}
}
foreach (var type in modules.AllTypes) {
foreach (var method in type.AllMethodsSorted) {
if (method.isVirtual())
continue; // Virtual methods are in allScopes, so already fixed above
if (method.Event != null)
continue;
var methodName = method.MethodDefinition.Name;
if (Utils.StartsWith(methodName, "add_", StringComparison.Ordinal))
createEventAdder(methodName.Substring(4), method);
else if (Utils.StartsWith(methodName, "remove_", StringComparison.Ordinal))
createEventRemover(methodName.Substring(7), method);
}
}
}
EventDef createEventAdder(string name, MethodDef eventMethod) {
if (string.IsNullOrEmpty(name))
return null;
var ownerType = eventMethod.Owner;
if (!ownerType.HasModule)
return null;
if (eventMethod.Event != null)
return null;
var method = eventMethod.MethodDefinition;
var eventDef = createEvent(ownerType, name, getEventType(method));
if (eventDef == null)
return null;
if (eventDef.AddMethod != null)
return null;
Log.v("Restoring event adder {0} ({1:X8}), Event: {2} ({3:X8})",
eventMethod,
eventMethod.MethodDefinition.MetadataToken.ToInt32(),
eventDef.EventDefinition,
eventDef.EventDefinition.MetadataToken.ToInt32());
eventDef.EventDefinition.AddMethod = eventMethod.MethodDefinition;
eventDef.AddMethod = eventMethod;
eventMethod.Event = eventDef;
return eventDef;
}
EventDef createEventRemover(string name, MethodDef eventMethod) {
if (string.IsNullOrEmpty(name))
return null;
var ownerType = eventMethod.Owner;
if (!ownerType.HasModule)
return null;
if (eventMethod.Event != null)
return null;
var method = eventMethod.MethodDefinition;
var eventDef = createEvent(ownerType, name, getEventType(method));
if (eventDef == null)
return null;
if (eventDef.RemoveMethod != null)
return null;
Log.v("Restoring event remover {0} ({1:X8}), Event: {2} ({3:X8})",
eventMethod,
eventMethod.MethodDefinition.MetadataToken.ToInt32(),
eventDef.EventDefinition,
eventDef.EventDefinition.MetadataToken.ToInt32());
eventDef.EventDefinition.RemoveMethod = eventMethod.MethodDefinition;
eventDef.RemoveMethod = eventMethod;
eventMethod.Event = eventDef;
return eventDef;
}
TypeReference getEventType(MethodReference method) {
if (method.MethodReturnType.ReturnType.FullName != "System.Void")
return null;
if (method.Parameters.Count != 1)
return null;
return method.Parameters[0].ParameterType;
}
EventDef createEvent(TypeDef ownerType, string name, TypeReference eventType) {
if (string.IsNullOrEmpty(name) || eventType == null || eventType.FullName == "System.Void")
return null;
var newEvent = DotNetUtils.createEventDefinition(name, eventType);
var eventDef = ownerType.find(newEvent);
if (eventDef != null)
return eventDef;
eventDef = ownerType.create(newEvent);
memberInfos.add(eventDef);
Log.v("Restoring event: {0}", newEvent);
return eventDef;
}
void prepareRenameMemberDefinitions(MethodNameScopes scopes) {
Log.v("Renaming member definitions #1");

View File

@ -88,6 +88,14 @@ namespace de4dot.renamer.asmmodules {
return false;
}
public bool hasEvent() {
foreach (var method in methods) {
if (method.Event != null)
return true;
}
return false;
}
public override string ToString() {
return string.Format("{0} -- {1}", methods.Count, methods.Count > 0 ? methods[0].ToString() : "");
}

View File

@ -327,6 +327,10 @@ namespace de4dot.renamer.asmmodules {
return properties.find(pr);
}
public EventDef find(EventReference er) {
return events.find(er);
}
public PropertyDef create(PropertyDefinition newProp) {
if (find(newProp) != null)
throw new ApplicationException("Can't add a property when it's already been added");
@ -337,6 +341,16 @@ namespace de4dot.renamer.asmmodules {
return propDef;
}
public EventDef create(EventDefinition newEvent) {
if (find(newEvent) != null)
throw new ApplicationException("Can't add an event when it's already been added");
var eventDef = new EventDef(newEvent, this, events.Count);
add(eventDef);
TypeDefinition.Events.Add(newEvent);
return eventDef;
}
public void addMembers() {
var type = TypeDefinition;