public static Instruction GetPriorInstruction(MethodReference callingMethod, MethodReference method, Instruction instruction) { try { var rootNode = new InstructionTreeNode(); var lastInstruction = GetParameterInstructionTree(callingMethod, method, instruction, rootNode); if (lastInstruction == null) { } // if the last instruction is ldarg.0 then return the instruction after that which will be the owner field or method if (lastInstruction.OpCode.Code == Mono.Cecil.Cil.Code.Ldarg_0) { return(lastInstruction.Next); } // if the last instruction is the target instruction, then return the previous one // this can happen with compiled generated classes if (lastInstruction.Offset == instruction.Offset) { return(lastInstruction.Previous); } return(lastInstruction); //return GetPreviousInstruction(lastInstruction); } catch (Exception ex) { return(null); } }
private InstructionTreeNode GetInstructionTree(MethodDefinition parentMethod, Instruction instruction, MethodReference calledMethod) { try { var rootNode = new InstructionTreeNode(); MethodArgumentInstructionParser.GetParameterInstructionTree(parentMethod, calledMethod, instruction, rootNode); return(rootNode); } catch (Exception ex) { _logOutput.LogAnalysis("ERROR " + parentMethod.FullName + " instruction" + instruction.ToString() + " Error-> " + ex); return(null); } }
public static Instruction GetParameterInstructionTreeForFuncConstructor(MethodReference callingMethod, MethodReference funcMethod, Instruction instruction, InstructionTreeNode parentNode) { if (parentNode.Instruction == null) { parentNode.Instruction = instruction; } int parameterCount = GetParameterCount(funcMethod); for (int i = 0; i < parameterCount; i++) { instruction = GetPreviousInstruction(instruction); var childNode = new InstructionTreeNode(); childNode.Instruction = instruction; parentNode.ChildInstructions.Add(childNode); } return(instruction); }
private List <Triple> TraverseTree(MethodDefinition parentMethod, InstructionTreeNode parentNode, string instanceOwnerKey, bool isObjectInitializerMember, string constructorInstructionKey = null) { var triples = new List <Triple>(); var toArgumentCounter = parentNode.ChildInstructions.Count; foreach (var argumentInstruction in parentNode.ChildInstructions) { var fromObjectType = InstructionKeyService.GetFromObjectType(argumentInstruction.Instruction); var fromInstanceOwnerKey = InstructionKeyService.GetFromInstanceOwnerKey(argumentInstruction.Instruction, fromObjectType, parentMethod); var triple = BuildTriple(parentNode.Instruction, instanceOwnerKey, argumentInstruction.Instruction, fromInstanceOwnerKey, parentMethod, toArgumentCounter); if (triple == null) { continue; } if (isObjectInitializerMember) { triple.SetsObjectInitializerMember = true; triple.ConstructorInstructionKey = constructorInstructionKey; } triples.Add(triple); toArgumentCounter--; if (argumentInstruction.ChildInstructions.Any()) { var subTriples = TraverseTree(parentMethod, argumentInstruction, triple.From.InstanceOwnerKey, false); triples.AddRange(subTriples); } } return(triples); }
private void FindFieldsAndMethods(MethodDefinition method, MethodObject methodNode, bool allowRecursion) { if (!method.HasBody) { return; } List <Instruction> instructions = null; var isAsync = IsAsync(method); if (isAsync.Item1) { instructions = GetInstructionsOfAsyncMethod(isAsync.Item2); } else { instructions = method.Body.Instructions.ToList(); } foreach (var instruction in instructions) { try { if (instruction.OpCode.Code == Mono.Cecil.Cil.Code.Call || instruction.OpCode.Code == Mono.Cecil.Cil.Code.Calli || instruction.OpCode.Code == Mono.Cecil.Cil.Code.Callvirt || instruction.OpCode.Code == Mono.Cecil.Cil.Code.Newobj) { var methodRef = (MethodReference)instruction.Operand; MethodDefinition methodDef = null; var resolved = ResolveService.TryResolve(methodRef, out methodDef); if (!resolved) { // log error continue; } if (DelegateIndexer.IsDelegateInvocation(methodRef)) { var concreteMethods = _delegateIndexer.GetAssignedMethods(method, methodRef); foreach (var concreteMethod in concreteMethods) { var delegateCall = new MethodCall(); delegateCall.Instruction = concreteMethod.MethodAssignmentInstruction; delegateCall.MethodCalled = concreteMethod.AssignedMethod; delegateCall.OwnerMethod = method; methodNode.MethodsCalled.Add(delegateCall); } } else if (IsLazilyEvaluated(instruction, methodDef)) { var nestedMethods = ExtractNestedMethods(methodDef.DeclaringType); foreach (var nestedMethod in nestedMethods) { if (allowRecursion) { FindFieldsAndMethods(nestedMethod, methodNode, false); } } } else if (!methodRef.FullName.Equals("System.Void System.Object::.ctor()")) { bool funcMethodCallsFound = false; // try to detect funcs if (methodRef.Parameters.Any()) { var rootNode = new InstructionTreeNode(); MethodArgumentInstructionParser.GetParameterInstructionTree(method, methodRef, instruction, rootNode); foreach (var loadFunctionNode in rootNode.GetDescendants().Where(x => x.Instruction.OpCode.Code == Mono.Cecil.Cil.Code.Ldftn)) { // except for delegates! var funcCall = new MethodCall(); funcCall.Instruction = loadFunctionNode.Instruction; funcCall.MethodCalled = loadFunctionNode.Instruction.Operand as MethodReference; funcCall.OwnerMethod = method; methodNode.MethodsCalled.Add(funcCall); funcMethodCallsFound = true; } } bool isCompilerServicesRelated = false; if (isAsync.Item1 && (methodRef.DeclaringType.FullName.StartsWith("System.Runtime.CompilerServices") || methodRef.DeclaringType.FullName.StartsWith("System.Threading.Tasks"))) { isCompilerServicesRelated = true; } // if not a func and not an async related CompilerServices call then go ahead and register the call if (!funcMethodCallsFound && !isCompilerServicesRelated) { var methodCall = new MethodCall(); methodCall.Instruction = instruction; methodCall.MethodCalled = methodRef; methodCall.OwnerMethod = method; methodNode.MethodsCalled.Add(methodCall); } } } else if (instruction.OpCode.OperandType == OperandType.InlineField) { var field = (FieldReference)instruction.Operand; if ((instruction.OpCode.Name.StartsWith("ldfld") || instruction.OpCode.Name.StartsWith("ldsfld")) && field.Name.IndexOf("BackingField") == -1) { methodNode.FieldsRead.Add(field); } } else if (instruction.OpCode.Code == Mono.Cecil.Cil.Code.Ldftn) { var methodRef = (MethodReference)instruction.Operand; MethodDefinition functionDefinition = null; var resolved = ResolveService.TryResolve(methodRef, out functionDefinition); if (!resolved) { // log error continue; } if (allowRecursion) { FindFieldsAndMethods(functionDefinition, methodNode, false); } } } catch (Exception ex) { // log it } } }
private static Instruction GetParameterInstructionTreeForNormalMethod(MethodReference parentMethodRef, MethodReference method, Instruction instruction, InstructionTreeNode parentNode) { MethodDefinition parentMethod = parentMethodRef.Resolve(); Instruction targetMethodInstruction = instruction; MethodDefinition targetMethodDef = null; var resolved = ResolveService.TryResolve((MethodReference)instruction.Operand, out targetMethodDef); if (!resolved) { throw new ILParseException("Could not resolve " + ((MethodReference)instruction.Operand).FullName); } var parameterCount = method.Parameters.Count; if (parentNode.Instruction == null) { parentNode.Instruction = instruction; } for (int i = 0; i < parameterCount; i++) { if (instruction.Previous == null) { throw new ILParseException("Unexpectedly reached the end of the instructions while analysing " + parentMethodRef.FullName); } instruction = GetPreviousInstruction(instruction); if (ShouldSkip(instruction)) { instruction = GetPreviousInstruction(instruction); } var childNode = new InstructionTreeNode(); childNode.Instruction = instruction; parentNode.ChildInstructions.Add(childNode); if (instruction.OpCode.OperandType == OperandType.InlineMethod) { var instructionMethodDef = ResolveMethod(instruction); if (instructionMethodDef.Parameters.Any()) { var lastInstructionOfParameters = GetParameterInstructionTree(parentMethodRef, instructionMethodDef, instruction, childNode); instruction = lastInstructionOfParameters; //if (AreInstructionsChained(instruction, lastInstructionOfParameters.Previous)) // instruction = lastInstructionOfParameters.Previous; // move to chained instruction so later call jumps chained instructions } } instruction = JumpPastAnyOwnerInstructions(instruction, parentMethod); } instruction = JumpAnyJumpableInstructionsOfTargetMethod(targetMethodInstruction, instruction, targetMethodDef, parentMethod); //if(TargetMethodHasJumpablePreviousInstruction(targetMethodInstruction, instruction, targetMethodDef, parentMethod)) // instruction = GetPreviousInstruction(instruction); //if (HasThis(callingMethod, methodDef) && instruction.OpCode.Code != Mono.Cecil.Cil.Code.Ldarg_0) // instruction = GetPreviousInstruction(instruction); return(instruction); }
public static Instruction GetParameterInstructionTree(MethodReference callingMethod, MethodReference method, Instruction instruction, InstructionTreeNode parentNode) { if (method.Name.Equals(".ctor") && (method.DeclaringType.Name.IndexOf("Func`") > -1 || method.FullName.IndexOf("System.Object,System.IntPtr") > -1)) { return(GetParameterInstructionTreeForFuncConstructor(callingMethod, method, instruction, parentNode)); } else { return(GetParameterInstructionTreeForNormalMethod(callingMethod, method, instruction, parentNode)); } }