void AnalysisCodes(MethodDefinition mtd) { for (int i = 0; i < mtd.Body.Instructions.Count; i++) { Instruction inst = mtd.Body.Instructions[i]; if (inst.Operand is MethodReference || inst.Operand is FieldReference) { if ((inst.Operand as MemberReference).DeclaringType is TypeSpecification && ((inst.Operand as MemberReference).DeclaringType as TypeSpecification).GetElementType() is TypeDefinition) { IMemberDefinition memDef; if (inst.Operand is MethodReference && (memDef = (inst.Operand as MethodReference).GetElementMethod().Resolve()) != null) { ((memDef as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new SpecificationReference(inst.Operand as MemberReference)); } else if (inst.Operand is FieldReference && (memDef = (inst.Operand as FieldReference).Resolve()) != null) { ((memDef as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new SpecificationReference(inst.Operand as MemberReference)); } } else if (inst.Operand is MethodReference) { MethodReference refer = inst.Operand as MethodReference; string id = refer.DeclaringType.FullName + "::" + refer.Name; if (Database.Reflections.ContainsKey(id)) { ReflectionMethod Rmtd = Database.Reflections[id]; Instruction memInst; MemberReference mem = StackTrace(i, mtd.Body.Instructions, Rmtd, mtd.Module, out memInst); if (mem != null) { ((mem as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new ReflectionReference(memInst)); } } } if (ivtRefs.ContainsKey((inst.Operand as MemberReference).MetadataToken)) { IMemberDefinition memDef; if (inst.Operand is TypeReference && (memDef = (inst.Operand as TypeReference).Resolve()) != null) { ((memDef as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new IvtMemberReference(inst.Operand as MemberReference)); } else if (inst.Operand is MethodReference && (memDef = (inst.Operand as MethodReference).Resolve()) != null) { ((memDef as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new IvtMemberReference(inst.Operand as MemberReference)); } else if (inst.Operand is FieldReference && (memDef = (inst.Operand as FieldReference).Resolve()) != null) { ((memDef as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new IvtMemberReference(inst.Operand as MemberReference)); } } } } }
static Database() { Reflections = new Dictionary <string, ReflectionMethod>(); string type = null; using (StringReader rdr = new StringReader(db)) { while (true) { string line = rdr.ReadLine(); if (line == "=") { break; } if (type != null) { if (line == "") { type = null; continue; } ReflectionMethod mtd = new ReflectionMethod(); mtd.typeName = type; mtd.mtdName = line.Substring(0, line.IndexOf('[')); string param = line.Substring(line.IndexOf('[') + 1, line.IndexOf(']') - line.IndexOf('[') - 1); string[] pars = param.Split(','); mtd.paramLoc = new int[pars.Length]; mtd.paramType = new string[pars.Length]; for (int i = 0; i < pars.Length; i++) { mtd.paramLoc[i] = int.Parse(pars[i].Split(':')[0]); mtd.paramType[i] = pars[i].Split(':')[1]; } Reflections.Add(mtd.typeName + "::" + mtd.mtdName, mtd); } else { type = line; } } } }
MemberReference StackTrace(int idx, Collection <Instruction> insts, ReflectionMethod mtd, ModuleDefinition scope, out Instruction memInst) { memInst = null; int count = ((insts[idx].Operand as MethodReference).HasThis ? 1 : 0) + (insts[idx].Operand as MethodReference).Parameters.Count; if (insts[idx].OpCode.Code == Code.Newobj) { count--; } int c = 0; for (idx--; idx >= 0; idx--) { if (count == c) { break; } Instruction inst = insts[idx]; switch (inst.OpCode.Code) { case Code.Ldc_I4: case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: case Code.Ldstr: c++; break; case Code.Call: case Code.Callvirt: { MethodReference target = (inst.Operand as MethodReference); c -= (target.HasThis ? 1 : 0) + target.Parameters.Count; if (target.ReturnType.FullName != "System.Void") { c++; } break; } case Code.Newobj: { MethodReference target = (inst.Operand as MethodReference); c -= target.Parameters.Count - 1; break; } case Code.Pop: c--; break; case Code.Ldarg: c++; break; case Code.Ldfld: c++; break; case Code.Ldloc: c++; break; case Code.Ldnull: c++; break; case Code.Starg: case Code.Stfld: case Code.Stloc: c--; break; case Code.Ldtoken: c++; break; default: FollowStack(inst.OpCode, ref c); break; } } return(StackTrace2(idx + 1, count, insts, mtd, scope, out memInst)); }
MemberReference StackTrace2(int idx, int c, Collection <Instruction> insts, ReflectionMethod mtd, ModuleDefinition scope, out Instruction memInst) { memInst = null; int count = c; Stack <object> stack = new Stack <object>(); for (int i = idx; ; i++) { if (stack.Count == count) { break; } Instruction inst = insts[i]; switch (inst.OpCode.Code) { case Code.Ldc_I4: case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: case Code.Ldstr: stack.Push(inst.Operand); break; case Code.Call: case Code.Callvirt: { MethodReference target = (inst.Operand as MethodReference); int cc = -(target.HasThis ? 1 : 0) - target.Parameters.Count; for (int ii = cc; ii != 0; ii++) { stack.Pop(); } if (target.ReturnType.FullName != "System.Void") { stack.Push(target.ReturnType); } break; } case Code.Newobj: { MethodReference target = (inst.Operand as MethodReference); for (int ii = -target.Parameters.Count; ii != 0; ii++) { stack.Pop(); } stack.Push(target.DeclaringType); break; } case Code.Pop: stack.Pop(); break; case Code.Ldarg: stack.Push((inst.Operand as ParameterReference).ParameterType); break; case Code.Ldfld: stack.Push((inst.Operand as FieldReference).FieldType); break; case Code.Ldloc: stack.Push((inst.Operand as VariableReference).VariableType); break; case Code.Ldnull: stack.Push(null); break; case Code.Starg: case Code.Stfld: case Code.Stloc: stack.Pop(); break; case Code.Ldtoken: stack.Push(inst.Operand); break; default: FollowStack(inst.OpCode, stack); break; } } object[] objs = stack.ToArray(); Array.Reverse(objs); string mem = null; TypeDefinition type = null; int typeIdx; Resource res = null; for (int i = 0; i < mtd.paramLoc.Length; i++) { if (mtd.paramLoc[i] >= objs.Length) { return(null); } object param = objs[mtd.paramLoc[i]]; switch (mtd.paramType[i]) { case "Target": if ((mem = param as string) == null) { return(null); } memInst = StackTrace3(idx, c, insts, mtd.paramLoc[i]); break; case "Type": case "This": if (param as TypeDefinition != null) { type = param as TypeDefinition; typeIdx = mtd.paramLoc[i]; } break; case "TargetType": if (!(param is string)) { return(null); } type = scope.GetType(param as string); typeIdx = mtd.paramLoc[i]; break; case "TargetResource": if (!(param is string)) { return(null); } res = scope.Resources.FirstOrDefault((r) => (r.Name == param as string + ".resources")); memInst = StackTrace3(idx, c, insts, mtd.paramLoc[i]); break; } } if (mem == null && type == null && res == null) { return(null); } if (res != null) { ((res as IAnnotationProvider).Annotations["RenRef"] as List <IReference>).Add(new ResourceNameReference(memInst)); return(null); } if (mem != null && type != null) { foreach (FieldDefinition fld in type.Fields) { if (fld.Name == mem) { return(fld); } } foreach (MethodDefinition mtd1 in type.Methods) { if (mtd1.Name == mem) { return(mtd1); } } foreach (PropertyDefinition prop in type.Properties) { if (prop.Name == mem) { return(prop); } } foreach (EventDefinition evt in type.Events) { if (evt.Name == mem) { return(evt); } } } else if (type != null) { memInst = StackTrace3(idx, c, insts, mtd.paramLoc[Array.IndexOf(mtd.paramType, "TargetType")]); return(type); } return(null); }