public void TestStackAnalysisResult() { AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(GetType().Module.Assembly.Location); Type testsDeclaringType = typeof(StackAnalysisResultScenarios); StringBuilder sb = new StringBuilder(); foreach (MethodInfo testMethod in testsDeclaringType.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance)) { try { MethodDefinition methodDefinition = MethodReferenceFor(testMethod, assembly).Resolve(); ExpectedStackAnalysisResultAttribute expected = ExpectedStackAnalysisResultFor(testMethod); StackAnalysisResult actual = StackAnalyzer.IsConsumedBy(IsMethodCallOnList, FindCastOrNewObj(methodDefinition), methodDefinition.DeclaringType.Module); Assert.AreEqual(expected.OpCode, actual.Consumer.OpCode.ToString()); Assert.AreEqual(expected.Offset, actual.Offset); Assert.AreEqual(expected.StackHeight, actual.StackHeight); Assert.AreEqual(expected.Match, true); } catch (Exception ex) { sb.AppendFormat("Exception while processing method {0}\r\n{1}", testMethod, ex); } } if (sb.Length > 0) { Assert.Fail(sb.ToString()); } }
private void InstrumentConcreteCollectionCasts(MethodDefinition methodDefinition) { foreach (Instruction cast in CastsToSupportedCollections(methodDefinition.Body)) { StackAnalysisResult result = StackAnalyzer.IsConsumedBy(MethodCallOnSupportedCollections, cast, methodDefinition.DeclaringType.Module); if (!result.Match) { throw new InvalidOperationException(string.Format("Error: [{0}] Invalid use of cast result: '{1}'.\r\nCasts to {2} are only allowed for property access/method calls.", methodDefinition, DebugInformation.InstructionInformationFor(result.Consumer, methodDefinition.Body.Instructions), cast.Operand)); } TypeReference castTarget = (TypeReference)cast.Operand; ReplaceCastAndCalleeDeclaringType(cast, result.Consumer, _collectionReplacements[castTarget.Resolve().FullName]); } }
private void InstrumentCollectionInstantiation(MethodDefinition methodDefinition) { foreach (Instruction newObj in TAEnabledCollectionInstantiations(methodDefinition.Body)) { StackAnalysisResult stackAnalysis = StackAnalyzer.IsConsumedBy(delegate { return(true); }, newObj, methodDefinition.DeclaringType.Module); if (IsAssignmentToConcreteType(stackAnalysis)) { Context.TraceWarning("[{0}] Assignment to concrete collection {1} ignored (offset: 0x{2:X2}).", methodDefinition, InstantiatedType(newObj), newObj.Next.Offset); continue; } ReplaceContructorWithConstructorFrom(newObj); } }
private void AssertStack(Type testsDeclaringType, bool expectedResult) { var typeReference = FindType(testsDeclaringType); var sb = new StringBuilder(); foreach (MethodReference testMethod in typeReference.Resolve().Methods) { var methodDefinition = testMethod.Resolve(); if (!methodDefinition.IsPublic) { continue; } if (methodDefinition.IsConstructor) { continue; } try { var stackAnalysis = StackAnalyzer.IsConsumedBy(IsMethodCallOnList, FindCast(methodDefinition), methodDefinition.DeclaringType.Module); if (expectedResult != stackAnalysis.Match) { sb.AppendFormat("Method {0} contains invalid cast operations.\r\n", testMethod); } } catch (Exception ex) { sb.AppendFormat("Exception while processing method {0}\r\n{1}", testMethod, ex); } } if (sb.Length > 0) { Assert.Fail(sb.ToString()); } }