public static bool ImplementsInterface(ITypeDefinition tgt, ITypeDefinition queryItf) { if (queryItf == null || tgt == null) { return(false); } foreach (ITypeReference itf in tgt.Interfaces) { ITypeDefinition analItf = Stubber.GetTypeToAnalyze(itf.ResolvedType); if (analItf != null && tdc.Equals(queryItf, analItf.ResolvedType)) { return(true); } } foreach (ITypeReference itf in tgt.Interfaces) { ITypeReference analItf = Stubber.GetTypeToAnalyze(itf.ResolvedType); if (analItf != null && ImplementsInterface(analItf.ResolvedType, queryItf)) { return(true); } } foreach (ITypeReference bcl in tgt.BaseClasses) { ITypeReference analBcl = Stubber.GetTypeToAnalyze(bcl.ResolvedType); if (analBcl != null && ImplementsInterface(analBcl.ResolvedType, queryItf)) { return(true); } } return(false); }
public static bool ExtendsClass(ITypeDefinition derivedCl, ITypeDefinition baseCl) { if (derivedCl == null || baseCl == null) { return(false); } ITypeDefinition analBaseCl = Stubber.GetTypeToAnalyze(baseCl); if (analBaseCl != null && tdc.Equals(derivedCl, analBaseCl)) { return(true); } foreach (ITypeReference bcl in derivedCl.BaseClasses) { ITypeDefinition analBcl = Stubber.GetTypeToAnalyze(bcl.ResolvedType); if (analBcl != null && tdc.Equals(baseCl, analBcl)) { return(true); } } foreach (ITypeReference bcl in derivedCl.BaseClasses) { ITypeDefinition analBcl = Stubber.GetTypeToAnalyze(bcl.ResolvedType); if (ExtendsClass(analBcl, baseCl)) { return(true); } } return(false); }
public void VisitLocals(MethodBody mBody) { ISet <IVariable> localVarSet = mBody.Variables; foreach (IVariable lclVar in localVarSet) { if (!lclVar.IsParameter && lclVar.Type.ResolvedType.IsStruct) { Stubber.CheckAndAdd(lclVar.Type.ResolvedType); } } return; }
public static IMethodDefinition GetInstantiatedMeth(IMethodDefinition templateMeth, IMethodDefinition instMeth) { IGenericMethodInstance genericM = instMeth as IGenericMethodInstance; IEnumerable <ITypeReference> genericArgs = genericM.GenericArguments; IList <ITypeReference> stubbedArgList = new List <ITypeReference>(); foreach (ITypeReference garg in genericArgs) { ITypeDefinition addedType = Stubber.CheckAndAdd(garg.ResolvedType); if (addedType != null) { stubbedArgList.Add(addedType); } else { stubbedArgList.Add(garg.ResolvedType); } } string argStr = GetGenericArgStr(stubbedArgList); IDictionary <string, IMethodDefinition> instMap; if (ClassAndMethodVisitor.genericMethodMap.ContainsKey(templateMeth)) { instMap = ClassAndMethodVisitor.genericMethodMap[templateMeth]; } else { instMap = new Dictionary <string, IMethodDefinition>(); ClassAndMethodVisitor.genericMethodMap[templateMeth] = instMap; } if (instMap.ContainsKey(argStr)) { return(instMap[argStr]); } else { GenericMethodInstanceReference newInstMethRef = new GenericMethodInstanceReference(templateMeth, genericArgs, internFactory); IMethodDefinition newInstMeth = newInstMethRef.ResolvedMethod; instMap[argStr] = newInstMeth; return(newInstMeth); } }
public static IMethodDefinition GetMethodSignMatchRecursive(ITypeDefinition ty, IMethodDefinition meth) { IMethodDefinition signMatchMeth = GetMethodSignMatch(ty, meth); if (signMatchMeth != null) { return(signMatchMeth); } foreach (ITypeReference bty in ty.BaseClasses) { ITypeDefinition analBty = Stubber.GetTypeToAnalyze(bty.ResolvedType); if (analBty != null && !Stubber.SuppressF(analBty)) { return(GetMethodSignMatchRecursive(analBty, meth)); } } return(null); }
private void ProcessStaticConstructors(ITypeDefinition ty) { if (!rtaAnalyzer.clinitProcessedClasses.Contains(ty) && !Stubber.SuppressM(ty)) { rtaAnalyzer.clinitProcessedClasses.Add(ty); IMethodDefinition clinitMeth = Utils.GetStaticConstructor(ty); if (clinitMeth != null) { Stubber.CheckAndAdd(clinitMeth); } if (ty.BaseClasses.Any()) { ITypeDefinition baseTy = ty.BaseClasses.Single().ResolvedType; ProcessStaticConstructors(baseTy); } foreach (ITypeReference itf in ty.Interfaces) { ITypeDefinition itfD = itf.ResolvedType; ProcessStaticConstructors(itfD); } } }
public static bool TypeMatch(ITypeReference t1, ITypeReference t2) { ITypeDefinition tdef1 = t1.ResolvedType; ITypeDefinition tdef2 = t2.ResolvedType; if (tdc.Equals(tdef1, tdef2)) { return(true); } if (Stubber.MatchesSuppressM(tdef1)) { tdef1 = Stubs.GetStubType(tdef1); } if (Stubber.MatchesSuppressM(tdef2)) { tdef2 = Stubs.GetStubType(tdef2); } // return (tdef1 != null && tdef2 != null && tdc.Equals(tdef1, tdef2)); if (tdef1 != null && tdef2 != null) { if (tdef1 is IGenericTypeInstance) { tdef1 = (tdef1 as IGenericTypeInstance).GenericType.ResolvedType; } if (tdef2 is IGenericTypeInstance) { tdef2 = (tdef2 as IGenericTypeInstance).GenericType.ResolvedType; } return(tdc.Equals(tdef1, tdef2)); } else { return(false); } }
static void DoRTA(IMetadataHost host, ClassAndMethodVisitor visitor, IModule rootModule, IModule stubsModule) { bool rootIsExe = false; if (rootModule.Kind == ModuleKind.ConsoleApplication) { rootIsExe = true; } StreamWriter rtaLogSW = new StreamWriter(Path.Combine(ConfigParams.LogDir, "rta_log.txt")); rtaAnalyzer = new RTAAnalyzer(rootIsExe, rtaLogSW, host); visitor.SetupRTAAnalyzer(rtaAnalyzer); Stubber.SetupRTAAnalyzer(rtaAnalyzer); Stubs.SetupInternFactory(host.InternFactory); GenericMethods.SetupInternFactory(host.InternFactory); Stubs.SetupStubs(stubsModule); bool diskLoadSuccessful = false; if (ConfigParams.LoadSavedScope) { diskLoadSuccessful = rtaAnalyzer.LoadSavedScope(host); } if (!diskLoadSuccessful) { Initialize(rtaAnalyzer.classes, rtaAnalyzer.entryPtClasses, rootModule, rootIsExe); } int iterationCount = 0; bool changeInCount = true; int startClassCnt, startMethCnt; while (changeInCount) { rtaLogSW.WriteLine(); rtaLogSW.WriteLine("Starting RTA ITERATION:{0}", iterationCount); startClassCnt = rtaAnalyzer.classes.Count; startMethCnt = rtaAnalyzer.methods.Count; rtaLogSW.WriteLine("Counts: classes:{0} methods:{1}", startClassCnt, startMethCnt); rtaAnalyzer.classWorkList.Clear(); rtaAnalyzer.visitedClasses.Clear(); rtaAnalyzer.ignoredClasses.Clear(); rtaAnalyzer.visitedMethods.Clear(); rtaAnalyzer.ignoredMethods.Clear(); CopyAll(rtaAnalyzer.classes, rtaAnalyzer.classWorkList); while (rtaAnalyzer.classWorkList.Count > 0) { ITypeDefinition ty = rtaAnalyzer.classWorkList.First <ITypeDefinition>(); rtaAnalyzer.classWorkList.RemoveAt(0); visitor.Traverse(ty); } if (rtaAnalyzer.classes.Count == startClassCnt && rtaAnalyzer.methods.Count == startMethCnt) { changeInCount = false; } iterationCount++; } Copy(rtaAnalyzer.allocClasses, rtaAnalyzer.classes); rtaLogSW.WriteLine(); rtaLogSW.WriteLine(); foreach (IMethodDefinition m in rtaAnalyzer.methods) { rtaLogSW.WriteLine(m.FullName()); } rtaLogSW.WriteLine(); rtaLogSW.WriteLine(); foreach (IMethodDefinition m in rtaAnalyzer.entryPtMethods) { rtaLogSW.WriteLine(m.FullName()); } rtaLogSW.WriteLine(); rtaLogSW.WriteLine(); foreach (ITypeDefinition cl in rtaAnalyzer.classes) { rtaLogSW.WriteLine(cl.FullName()); } rtaLogSW.WriteLine(); rtaLogSW.WriteLine("ALLOC CLASSES"); foreach (ITypeDefinition cl in rtaAnalyzer.allocClasses) { rtaLogSW.WriteLine(cl.FullName()); } rtaLogSW.WriteLine("+++++++++++++++ RTA DONE ++++++++++++++++++"); if (!diskLoadSuccessful) { rtaAnalyzer.SaveScope(host); } rtaLogSW.Close(); }
public MethodCfgAndTac AnalyzeIntraProcedural(IMethodDefinition methodDefinition) { // System.Console.WriteLine("Traversing: {0}", methodDefinition.GetName()); if (Stubber.SuppressM(methodDefinition)) { return(null); } if (methodDefinition.IsExternal) { return(null); } if (methodDefinition.IsAbstract) { return(null); } ITypeDefinition containingDefn = methodDefinition.ContainingTypeDefinition; ISourceLocationProvider sourceLocationProvider = null; if (containingDefn != null) { IModule mod = TypeHelper.GetDefiningUnit(containingDefn) as IModule; if (moduleToPdbMap.ContainsKey(mod)) { sourceLocationProvider = moduleToPdbMap[mod]; } else { if (!(mod == null || mod == Dummy.Module || mod == Dummy.Assembly)) { sourceLocationProvider = GetPdbReader(mod.Location); moduleToPdbMap[mod] = sourceLocationProvider; } } } var disassembler = new Disassembler(host, methodDefinition, sourceLocationProvider); var methodBody = disassembler.Execute(); var cfAnalysis = new ControlFlowAnalysis(methodBody); // var cfg = cfAnalysis.GenerateNormalControlFlow(); var cfg = cfAnalysis.GenerateExceptionalControlFlow(); var domAnalysis = new DominanceAnalysis(cfg); domAnalysis.Analyze(); domAnalysis.GenerateDominanceTree(); var loopAnalysis = new NaturalLoopAnalysis(cfg); loopAnalysis.Analyze(); var domFrontierAnalysis = new DominanceFrontierAnalysis(cfg); domFrontierAnalysis.Analyze(); var splitter = new WebAnalysis(cfg, methodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var typeAnalysis = new TypeInferenceAnalysis(cfg, methodDefinition.Type); typeAnalysis.Analyze(); var forwardCopyAnalysis = new ForwardCopyPropagationAnalysis(cfg); forwardCopyAnalysis.Analyze(); forwardCopyAnalysis.Transform(methodBody); // backwardCopyAnalysis is buggy - it says so in the source file - see notes in src/test // var backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(cfg); // backwardCopyAnalysis.Analyze(); // backwardCopyAnalysis.Transform(methodBody); var liveVariables = new LiveVariablesAnalysis(cfg); liveVariables.Analyze(); var ssa = new StaticSingleAssignment(methodBody, cfg); ssa.Transform(); ssa.Prune(liveVariables); methodBody.UpdateVariables(); MethodCfgAndTac mct = new MethodCfgAndTac(cfg, methodBody); foreach (IExceptionHandlerBlock ehInfo in disassembler.GetExceptionHandlers()) { if (ehInfo is CatchExceptionHandler) { mct.ehInfoList.Add(ehInfo as CatchExceptionHandler); } } return(mct); }
public void Traverse(IMethodDefinition methodDefinition) { ControlFlowGraph cfg; MethodBody methodBody; IList <CatchExceptionHandler> ehInfoList; if (methodToCfgAndTacMap.ContainsKey(methodDefinition)) { MethodCfgAndTac mct = methodToCfgAndTacMap[methodDefinition]; if (mct == null) { return; } cfg = mct.cfg; methodBody = mct.methodBody; ehInfoList = mct.ehInfoList; } else { MethodCfgAndTac mct = AnalyzeIntraProcedural(methodDefinition); methodToCfgAndTacMap[methodDefinition] = mct; if (mct == null) { return; } cfg = mct.cfg; methodBody = mct.methodBody; ehInfoList = mct.ehInfoList; } if (rtaAnalyzer != null) { if (rtaAnalyzer.entryPtClasses.Contains(methodDefinition.ContainingTypeDefinition)) { if (rtaAnalyzer.rootIsExe) { // Add only the Main method as entry point if (Utils.IsMainMethod(methodDefinition)) { rtaAnalyzer.rtaLogSW.WriteLine("Adding main method: {0}", methodDefinition.FullName()); IMethodDefinition addedMeth = Stubber.CheckAndAdd(methodDefinition); // The assumption is that addedMeth is not a template method. Here it is safe because it holds for the main method. if (addedMeth != null) { rtaAnalyzer.entryPtMethods.Add(addedMeth); } } } else { if (methodDefinition.Visibility == TypeMemberVisibility.Public || methodDefinition.Visibility == TypeMemberVisibility.Family) { // Otherwise, add all public methods as entry points IMethodDefinition addedMeth = Stubber.CheckAndAdd(methodDefinition); rtaAnalyzer.rtaLogSW.WriteLine("Adding method: {0}", methodDefinition.FullName()); // The assumption here is that addedMeth is not a template method. // TODO: It may be the case that this assumption does not hold in some cases. if (addedMeth != null) { rtaAnalyzer.entryPtMethods.Add(addedMeth); } } } } if (rtaAnalyzer.methods.Contains(methodDefinition) && !rtaAnalyzer.visitedMethods.Contains(methodDefinition)) { rtaAnalyzer.visitedMethods.Add(methodDefinition); // rtaAnalyzer.rtaLogSW.WriteLine("SRK_DBG: Visiting method: {0}", methodDefinition.GetName()); rtaAnalyzer.VisitMethod(methodBody, cfg); } else { rtaAnalyzer.ignoredMethods.Add(methodDefinition); } } else if (factGen != null) { if (factGen.methods.Contains(methodDefinition)) { factGen.GenerateFacts(methodBody, cfg, ehInfoList); } } }
public void VisitMethod(MethodBody mBody, ControlFlowGraph cfg) { VisitLocals(mBody); // Going through the instructions via cfg nodes instead of directly iterating over the instructions // of the methodBody becuase Phi instructions may not have been inserted in the insts of the methodBody. foreach (var node in cfg.Nodes) { foreach (var instruction in node.Instructions) { // System.Console.WriteLine("{0}", instruction.ToString()); // System.Console.WriteLine("{0}", instruction.GetType().FullName()); // System.Console.WriteLine(); if (instruction is LoadInstruction) { LoadInstruction lInst = instruction as LoadInstruction; IValue rhsOperand = lInst.Operand; if (rhsOperand is StaticFieldAccess) { StaticFieldAccess rhsAcc = rhsOperand as StaticFieldAccess; IFieldReference fld = rhsAcc.Field; ITypeDefinition fldType = fld.ContainingType.ResolvedType; Stubber.CheckAndAdd(fldType); } // Note: calls to static methods and instance methods appear as a StaticMethodReference else if (rhsOperand is StaticMethodReference) { StaticMethodReference sMethAddr = rhsOperand as StaticMethodReference; IMethodDefinition tgtMeth = sMethAddr.Method.ResolvedMethod; ITypeDefinition containingTy = tgtMeth.ContainingTypeDefinition; Stubber.CheckAndAdd(containingTy); IMethodDefinition addedMeth = Stubber.CheckAndAdd(tgtMeth); // addrTakenMethods do not contain templates. if (addedMeth != null) { addrTakenMethods.Add(addedMeth); } } //Note: calls to virtual, abstract or interface methods appear as VirtualMethodReference else if (rhsOperand is VirtualMethodReference) { VirtualMethodReference sMethAddr = rhsOperand as VirtualMethodReference; IMethodDefinition tgtMeth = sMethAddr.Method.ResolvedMethod; ITypeDefinition containingTy = tgtMeth.ContainingTypeDefinition; ITypeDefinition addedTy = Stubber.CheckAndAdd(containingTy); IMethodDefinition addedMeth = Stubber.CheckAndAdd(tgtMeth); if (addedTy != null && addedMeth != null) { // addrTakenMethods do not contain templates. addrTakenMethods.Add(addedMeth); ProcessVirtualInvoke(addedMeth, addedTy, true); } } else if (rhsOperand is Reference) { Reference rhsRef = rhsOperand as Reference; IReferenceable refOf = rhsRef.Value; if (refOf is StaticFieldAccess) { StaticFieldAccess refAcc = refOf as StaticFieldAccess; IFieldDefinition fld = refAcc.Field.ResolvedField; ITypeDefinition fldType = fld.ContainingType.ResolvedType; Stubber.CheckAndAdd(fldType); addrTakenStatFlds.Add(fld); } else if (refOf is IVariable) { IVariable refVar = refOf as IVariable; if (!refVar.Type.IsValueType || refVar.Type.ResolvedType.IsStruct) { addrTakenLocals.Add(refVar); } } else if (refOf is InstanceFieldAccess) { InstanceFieldAccess refAcc = refOf as InstanceFieldAccess; IFieldDefinition fld = refAcc.Field.ResolvedField; addrTakenInstFlds.Add(fld); } else if (refOf is ArrayElementAccess) { // All arrays will be added into domX as potential address taken. } } } else if (instruction is StoreInstruction) { StoreInstruction sInst = instruction as StoreInstruction; IAssignableValue lhs = sInst.Result; if (lhs is StaticFieldAccess) { StaticFieldAccess lhsAcc = lhs as StaticFieldAccess; IFieldReference fld = lhsAcc.Field; ITypeDefinition fldType = fld.ContainingType.ResolvedType; Stubber.CheckAndAdd(fldType); } } else if (instruction is CreateObjectInstruction) { CreateObjectInstruction newObjInst = instruction as CreateObjectInstruction; ITypeReference objType = newObjInst.AllocationType; ITypeDefinition objTypeDef = objType.ResolvedType; if (objTypeDef is IGenericTypeInstance) { objTypeDef = objTypeDef.ResolvedType; } ITypeDefinition addedTy = Stubber.CheckAndAdd(objTypeDef); if (addedTy != null && !allocClasses.Contains(addedTy)) { allocClasses.Add(addedTy); } } else if (instruction is CreateArrayInstruction) { CreateArrayInstruction newArrInst = instruction as CreateArrayInstruction; ITypeReference elemType = newArrInst.ElementType; ITypeDefinition elemTypeDef = elemType.ResolvedType; ITypeDefinition addedTy = Stubber.CheckAndAdd(elemTypeDef); if (addedTy != null && !allocClasses.Contains(addedTy)) { allocClasses.Add(addedTy); } } else if (instruction is MethodCallInstruction) { MethodCallInstruction invkInst = instruction as MethodCallInstruction; IMethodReference callTgt = invkInst.Method; ITypeReference containingType = callTgt.ContainingType; ITypeDefinition declType = containingType.ResolvedType; IMethodDefinition callTgtDef = callTgt.ResolvedMethod; ITypeDefinition addedType = Stubber.CheckAndAdd(declType); IMethodDefinition addedMeth = Stubber.CheckAndAdd(callTgtDef); MethodCallOperation callType = invkInst.Operation; if (callType == MethodCallOperation.Virtual && addedType != null && addedMeth != null) { ProcessVirtualInvoke(addedMeth, addedType, false); } } else { // System.Console.WriteLine("{0}", instruction.ToString()); // System.Console.WriteLine("Not currently handled: {0}", instruction.GetType().ToString()); // System.Console.WriteLine(); } } } }
public void ProcessVirtualInvoke(IMethodDefinition mCallee, ITypeDefinition calleeClass, bool isAddrTaken) { // mCallee is an ordinary method - never a template method. // calleeClass and mCallee are either both stubbed or, both unstubbed - i.e. they are consistent. bool isInterface = calleeClass.IsInterface; IMethodDefinition calleeTemplate = null; if (mCallee is IGenericMethodInstance) { calleeTemplate = (mCallee as IGenericMethodInstance).GenericMethod.ResolvedMethod; } foreach (ITypeDefinition cl in allocClasses) { if (cl is IArrayTypeReference) { continue; } if (!Stubber.SuppressM(cl)) { bool process = false; if (isInterface && Utils.ImplementsInterface(cl, calleeClass)) { process = true; } if (Utils.ExtendsClass(cl, calleeClass)) { process = true; } if (!process) { continue; } IMethodDefinition calleeArg; if (mCallee is IGenericMethodInstance) { calleeArg = calleeTemplate; } else { calleeArg = mCallee; } IMethodDefinition meth = Utils.GetMethodSignMatchRecursive(cl, calleeArg); if (meth == null) { continue; } if (meth.IsGeneric && calleeTemplate != null) { IMethodDefinition instMeth = GenericMethods.RecordInfo(meth, mCallee, /* createIfReqd = */ true); IMethodDefinition addedMeth = Stubber.CheckAndAdd(instMeth); if (addedMeth != null && isAddrTaken) { addrTakenMethods.Add(addedMeth); } } else if (meth.IsGeneric && calleeTemplate == null) { continue; } else if (!meth.IsGeneric && calleeTemplate != null) { continue; } else // meth is not generic and calleeTemplate is null { IMethodDefinition addedMeth = Stubber.CheckAndAdd(meth); if (addedMeth != null && isAddrTaken) { addrTakenMethods.Add(addedMeth); } } } } }