private bool ProcessOpCall_retval2(MethodDefinition currentMethod, Instruction callInstruction, MethodReference callMethodRef, string methodOpName) { var ILprocessorEx = new ILProcessorEx(currentMethod); if (Match_Stloc(callInstruction.Next)) { Instruction StlocInstruction = callInstruction.Next; int n; Instruction newLdlocaInstruction = Stloc2Ldloca(ILprocessorEx, StlocInstruction, out n); Instruction op_outInstruction = GetMethodRefOp2(ILprocessorEx, callMethodRef, methodOpName); if (op_outInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_outInstruction.Operand).FullName); ILprocessorEx.Remove(StlocInstruction); ILprocessorEx.InsertBefore(callInstruction, newLdlocaInstruction); // replace 'valuetype Op(...)' with 'void Op(..., out valuetype)' ILprocessorEx.Replace(callInstruction, op_outInstruction); return(true); } return(false); }
private static Instruction GetMethodRefOp2(ILProcessorEx ILprocessorEx, MethodReference callMethodRef, string methodOpName) { MethodReference MethodDefOp = null; var typeDef = callMethodRef.DeclaringType.Resolve(); foreach (var method in typeDef.Methods) { if (method.HasThis) { continue; } if (method.Name != methodOpName) { continue; } if (method.ReturnType.FullName != "System.Void") // { continue; } //if (callMethodRef.ReturnType.FullName) // // continue; if ((method.Parameters.Count - 1) != callMethodRef.Parameters.Count) { continue; } var match = true; for (int i = 0; i < callMethodRef.Parameters.Count; i++) { if (method.Parameters[i].ParameterType.IsByReference != callMethodRef.Parameters[i].ParameterType.IsByReference) { match = false; continue; } } if (match != true) { continue; } //if (method.Parameters[0].ParameterType.IsByReference == false && // method.Parameters[1].ParameterType.IsByReference == true) MethodDefOp = method; break; } if (MethodDefOp == null) { //method not found return(null); } var methodRefOp = callMethodRef.DeclaringType.Module.ImportReference(MethodDefOp); var op_outInstruction = ILprocessorEx.Create(OpCodes.Call, methodRefOp); return(op_outInstruction); }
private static Instruction Stloc2Ldloca(ILProcessorEx ILprocessorEx, Instruction StlocInstruction, out int n) { if (StlocInstruction.OpCode.Code == Code.Stloc) { var varDef = StlocInstruction.Operand as VariableDefinition; n = varDef.Index; return(ILprocessorEx.Create(OpCodes.Ldloca, ILprocessorEx.Method.Body.Variables[n])); } else if (StlocInstruction.OpCode.Code == Code.Stloc_S) { var varDef = StlocInstruction.Operand as VariableDefinition; n = varDef.Index; } else if (StlocInstruction.OpCode.Code == Code.Stloc_0) { n = 0; } else if (StlocInstruction.OpCode.Code == Code.Stloc_1) { n = 1; } else if (StlocInstruction.OpCode.Code == Code.Stloc_2) { n = 2; } else if (StlocInstruction.OpCode.Code == Code.Stloc_3) { n = 3; } else { throw new InvalidOperationException(); } return(ILprocessorEx.Create(OpCodes.Ldloca_S, ILprocessorEx.Method.Body.Variables[n])); }
private static Instruction Ldarg2Ldarga(ILProcessorEx ILprocessorEx, Instruction LdargInstruction, out int n) { if (LdargInstruction.OpCode.Code == Code.Ldarg) { var varDef = LdargInstruction.Operand as VariableDefinition; n = varDef.Index; return(ILprocessorEx.Create(OpCodes.Ldarga, ILprocessorEx.Method.Parameters[n])); } else if (LdargInstruction.OpCode.Code == Code.Ldarg_S) { var varDef = LdargInstruction.Operand as VariableDefinition; n = varDef.Index; } else if (LdargInstruction.OpCode.Code == Code.Ldarg_0) { n = 0; } else if (LdargInstruction.OpCode.Code == Code.Ldarg_1) { n = 1; } else if (LdargInstruction.OpCode.Code == Code.Ldarg_2) { n = 2; } else if (LdargInstruction.OpCode.Code == Code.Ldarg_3) { n = 3; } else { throw new InvalidOperationException(); } return(ILprocessorEx.Create(OpCodes.Ldarga_S, ILprocessorEx.Method.Parameters[n])); }
private bool ProcessOpCall_retout(MethodDefinition currentMethod, Instruction callInstruction, MethodReference callMethodRef, string methodOpName) { var ILprocessorEx = new ILProcessorEx(currentMethod); return(false); }
private bool ProcessOpCall_retval(MethodDefinition currentMethod, Instruction callInstruction, MethodReference callMethodRef, string methodOpName) { var ILprocessorEx = new ILProcessorEx(currentMethod); int currentParamIdx = callMethodRef.Parameters.Count - 1; // for now we support only operators (with two arguments). currentParamIdx has to be #1. if (currentParamIdx != 1) { throw new InvalidOperationException(); } var currentParam = callMethodRef.Parameters[currentParamIdx]; var isCurrentParamByRef = currentParam.ParameterType.IsByReference; for (var instruction = callInstruction.Previous; instruction != null; instruction = instruction.Previous) { //TODO: check if there is a branch target between instruction and callInstruction and quit // break; if (isCurrentParamByRef == false) { if (Match_Ldloc(instruction)) { Instruction LdlocInstruction = instruction; int n; Instruction newLdlocaInstruction = Ldloc2Ldloca(ILprocessorEx, LdlocInstruction, out n); Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); // replace 'Ldloc' with 'Ldloca' ILprocessorEx.Replace(LdlocInstruction, newLdlocaInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2,vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } else if (Match_Ldarg(instruction)) { Instruction LdargInstruction = instruction; int n; Instruction newLdargaInstruction = Ldarg2Ldarga(ILprocessorEx, LdargInstruction, out n); // check validity of parameter n var targParam = currentMethod.Parameters[n]; if (targParam.ParameterType.IsByReference == true) { throw new InvalidOperationException(); } Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); // replace 'Ldarg' with 'Ldarga' ILprocessorEx.Replace(LdargInstruction, newLdargaInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2, ref vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } else if (Match_Ldobj(instruction)) { Instruction LdobjInstruction = instruction; var ldtype = LdobjInstruction.Operand; var type = callMethodRef.Parameters[1]; if (Match_Ldarg(LdobjInstruction.Previous)) { Instruction LdargInstruction = LdobjInstruction.Previous; int n; Instruction newLdargaInstruction = Ldarg2Ldarga(ILprocessorEx, LdargInstruction, out n); // check validity of parameter n var targParam = currentMethod.Parameters[n]; if (targParam.ParameterType.IsByReference == false) { throw new InvalidOperationException(); } Instruction op_refInstruction = GetMethodRefOp(ILprocessorEx, callMethodRef, methodOpName, currentParamIdx); if (op_refInstruction == null) { return(false); } var callOffset = callInstruction.Offset; Console.WriteLine(@"Patching " + callMethodRef.FullName + @" (0x" + callInstruction.Offset.ToString("X") + ")"); Console.WriteLine(@" ...into " + ((MethodReference)op_refInstruction.Operand).FullName); ILprocessorEx.Remove(LdobjInstruction); // replace 'vector2 Add(vector2,vector2)' with 'vector2 Add(vector2, ref vector2)' ILprocessorEx.Replace(callInstruction, op_refInstruction); return(true); } } return(false); } else // (isCurrentParamByRef == true) { if (Match_Ldloca(instruction)) { Instruction LdlocaInstruction = instruction; // argument sucesfully matched. Move to next argument. if (currentParamIdx == 0) { // no more arguments to match. return(false); } else { // Move to next argument. currentParamIdx--; currentParam = callMethodRef.Parameters[currentParamIdx]; isCurrentParamByRef = currentParam.ParameterType.IsByReference; continue; } } return(false); } if (Match_Nop(instruction)) { continue; } if (Match_Break(instruction)) { continue; } // Unkwown instruction. quit break; } return(false); }