ソースを解析する際に、人力でコードを追う方法以外に、
DLL のメタ情報から欲しい情報を抽出出来ないかと調べた所、
↓のような素敵なライブラリが合ったので試しに使ってみました。
github.com
www.nuget.org
まずは、nuget にて dnlib をインストール。
ライブラリ自体は dll への read/write 両方とも出来るようですが、
一先ず、色々と抽出したいので read に絞って実験。
private static IEnumerable<Tuple<MethodDef, IMethodDefOrRef>> GetUsedMethodsAndProperties(IEnumerable<string> moduleFiles) { // func を再帰呼び出しする為に定義と実装を分離する。(ここは定義) Func<MethodDef, HashSet<MethodDef>, IEnumerable<Tuple<MethodDef, IMethodDefOrRef>>>? func = null; // ここは実装 func = (method, hashSet) => { var result = new List<Tuple<MethodDef, IMethodDefOrRef>>(); // 無限ループになる可能性がある為、1度処理したメソッドは処理しない。 if (method == null || hashSet.Contains(method)) return result; hashSet.Add(method); var methodBody = method.Body; if (methodBody == null) return result; foreach (var calledMethodOrProperty in methodBody.Instructions .Where(m => m.Operand is IMethodDefOrRef) .Select(m => (IMethodDefOrRef)m.Operand)) { // 出力したい条件を↓に指定する。 // ToString を呼んでいる処理を抽出 if (calledMethodOrProperty.Name.Contains("ToString")) result.Add(Tuple.Create(method, calledMethodOrProperty)); result.AddRange(func!(calledMethodOrProperty.ResolveMethodDef(), hashSet)); } return result; }; var h = new HashSet<MethodDef>(); return moduleFiles .Select(m => ModuleDefMD.Load(m)) .SelectMany(m => m.GetTypes()) .SelectMany(m => m.Methods) .SelectMany(m => func(m, h)); }
GetUsedMethodsAndProperties の引数は解析したい DLL のフルパス。
こんな感じで、一先ず欲しい情報は抽出出来た。
これからは、 example や readme を参考にもう少し調べてみる。