private void FindFunctionTypes(Function function, bool makeNewStuffUp) { var code = ainFile.DecompiledCodeCache.GetDecompiledCode(function); foreach (var e in code.GetChildExpressions()) { if (e.ExpressionType == Instruction.CALLFUNC2 || e.ExpressionType == Instruction.FT_ASSIGNS) { int funcTypeIndex = -1; IVariable funcTypeVariable = null; if (e.ExpressionType == Instruction.CALLFUNC2) { funcTypeIndex = e.Arg2.Value; funcTypeVariable = e.Arg1.Variable.Canonicalize(); } else if (e.ExpressionType == Instruction.FT_ASSIGNS) { funcTypeIndex = e.Arg3.Value; funcTypeVariable = e.Arg1.Variable.Canonicalize(); } if (funcTypeVariable == null) { var arg1 = e.Arg1; if (arg1 != null) { arg1 = arg1.Arg1; } if (arg1 != null) { funcTypeVariable = arg1.Variable; } if (funcTypeVariable != null) { funcTypeVariable = funcTypeVariable.Canonicalize(); } } if (funcTypeVariable != null && funcTypeVariable.StructType == -1) { matches.Clear(); finished.Clear(); var traceResults = TraceVariable(funcTypeVariable, VariableTraceMode.DirectCopiesRecursive); foreach (var res in traceResults) { if (res.DataType.IsFuncType()) { res.StructType = funcTypeIndex; } } funcTypeVariable.StructType = funcTypeIndex; } } else if (e.ExpressionType == Instruction.DG_CALLBEGIN) { int delegateIndex = -1; IVariable delegateVariable = null; if (e.ExpressionType == Instruction.DG_CALLBEGIN) { delegateIndex = e.Value; delegateVariable = e.Arg2.Variable.Canonicalize(); } if (delegateVariable == null) { var arg1 = e.Arg2; if (arg1 != null) { arg1 = arg1.Arg1; } if (arg1 != null) { delegateVariable = arg1.Variable; } if (delegateVariable != null) { delegateVariable = delegateVariable.Canonicalize(); } } if (delegateVariable != null && delegateVariable.StructType == -1) { matches.Clear(); finished.Clear(); var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive); foreach (var res in traceResults) { if (res.DataType.IsDelegate()) { res.StructType = delegateIndex; } } delegateVariable.StructType = delegateIndex; } } else if (e.ExpressionType == Instruction.DG_STR_TO_METHOD) { var otherExpression = e.GetOtherSideOfBinaryExpression(); int delegateIndex = -1; if (e.Arg2.ExpressionType == Instruction.PUSH) { delegateIndex = e.Arg2.Value; } IVariable delegateVariable = null; if (otherExpression == null) { delegateVariable = e.GetFunctionCallParameter(); if (e.Parent != null && e.Parent.ExpressionType == Instruction.DG_ADD) { delegateVariable = e.Parent.Arg1.Variable.Canonicalize(); } else { } } else { delegateVariable = otherExpression.Variable; if (delegateVariable != null) { delegateVariable = delegateVariable.Canonicalize(); } else { } } if (delegateVariable != null && delegateVariable.StructType == -1 && delegateIndex != -1) { matches.Clear(); finished.Clear(); var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive); foreach (var res in traceResults) { if (res.DataType.IsDelegate()) { res.StructType = delegateIndex; } } delegateVariable.StructType = delegateIndex; } } else if (e.ExpressionType == Instruction.DG_NEW_FROM_METHOD) { var otherExpression = e.GetOtherSideOfBinaryExpression(); IVariable delegateVariable = null; if (otherExpression == null) { delegateVariable = e.GetFunctionCallParameter(); if (e.Parent != null && e.Parent.ExpressionType == Instruction.DG_ADD) { delegateVariable = e.Parent.Arg1.Variable.Canonicalize(); } else if (delegateVariable == null) { } } else { delegateVariable = otherExpression.Variable; } if (delegateVariable != null) { Function assignedFunction = null; if (e.Arg2.ExpressionType == Instruction.PUSH) { assignedFunction = ainFile.GetFunction(e.Arg2.Value); } if (assignedFunction != null) { var matchingTypes = ainFile.MatchingDelegates(assignedFunction); FunctionType firstMatch = null, secondMatch = null; foreach (var m in matchingTypes) { if (firstMatch == null) { firstMatch = m; } else { secondMatch = m; break; } } if (firstMatch != null && (secondMatch == null || makeNewStuffUp)) { int delegateIndex = firstMatch.Index; if (delegateVariable.StructType == -1) { matches.Clear(); finished.Clear(); var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive); foreach (var res in traceResults) { if (res.DataType.IsDelegate()) { res.StructType = delegateIndex; } } delegateVariable.StructType = delegateIndex; } } } } } } }
private void TraceExpressionUp2(Expression firstExpression) { var expression = firstExpression; if (expression == null) { return; } //Called on a instance of a variable expression in a function //Want to find: // Look at operators and assignment, ? : operator, casting // Copying to a function arguments // Return values //Types of searches: // Direct copies of variables, ignoring casting // Other variables that appear in a variable read // Other variables that appear in a variable write var lookForVariable = firstExpression.Variable; if (lookForVariable != null) { lookForVariable = lookForVariable.Canonicalize(); } //IVariable functionParameter = null; IVariable lValue = null; IVariable rValue = null; //look for a parent expression by seeking through operators while (true) { var parent = expression.Parent; if (parent == null || parent.ExpressionType == Instruction.Statement) { break; } //check for Return if (parent.ExpressionType == Instruction.RETURN) { expression = parent; lValue = parent.Root.Variable; break; } //check for function call or comma if (parent.ExpressionType.IsFunctionCall() || parent.ExpressionType == Instruction.Comma) { //functionParameter = expression.GetFunctionCallParameter(); lValue = expression.GetFunctionCallParameter(); break; } //check for cast operator or expression if (!ExpressionIsOperatorOrCast(parent)) { break; } expression = parent; } Expression e2 = SkipCastExpressions(expression); //is this an assignment expression? if (lValue == null) { if (expression.ExpressionType.IsAssignment()) { lValue = expression.Variable; var lValueCanon = lValue.Canonicalize(); var arg1ExpressionType = expression.Arg1.ExpressionType; if (lValueCanon == null && (arg1ExpressionType == Instruction.REF || arg1ExpressionType == Instruction.ArrayIndex)) { lValue = expression.Arg1.Arg1.Variable; } var arg2 = SkipCastExpressions(expression.Arg2); if (arg2 != null) { rValue = arg2.Variable; } if (rValue != null) { rValue = rValue.Canonicalize(); } } } else { rValue = e2.Variable; if (rValue != null) { rValue = rValue.Canonicalize(); } if (rValue == null) { e2 = SkipCastExpressions(firstExpression); rValue = e2.Variable; if (rValue != null) { rValue = rValue.Canonicalize(); } } } //fixme, lvalue and rvalue stuff got weird //Are we directly pointing to the variable? (excluding cast operations) //Expression e2 = SkipCastExpressions(expression); bool isDirect = false; var v2 = e2.Variable; IVariable v2Canon = null; if (v2 != null) { v2Canon = v2.Canonicalize(); if (v2Canon == v2 && !(expression.ExpressionType.IsAssignment() && !expression.ExpressionType.IsDirectAssignment()) && (lookForVariable != null && lookForVariable.DataType == v2.DataType)) { isDirect = true; } else if (v2Canon == v2 && (lookForVariable != null && lookForVariable.DataType == v2.DataType) && (expression.ExpressionType == Instruction.DG_PLUSA || expression.ExpressionType == Instruction.DG_MINUSA || expression.ExpressionType == Instruction.DG_ASSIGN)) { isDirect = true; } } if (0 != (mode & VariableTraceMode.DirectCopies)) { if (isDirect && (lValue == lookFor || v2 == lookFor || rValue == lookFor)) { EnqueueVariable(v2); if (!(lookFor.DataType == DataType.Functype && lValue != null && lValue.DataType != DataType.Functype)) { EnqueueVariable(lValue); } if (!(lookFor.DataType == DataType.Functype && rValue != null && rValue.DataType != DataType.Functype)) { EnqueueVariable(rValue); } } } if (0 != (mode & VariableTraceMode.Writes)) { if (lValue == lookFor) { TraceExpressionDown(expression); } } if (0 != (mode & VariableTraceMode.Reads)) { var lValueCanon = lValue.Canonicalize(); if (lValueCanon != null) { EnqueueVariable(lValueCanon); } TraceExpressionDown(expression); } }