Update symbol renamer to load referenced assemblies.

This way it's possible to use a rename-all regex (.*) without renaming
symbols that shouldn't be renamed (eg. methods that are defined in an
interface in a non-deobfuscated module, eg. Dispose()). A warning is
displayed if an assembly can't be loaded.
This commit is contained in:
de4dot 2011-11-03 06:43:33 +01:00
parent 2a967dc699
commit f351a09564
9 changed files with 300 additions and 116 deletions

View File

@ -21,13 +21,7 @@
/*
How to test it:
- Compile this assembly and the other test assembly
- Force rename of everything (set name regex to eg. asdfasdfasdf)
Make sure the code doesn't rename any types inheriting from
Delegate or MulticastDelegate. renameMembers() should
return before renaming the members
if (TypeDefinition.BaseType != null && TypeDefinition.BaseType.Name.Contains("Delegate"))
return;
...real code...
- Force rename of everything (set name regex to eg. .*)
- Run peverify /IL /MD on both files
- Decompile them and create a solution for both projects. I recommend using ILSpy.
- Compile with VS. If it fails to build, make sure the decompiler isn't buggy.

View File

@ -330,12 +330,29 @@ namespace de4dot.blocks {
}
public static string getCanonicalizedScopeName(IMetadataScope scope) {
var name = scope.Name.ToLowerInvariant();
if (scope is ModuleDefinition) {
if (name.EndsWith(".exe", StringComparison.Ordinal) || name.EndsWith(".dll", StringComparison.Ordinal))
name = name.Remove(name.Length - 4);
AssemblyNameReference asmRef = null;
switch (scope.MetadataScopeType) {
case MetadataScopeType.AssemblyNameReference:
asmRef = (AssemblyNameReference)scope;
break;
case MetadataScopeType.ModuleDefinition:
var module = (ModuleDefinition)scope;
if (module.Assembly != null)
asmRef = module.Assembly.Name;
break;
case MetadataScopeType.ModuleReference:
break;
default:
throw new ApplicationException(string.Format("Invalid scope type: {0}", scope.GetType()));
}
return name;
if (asmRef != null) {
if (asmRef.FullName.StartsWith("mscorlib,", StringComparison.Ordinal))
return "mscorlib";
return string.Format("{0}", asmRef.FullName.ToLowerInvariant());
}
return string.Format("{0}", scope.ToString().ToLowerInvariant());
}
public static bool compareScope(IMetadataScope a, IMetadataScope b) {

View File

@ -104,6 +104,7 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="renamer\DefinitionsRenamer.cs" />
<Compile Include="renamer\ExternalAssemblies.cs" />
<Compile Include="renamer\MemberRefFinder.cs" />
<Compile Include="renamer\MemberRefs.cs" />
<Compile Include="renamer\MemberRenameState.cs" />

View File

@ -23,7 +23,7 @@ using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.renamer {
// Renames all typedefs, methoddefs, eventdefs, fielddefs, and propdefs
// Renames typedefs, methoddefs, eventdefs, fielddefs, propdefs, and genparams
class DefinitionsRenamer : IResolver, IDefFinder {
// All types that don't derive from an existing type definition (most likely mscorlib
// isn't loaded, so this won't have just one element).
@ -31,7 +31,6 @@ namespace de4dot.renamer {
IList<TypeDef> nonNestedTypes;
IList<Module> modules = new List<Module>();
List<TypeDef> allTypes = new List<TypeDef>();
IDictionary<MethodDefinition, MethodDef> methodToMethodDef = new Dictionary<MethodDefinition, MethodDef>();
TypeNameState typeNameState;
ModulesDict modulesDict = new ModulesDict();
AssemblyHash assemblyHash = new AssemblyHash();
@ -114,7 +113,7 @@ namespace de4dot.renamer {
public void renameAll() {
if (modules.Count == 0)
return;
Log.n("Renaming all obfuscated names");
Log.n("Renaming all obfuscated symbols");
findAllMemberReferences();
resolveAllRefs();
initAllTypes();
@ -132,7 +131,7 @@ namespace de4dot.renamer {
foreach (var module in modules)
allTypes.AddRange(module.getAllTypes());
var typeToTypeDef = new Dictionary<TypeDefinition, TypeDef>();
var typeToTypeDef = new Dictionary<TypeDefinition, TypeDef>(allTypes.Count);
foreach (var typeDef in allTypes)
typeToTypeDef[typeDef.TypeDefinition] = typeDef;
@ -147,12 +146,11 @@ namespace de4dot.renamer {
var baseType = typeDef.TypeDefinition.BaseType;
if (baseType == null)
continue;
var baseTypeDefinition = resolve(baseType);
if (baseTypeDefinition == null)
continue;
var baseTypeDef = typeToTypeDef[baseTypeDefinition];
typeDef.baseType = new TypeInfo(baseType, baseTypeDef);
baseTypeDef.derivedTypes.Add(typeDef);
var baseTypeDef = resolve(baseType) ?? resolveOther(baseType);
if (baseTypeDef != null) {
typeDef.addBaseType(baseTypeDef, baseType);
baseTypeDef.derivedTypes.Add(typeDef);
}
}
// Initialize interfaces
@ -160,9 +158,9 @@ namespace de4dot.renamer {
if (typeDef.TypeDefinition.Interfaces == null)
continue;
foreach (var iface in typeDef.TypeDefinition.Interfaces) {
var ifaceTypeDefinition = resolve(iface);
if (ifaceTypeDefinition != null)
typeDef.interfaces.Add(new TypeInfo(iface, typeToTypeDef[ifaceTypeDefinition]));
var ifaceTypeDef = resolve(iface) ?? resolveOther(iface);
if (ifaceTypeDef != null)
typeDef.addInterface(ifaceTypeDef, iface);
}
}
@ -176,15 +174,11 @@ namespace de4dot.renamer {
}
nonNestedTypes = new List<TypeDef>(allTypesDict.Keys);
// So we can quickly look up MethodDefs
foreach (var typeDef in allTypes) {
foreach (var methodDef in typeDef.Methods)
methodToMethodDef[methodDef.MethodDefinition] = methodDef;
foreach (var typeDef in allTypes)
typeDef.defFinder = this;
}
foreach (var typeDef in allTypes) {
if (typeDef.baseType == null)
if (typeDef.baseType == null || !typeDef.baseType.typeDef.IsRenamable)
baseTypes.Add(typeDef);
}
}
@ -328,12 +322,48 @@ namespace de4dot.renamer {
renameEntryPoints();
}
Dictionary<TypeReferenceKey, TypeDef> otherTypesDict = new Dictionary<TypeReferenceKey, TypeDef>();
ExternalAssemblies externalAssemblies = new ExternalAssemblies();
TypeDef resolveOther(TypeReference type) {
if (type == null)
return null;
type = type.GetElementType();
TypeDef typeDef;
var key = new TypeReferenceKey(type);
if (otherTypesDict.TryGetValue(key, out typeDef))
return typeDef;
otherTypesDict[key] = null; // In case of a circular reference
TypeDefinition typeDefinition = externalAssemblies.resolve(type);
if (typeDefinition == null)
return null;
typeDef = new TypeDef(typeDefinition);
typeDef.MemberRenameState = new MemberRenameState();
typeDef.addMembers();
foreach (var iface in typeDef.TypeDefinition.Interfaces) {
var ifaceDef = resolveOther(iface);
if (ifaceDef == null)
continue;
typeDef.MemberRenameState.mergeRenamed(ifaceDef.MemberRenameState);
typeDef.addInterface(ifaceDef, iface);
}
var baseDef = resolveOther(typeDef.TypeDefinition.BaseType);
if (baseDef != null) {
typeDef.MemberRenameState.mergeRenamed(baseDef.MemberRenameState);
typeDef.addBaseType(baseDef, typeDef.TypeDefinition.BaseType);
}
typeDef.initializeVirtualMembers();
return otherTypesDict[key] = typeDef;
}
void renameEntryPoints() {
foreach (var module in modules) {
var entryPoint = module.ModuleDefinition.EntryPoint;
if (entryPoint == null)
continue;
var methodDef = findMethod(entryPoint);
var methodDef = resolve(entryPoint);
if (methodDef == null)
throw new ApplicationException(string.Format("Could not find entry point. Module: {0}, Method: {1}", module.ModuleDefinition.FullyQualifiedName, entryPoint));
if (!methodDef.MethodDefinition.IsStatic)
@ -402,7 +432,7 @@ namespace de4dot.renamer {
IEnumerable<InterfaceScopeInfo> getInterfaceScopeInfo(IEnumerable<TypeDef> baseTypes) {
foreach (var typeDef in baseTypes) {
yield return new InterfaceScopeInfo(typeDef, new List<TypeDef>(typeDef.getAllInterfaces()));
yield return new InterfaceScopeInfo(typeDef, new List<TypeDef>(typeDef.getAllRenamableInterfaces()));
}
}
@ -461,7 +491,7 @@ namespace de4dot.renamer {
return typeReference is ArrayType || typeReference is PointerType;
}
public TypeDefinition resolve(TypeReference typeReference) {
public TypeDef resolve(TypeReference typeReference) {
var modules = findModules(typeReference.Scope);
if (modules == null)
return null;
@ -475,7 +505,7 @@ namespace de4dot.renamer {
throw new ApplicationException(string.Format("Could not resolve TypeReference {0} ({1:X8})", typeReference, typeReference.MetadataToken.ToInt32()));
}
public MethodDefinition resolve(MethodReference methodReference) {
public MethodDef resolve(MethodReference methodReference) {
if (methodReference.DeclaringType == null)
return null;
var modules = findModules(methodReference.DeclaringType.Scope);
@ -491,7 +521,7 @@ namespace de4dot.renamer {
throw new ApplicationException(string.Format("Could not resolve MethodReference {0} ({1:X8})", methodReference, methodReference.MetadataToken.ToInt32()));
}
public FieldDefinition resolve(FieldReference fieldReference) {
public FieldDef resolve(FieldReference fieldReference) {
if (fieldReference.DeclaringType == null)
return null;
var modules = findModules(fieldReference.DeclaringType.Scope);
@ -508,21 +538,18 @@ namespace de4dot.renamer {
}
public MethodDef findMethod(MethodReference methodReference) {
var method = resolve(methodReference);
if (method == null)
return null;
return methodToMethodDef[method];
return resolve(methodReference);
}
public PropertyDef findProp(MethodReference methodReference) {
var methodDef = findMethod(methodReference);
var methodDef = resolve(methodReference);
if (methodDef == null)
return null;
return methodDef.Property;
}
public EventDef findEvent(MethodReference methodReference) {
var methodDef = findMethod(methodReference);
var methodDef = resolve(methodReference);
if (methodDef == null)
return null;
return methodDef.Event;

View File

@ -0,0 +1,79 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.renamer {
class ExternalAssembly {
AssemblyDefinition asmDef;
public ExternalAssembly(AssemblyDefinition asmDef) {
this.asmDef = asmDef;
}
public TypeDefinition resolve(TypeReference type) {
foreach (var module in asmDef.Modules) {
var typeDef = DotNetUtils.getType(module, type);
if (typeDef != null)
return typeDef;
}
return null;
}
}
// Loads assemblies that aren't renamed
class ExternalAssemblies {
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>();
ExternalAssembly load(TypeReference type) {
var asmFullName = DotNetUtils.getFullAssemblyName(type.Scope);
ExternalAssembly asm;
if (assemblies.TryGetValue(asmFullName, out asm))
return asm;
AssemblyDefinition asmDef = null;
try {
asmDef = GlobalAssemblyResolver.Instance.Resolve(asmFullName);
}
catch (ResolutionException) {
}
catch (AssemblyResolutionException) {
}
if (asmDef == null) {
// If we can't load it now, we can't load it later. Make sure above code returns null.
assemblies[asmFullName] = null;
Log.w("Could not load assembly {0}", asmFullName);
return null;
}
Log.v("Loaded assembly {0}", asmFullName);
return assemblies[asmFullName] = asm = new ExternalAssembly(asmDef);
}
public TypeDefinition resolve(TypeReference type) {
var asm = load(type);
if (asm == null)
return null;
return asm.resolve(type);
}
}
}

View File

@ -69,6 +69,10 @@ namespace de4dot.renamer {
list.Add(new GenericParamDef(param, i++));
return list;
}
public override string ToString() {
return MemberReference != null ? MemberReference.ToString() : null;
}
}
class FieldDef : Ref {
@ -312,6 +316,16 @@ namespace de4dot.renamer {
get { return genericParams; }
}
public bool IsRenamable {
get { return module != null; }
}
bool IsDelegate { get; set; }
public TypeDef(TypeDefinition typeDefinition)
: this(typeDefinition, null) {
}
public TypeDef(TypeDefinition typeDefinition, Module module, int index = 0)
: base(typeDefinition, null, index) {
this.module = module;
@ -330,8 +344,18 @@ namespace de4dot.renamer {
get { return methods.getAll(); }
}
// Called when all members (events, fields, props, methods) have been added
public void membersAdded() {
public void addMembers() {
var type = TypeDefinition;
for (int i = 0; i < type.Events.Count; i++)
add(new EventDef(type.Events[i], this, i));
for (int i = 0; i < type.Fields.Count; i++)
add(new FieldDef(type.Fields[i], this, i));
for (int i = 0; i < type.Methods.Count; i++)
add(new MethodDef(type.Methods[i], this, i));
for (int i = 0; i < type.Properties.Count; i++)
add(new PropertyDef(type.Properties[i], this, i));
foreach (var propDef in properties.getAll()) {
foreach (var method in propDef.methodDefinitions()) {
var methodDef = find(method);
@ -351,6 +375,19 @@ namespace de4dot.renamer {
}
}
public void addInterface(TypeDef ifaceDef, TypeReference iface) {
if (ifaceDef == null || iface == null)
return;
interfaces.Add(new TypeInfo(iface, ifaceDef));
}
public void addBaseType(TypeDef baseDef, TypeReference baseRef) {
if (baseDef == null || baseRef == null)
return;
baseType = new TypeInfo(baseRef, baseDef);
IsDelegate = baseRef.FullName == "System.Delegate" || baseRef.FullName == "System.MulticastDelegate";
}
// Called when all types have been renamed
public void onTypesRenamed() {
events.onTypesRenamed();
@ -372,6 +409,13 @@ namespace de4dot.renamer {
}
}
public IEnumerable<TypeDef> getAllRenamableInterfaces() {
foreach (var iface in getAllInterfaces()) {
if (iface.IsRenamable)
yield return iface;
}
}
public void add(EventDef e) {
events.add(e);
}
@ -562,6 +606,22 @@ namespace de4dot.renamer {
}
}
public void initializeVirtualMembers() {
expandGenerics();
foreach (var propDef in properties.getSorted()) {
if (propDef.isVirtual())
MemberRenameState.add(propDef);
}
foreach (var eventDef in events.getSorted()) {
if (eventDef.isVirtual())
MemberRenameState.add(eventDef);
}
foreach (var methodDef in methods.getSorted()) {
if (methodDef.isVirtual())
MemberRenameState.add(methodDef);
}
}
public void prepareRenameMembers() {
if (prepareRenameMembersCalled)
return;
@ -572,19 +632,33 @@ namespace de4dot.renamer {
if (baseType != null)
baseType.typeDef.prepareRenameMembers();
if (baseType != null)
if (MemberRenameState == null)
MemberRenameState = baseType.typeDef.MemberRenameState.clone();
MemberRenameState.variableNameState.IsValidName = module.IsValidName;
// For each base type and interface it implements, add all its virtual methods, props,
// and events if the type is a non-renamable type (eg. it's from mscorlib or some other
// non-deobfuscated assembly).
if (IsRenamable) {
foreach (var ifaceInfo in interfaces) {
if (!ifaceInfo.typeDef.IsRenamable)
MemberRenameState.mergeRenamed(ifaceInfo.typeDef.MemberRenameState);
}
if (baseType != null && !baseType.typeDef.IsRenamable)
MemberRenameState.mergeRenamed(baseType.typeDef.MemberRenameState);
}
if (InterfaceScopeState != null)
MemberRenameState.mergeRenamed(InterfaceScopeState);
expandGenerics();
prepareRenameFields(); // must be first
prepareRenameProperties();
prepareRenameEvents();
prepareRenameMethods(); // must be last
if (IsRenamable) {
MemberRenameState.variableNameState.IsValidName = module.IsValidName;
prepareRenameFields(); // must be first
prepareRenameProperties();
prepareRenameEvents();
prepareRenameMethods(); // must be last
}
}
// Replaces the generic params with the generic args, if any
@ -851,13 +925,31 @@ namespace de4dot.renamer {
if (methodDef.Renamed)
return;
methodDef.Renamed = true;
bool canRenameName = true;
if (IsDelegate && methodDef.isVirtual()) {
switch (methodDef.MethodDefinition.Name) {
case "GetMethodImpl":
case "CombineImpl":
case "DynamicInvokeImpl":
case "GetInvocationList":
case "RemoveImpl":
case "Invoke":
case "BeginInvoke":
case "EndInvoke":
canRenameName = false;
break;
}
}
var variableNameState = MemberRenameState.variableNameState;
bool isVirtual = methodDef.isVirtual();
var nameCreator = getMethodNameCreator(methodDef, suggestedName);
if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName))
methodDef.NewName = nameCreator.newName();
if (canRenameName) {
var nameCreator = getMethodNameCreator(methodDef, suggestedName);
if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName))
methodDef.NewName = nameCreator.newName();
}
if (methodDef.ParamDefs.Count > 0) {
var newVariableNameState = variableNameState.clone();

View File

@ -27,6 +27,10 @@ namespace de4dot.renamer {
public Dictionary<EventReferenceKey, EventRef> events = new Dictionary<EventReferenceKey, EventRef>();
public Dictionary<MethodReferenceKey, MethodRef> methods = new Dictionary<MethodReferenceKey, MethodRef>();
public MemberRenameState()
: this(null) {
}
public MemberRenameState(VariableNameState variableNameState) {
this.variableNameState = variableNameState;
}
@ -78,7 +82,7 @@ namespace de4dot.renamer {
}
public MemberRenameState clone() {
var rv = new MemberRenameState(variableNameState.clone());
var rv = new MemberRenameState(variableNameState == null ? null : variableNameState.clone());
rv.properties = new Dictionary<PropertyReferenceKey, PropertyRef>(properties);
rv.events = new Dictionary<EventReferenceKey, EventRef>(events);
rv.methods = new Dictionary<MethodReferenceKey, MethodRef>(methods);
@ -86,7 +90,7 @@ namespace de4dot.renamer {
}
public MemberRenameState cloneVariables() {
var rv = new MemberRenameState(variableNameState.clone());
var rv = new MemberRenameState(variableNameState == null ? null : variableNameState.clone());
rv.properties = properties;
rv.events = events;
rv.methods = methods;

View File

@ -17,16 +17,15 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.renamer {
interface IResolver {
TypeDefinition resolve(TypeReference typeReference);
MethodDefinition resolve(MethodReference methodReference);
FieldDefinition resolve(FieldReference fieldReference);
TypeDef resolve(TypeReference typeReference);
MethodDef resolve(MethodReference methodReference);
FieldDef resolve(FieldReference fieldReference);
}
interface IDefFinder {
@ -212,9 +211,9 @@ namespace de4dot.renamer {
}
public EventDef find(EventReference eventReference) {
EventDef propDef;
tokenToEventDef.TryGetValue(new ScopeAndTokenKey(eventReference), out propDef);
return propDef;
EventDef eventDef;
tokenToEventDef.TryGetValue(new ScopeAndTokenKey(eventReference), out eventDef);
return eventDef;
}
public void add(EventDef eventDef) {

View File

@ -199,36 +199,16 @@ namespace de4dot.renamer {
allTypes.add(typeDef);
allTypesList.Add(typeDef);
if (type.Events != null) {
for (int i = 0; i < type.Events.Count; i++) {
var ev = type.Events[i];
typeDef.add(new EventDef(ev, typeDef, i));
memberRefFinder.removeEventDefinition(ev);
}
}
if (type.Fields != null) {
for (int i = 0; i < type.Fields.Count; i++) {
var field = type.Fields[i];
typeDef.add(new FieldDef(field, typeDef, i));
memberRefFinder.removeFieldDefinition(field);
}
}
if (type.Methods != null) {
for (int i = 0; i < type.Methods.Count; i++) {
var method = type.Methods[i];
typeDef.add(new MethodDef(method, typeDef, i));
memberRefFinder.removeMethodDefinition(method);
}
}
if (type.Properties != null) {
for (int i = 0; i < type.Properties.Count; i++) {
var property = type.Properties[i];
typeDef.add(new PropertyDef(property, typeDef, i));
memberRefFinder.removePropertyDefinition(property);
}
}
typeDef.addMembers();
typeDef.membersAdded();
foreach (var ev in type.Events)
memberRefFinder.removeEventDefinition(ev);
foreach (var field in type.Fields)
memberRefFinder.removeFieldDefinition(field);
foreach (var method in type.Methods)
memberRefFinder.removeMethodDefinition(method);
foreach (var property in type.Properties)
memberRefFinder.removePropertyDefinition(property);
}
// Add all nested types to the correct TypeDef's types list
@ -265,21 +245,21 @@ namespace de4dot.renamer {
public void resolveAllRefs(IResolver resolver) {
foreach (var typeRef in memberRefFinder.typeReferences.Keys) {
var typeDefinition = resolver.resolve(typeRef);
if (typeDefinition != null)
typeRefsToRename.Add(new RefToDef<TypeReference, TypeDefinition>(typeRef, typeDefinition));
var typeDef = resolver.resolve(typeRef);
if (typeDef != null)
typeRefsToRename.Add(new RefToDef<TypeReference, TypeDefinition>(typeRef, typeDef.TypeDefinition));
}
foreach (var methodRef in memberRefFinder.methodReferences.Keys) {
var methodDefinition = resolver.resolve(methodRef);
if (methodDefinition != null)
methodRefsToRename.Add(new RefToDef<MethodReference, MethodDefinition>(methodRef, methodDefinition));
var methodDef = resolver.resolve(methodRef);
if (methodDef != null)
methodRefsToRename.Add(new RefToDef<MethodReference, MethodDefinition>(methodRef, methodDef.MethodDefinition));
}
foreach (var fieldRef in memberRefFinder.fieldReferences.Keys) {
var fieldDefinition = resolver.resolve(fieldRef);
if (fieldDefinition != null)
fieldRefsToRename.Add(new RefToDef<FieldReference, FieldDefinition>(fieldRef, fieldDefinition));
var fieldDef = resolver.resolve(fieldRef);
if (fieldDef != null)
fieldRefsToRename.Add(new RefToDef<FieldReference, FieldDefinition>(fieldRef, fieldDef.FieldDefinition));
}
}
@ -319,31 +299,22 @@ namespace de4dot.renamer {
return type.ElementType;
}
public TypeDefinition resolve(TypeReference typeReference) {
var typeDef = this.allTypes.find(getNonGenericTypeReference(typeReference));
if (typeDef == null)
return null;
return typeDef.TypeDefinition;
public TypeDef resolve(TypeReference typeReference) {
return this.allTypes.find(getNonGenericTypeReference(typeReference));
}
public MethodDefinition resolve(MethodReference methodReference) {
public MethodDef resolve(MethodReference methodReference) {
var typeDef = this.allTypes.find(getNonGenericTypeReference(methodReference.DeclaringType));
if (typeDef == null)
return null;
var methodDef = typeDef.find(methodReference);
if (methodDef == null)
return null;
return methodDef.MethodDefinition;
return typeDef.find(methodReference);
}
public FieldDefinition resolve(FieldReference fieldReference) {
public FieldDef resolve(FieldReference fieldReference) {
var typeDef = this.allTypes.find(getNonGenericTypeReference(fieldReference.DeclaringType));
if (typeDef == null)
return null;
var fieldDef = typeDef.find(fieldReference);
if (fieldDef == null)
return null;
return fieldDef.FieldDefinition;
return typeDef.find(fieldReference);
}
}
}