Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }