Use type cache to look up types (huge speedup in DNR code)
This commit is contained in:
parent
f342a481a9
commit
ade1720d32
|
@ -23,6 +23,57 @@ using Mono.Cecil;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
|
|
||||||
namespace de4dot.blocks {
|
namespace de4dot.blocks {
|
||||||
|
class TypeCache {
|
||||||
|
ModuleDefinition module;
|
||||||
|
Dictionary<TypeReferenceKey, TypeDefinition> typeRefToDef = new Dictionary<TypeReferenceKey, TypeDefinition>();
|
||||||
|
|
||||||
|
public TypeCache(ModuleDefinition module) {
|
||||||
|
this.module = module;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
foreach (var type in module.GetTypes()) {
|
||||||
|
var key = new TypeReferenceKey(type);
|
||||||
|
typeRefToDef[key] = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeDefinition lookup(TypeReference typeReference) {
|
||||||
|
if (typeReference is TypeDefinition)
|
||||||
|
return (TypeDefinition)typeReference;
|
||||||
|
TypeDefinition typeDefinition;
|
||||||
|
typeRefToDef.TryGetValue(new TypeReferenceKey(typeReference), out typeDefinition);
|
||||||
|
return typeDefinition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TypeCaches {
|
||||||
|
Dictionary<ModuleDefinition, TypeCache> typeCaches = new Dictionary<ModuleDefinition, TypeCache>();
|
||||||
|
|
||||||
|
// Should be called when the whole module is reloaded or when a lot of types have been
|
||||||
|
// modified (eg. renamed)
|
||||||
|
public void invalidate(ModuleDefinition module) {
|
||||||
|
if (module == null)
|
||||||
|
return;
|
||||||
|
typeCaches.Remove(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call this to invalidate all modules
|
||||||
|
public void invalidateAll() {
|
||||||
|
typeCaches.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeDefinition lookup(ModuleDefinition module, TypeReference typeReference) {
|
||||||
|
if (typeReference is TypeDefinition)
|
||||||
|
return (TypeDefinition)typeReference;
|
||||||
|
TypeCache typeCache;
|
||||||
|
if (!typeCaches.TryGetValue(module, out typeCache))
|
||||||
|
typeCaches[module] = typeCache = new TypeCache(module);
|
||||||
|
return typeCache.lookup(typeReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class CallCounter {
|
public class CallCounter {
|
||||||
Dictionary<MethodReferenceAndDeclaringTypeKey, int> calls = new Dictionary<MethodReferenceAndDeclaringTypeKey, int>();
|
Dictionary<MethodReferenceAndDeclaringTypeKey, int> calls = new Dictionary<MethodReferenceAndDeclaringTypeKey, int>();
|
||||||
|
|
||||||
|
@ -78,6 +129,8 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DotNetUtils {
|
public static class DotNetUtils {
|
||||||
|
public static readonly TypeCaches typeCaches = new TypeCaches();
|
||||||
|
|
||||||
public static bool isLdcI4(Instruction instruction) {
|
public static bool isLdcI4(Instruction instruction) {
|
||||||
return isLdcI4(instruction.OpCode.Code);
|
return isLdcI4(instruction.OpCode.Code);
|
||||||
}
|
}
|
||||||
|
@ -309,11 +362,7 @@ namespace de4dot.blocks {
|
||||||
return null;
|
return null;
|
||||||
if (typeReference is TypeDefinition)
|
if (typeReference is TypeDefinition)
|
||||||
return (TypeDefinition)typeReference;
|
return (TypeDefinition)typeReference;
|
||||||
foreach (var type in module.GetTypes()) {
|
return typeCaches.lookup(module, typeReference);
|
||||||
if (MemberReferenceHelper.compareTypes(type, typeReference))
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FieldDefinition getField(ModuleDefinition module, FieldReference field) {
|
public static FieldDefinition getField(ModuleDefinition module, FieldReference field) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using Mono.MyStuff;
|
using Mono.MyStuff;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot {
|
namespace de4dot {
|
||||||
class AssemblyModule {
|
class AssemblyModule {
|
||||||
|
@ -51,6 +52,7 @@ namespace de4dot {
|
||||||
public ModuleDefinition reload(byte[] newModuleData, Dictionary<uint, DumpedMethod> dumpedMethods) {
|
public ModuleDefinition reload(byte[] newModuleData, Dictionary<uint, DumpedMethod> dumpedMethods) {
|
||||||
var assemblyResolver = AssemblyResolver.Instance;
|
var assemblyResolver = AssemblyResolver.Instance;
|
||||||
assemblyResolver.removeModule(module);
|
assemblyResolver.removeModule(module);
|
||||||
|
DotNetUtils.typeCaches.invalidate(module);
|
||||||
this.dumpedMethods = dumpedMethods;
|
this.dumpedMethods = dumpedMethods;
|
||||||
|
|
||||||
var readerParameters = new ReaderParameters(ReadingMode.Deferred);
|
var readerParameters = new ReaderParameters(ReadingMode.Deferred);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Mono.Cecil;
|
||||||
|
using de4dot.blocks;
|
||||||
using de4dot.renamer;
|
using de4dot.renamer;
|
||||||
using de4dot.deobfuscators;
|
using de4dot.deobfuscators;
|
||||||
using de4dot.AssemblyClient;
|
using de4dot.AssemblyClient;
|
||||||
|
@ -70,9 +72,14 @@ namespace de4dot {
|
||||||
deobfuscateAll();
|
deobfuscateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeModule(ModuleDefinition module) {
|
||||||
|
AssemblyResolver.Instance.removeModule(module);
|
||||||
|
DotNetUtils.typeCaches.invalidate(module);
|
||||||
|
}
|
||||||
|
|
||||||
void detectObfuscators() {
|
void detectObfuscators() {
|
||||||
foreach (var file in loadAllFiles()) {
|
foreach (var file in loadAllFiles()) {
|
||||||
AssemblyResolver.Instance.removeModule(file.ModuleDefinition);
|
removeModule(file.ModuleDefinition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +95,7 @@ namespace de4dot {
|
||||||
|
|
||||||
file.save();
|
file.save();
|
||||||
|
|
||||||
AssemblyResolver.Instance.removeModule(file.ModuleDefinition);
|
removeModule(file.ModuleDefinition);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Log.w("Could not deobfuscate {0}. Use -v to see stack trace", file.Filename);
|
Log.w("Could not deobfuscate {0}. Use -v to see stack trace", file.Filename);
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace de4dot.renamer {
|
||||||
renameMemberDefinitions();
|
renameMemberDefinitions();
|
||||||
renameMemberReferences();
|
renameMemberReferences();
|
||||||
renameResources();
|
renameResources();
|
||||||
|
DotNetUtils.typeCaches.invalidateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initAllTypes() {
|
void initAllTypes() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user