Ejemplo n.º 1
0
        private Instruction ReplaceLoadAddressByName(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var stack        = Analysis[instruction.Previous];
            var variableName = stack.Head.Item2;

            if (!variableName.IsConstant)
            {
                throw new Exception(string.Format("Expected constant values to be passed to LoadAddressByName used in {0}", ilProcessor.Body.Method.FullName));
            }

            var variable = ilProcessor.Body.Variables.FirstOrDefault(v => v.Name == variableName.Value);

            if (variable != null)
            {
                var ldloc = Instruction.Create(OpCodes.Ldloca, variable);
                ilProcessor.InsertAfter(instruction, ldloc);
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(ldloc.Next);
            }

            var parameter = ilProcessor.Body.Method.Parameters.FirstOrDefault(p => p.Name == variableName.Value);

            if (parameter != null)
            {
                var ldarg = Instruction.Create(OpCodes.Ldarga, parameter);
                ilProcessor.InsertAfter(instruction, ldarg);
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(ldarg.Next);
            }

            throw new Exception(string.Format("Variable \"{0}\", used in method {1}, not found!", variableName.Value, ilProcessor.Body.Method.FullName));
        }
Ejemplo n.º 2
0
        private void ReplaceVariable(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var callingMethod = ilProcessor.Body.Method;
            var module        = callingMethod.Module;

            var name = Analysis[instruction.Previous].Head.Item2.Value as string;


            var variable = callingMethod.Body.Variables.FirstOrDefault(var => var.Name == name);

            if (variable == null)
            {
                throw new Exception(string.Format("Could not find variable '{0}'.", name));
            }

            var localVariableInfo = Reference.ParseTypeReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.LocalVariableInfo");

            var methodReference = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                Silk.Loom.CecilNames.MethodName(callingMethod));

            var getMethodFromHandle = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.MethodBase::GetMethodFromHandle(System.RuntimeMethodHandle)");

            var getMethodBody = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.MethodBase::GetMethodBody()");

            var get_localVariables = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.MethodBody::get_LocalVariables()");

            var get_ilist_item = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Collections.Generic.IList`1<System.Reflection.LocalVariableInfo>::get_Item(System.Int32)");

            var insert_before = instruction.Next;

            // Push calling method onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, methodReference));
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getMethodFromHandle));
            // Get method body
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Callvirt, getMethodBody));
            // Get local variable array
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, get_localVariables));
            // Push variable index onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldc_I4, variable.Index));
            // Get local variable
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Callvirt, get_ilist_item));

            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
        }
Ejemplo n.º 3
0
        private void ReplaceParameter(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var callingMethod = ilProcessor.Body.Method;
            var module        = callingMethod.Module;

            var name = Analysis[instruction.Previous].Head.Item2.Value as string;

            var parameter = callingMethod.Parameters.FirstOrDefault(var => var.Name == name);

            if (parameter == null)
            {
                throw new Exception(string.Format("Could not find parameter '{0}'.", name));
            }

            var parameterInfo = Reference.ParseTypeReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.ParameterInfo");

            var methodReference = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                Silk.Loom.CecilNames.MethodName(callingMethod));

            var getMethodFromHandle = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.MethodBase::GetMethodFromHandle(System.RuntimeMethodHandle)");

            var getParameters = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Reflection.MethodBase::GetParameters()");

            var insert_before = instruction.Next;

            // Push calling method onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, methodReference));
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getMethodFromHandle));
            // Get parameter array
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Callvirt, getParameters));
            // Push parameter index onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldc_I4, parameter.Index));
            // Get local variable
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldelem_Any, parameterInfo));

            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
        }
Ejemplo n.º 4
0
        private void ReplaceType(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var callingMethod = ilProcessor.Body.Method;
            var module        = callingMethod.Module;

            var name = Analysis[instruction.Previous].Head.Item2.Value as string;

            var typeReference = Reference.ParseTypeReference(
                Reference.Scope.NewMethodScope(callingMethod), name);

            var getTypeFromHandle = Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)");

            var insert_before = instruction.Next;

            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, typeReference));
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getTypeFromHandle));
            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
        }
Ejemplo n.º 5
0
        private Instruction ReplaceDeclareLocal(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var stack = Analysis[instruction.Previous];
            var name  = stack.Head.Item2;
            var type  = stack.Tail.Head.Item2;

            if (name.IsConstant && type.IsConstant)
            {
                var variableType = Reference.ParseTypeReference(
                    Reference.Scope.NewMethodScope(ilProcessor.Body.Method), type.Value);

                ilProcessor.Body.Variables.Add(new VariableDefinition(name.Value, variableType));
            }
            else
            {
                throw new Exception(string.Format("Expected constant values to be passed to DeclareLocal used in method {0}", ilProcessor.Body.Method.FullName));
            }

            Instruction next = instruction.Next;

            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
            return(next);
        }
Ejemplo n.º 6
0
        protected override Instruction Visit(ILProcessor ilProcessor, Instruction instruction)
        {
            var label = Analysis[instruction.Previous].Head;

            if (!label.Item2.IsConstant)
            {
                Console.WriteLine("Label call must be used with a string literal.");
                Environment.Exit(1);
            }

            var jump_location = instruction.Next;

            if (jump_location == null)
            {
                jump_location = Instruction.Create(OpCodes.Nop);
                ilProcessor.InsertAfter(instruction, jump_location);
            }

            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);

            Labels.Add(Tuple.Create(ilProcessor.Body, label.Item2.Value), jump_location);

            return(jump_location.Next);
        }
Ejemplo n.º 7
0
        Instruction ReplaceCalli(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            //public static unsafe void Calli(
            //System.Runtime.InteropServices.CallingConvention callingConvention, Type returnType, Type arg0, ...)
            var stack = Analysis[instruction.Previous];
            Tuple <Instruction, StackAnalyser.StackEntry> entry;

            var module = ilProcessor.Body.Method.Module;

            var args = new List <Tuple <Instruction, StackAnalyser.StackEntry> >();

            for (int i = 0; i < calledMethod.Parameters.Count - 2; ++i)
            {
                entry = stack.Head;
                stack = stack.Tail;
                args.Add(entry);
            }
            args.Reverse();

            entry = stack.Head;
            stack = stack.Tail;
            var returnType = entry;

            entry = stack.Head;
            stack = stack.Tail;
            var callingConvention = entry.Item2;

            Mono.Cecil.MethodCallingConvention methodCallingConvention;
            if (callingConvention.IsConstant)
            {
                switch ((System.Runtime.InteropServices.CallingConvention)callingConvention.Value)
                {
                case System.Runtime.InteropServices.CallingConvention.Cdecl:
                    methodCallingConvention = MethodCallingConvention.C;
                    break;

                case System.Runtime.InteropServices.CallingConvention.FastCall:
                    methodCallingConvention = MethodCallingConvention.FastCall;
                    break;

                case System.Runtime.InteropServices.CallingConvention.StdCall:
                    methodCallingConvention = MethodCallingConvention.StdCall;
                    break;

                case System.Runtime.InteropServices.CallingConvention.ThisCall:
                    methodCallingConvention = MethodCallingConvention.ThisCall;
                    break;

                case System.Runtime.InteropServices.CallingConvention.Winapi:
                    methodCallingConvention = MethodCallingConvention.StdCall;
                    break;

                default:
                    methodCallingConvention = MethodCallingConvention.Default;
                    break;
                }
            }
            else
            {
                Console.WriteLine("Calling convention passed to Calli is not a constant expression.");
                var next = instruction.Next;
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(next);
            }

            TypeReference returnTypeReference = null;

            if (returnType.Item2.IsConstant)
            {
                Type retTy = returnType.Item2.Value;
                returnTypeReference = module.Import(retTy);
            }
            else if (returnType.Item1.OpCode == OpCodes.Call && returnType.Item1.Operand is MethodReference && (returnType.Item1.Operand as MethodReference).Name == "GetTypeFromHandle")
            {
                var ldtoken_stack = Analysis[returnType.Item1.Previous];
                var ldtoken       = ldtoken_stack.Head;

                returnTypeReference = ldtoken.Item1.Operand as TypeReference;
            }

            if (returnTypeReference == null)
            {
                Console.WriteLine("Return type passed to Calli is not a constant expression.");
                var next = instruction.Next;
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(next);
            }

            TypeReference[] parameterTypesArray = new TypeReference[args.Count];
            for (int i = 0; i < args.Count; ++i)
            {
                var arg = args[i];

                if (arg.Item2.IsConstant)
                {
                    parameterTypesArray[i] = module.Import((Type)arg.Item2.Value);
                }
                else if (arg.Item1.OpCode == OpCodes.Call && arg.Item1.Operand is MethodReference && (arg.Item1.Operand as MethodReference).Name == "GetTypeFromHandle")
                {
                    var ldtoken_stack = Analysis[arg.Item1.Previous];
                    var ldtoken       = ldtoken_stack.Head;

                    parameterTypesArray[i] = ldtoken.Item1.Operand as TypeReference;
                }
            }

            if (parameterTypesArray.Any(ty => ty == null))
            {
                Console.WriteLine("Type passed to Calli is not a constant expression.");
                var next = instruction.Next;
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(next);
            }

            var callSite = new CallSite(returnTypeReference);

            callSite.CallingConvention = methodCallingConvention;
            foreach (var parameterType in parameterTypesArray)
            {
                callSite.Parameters.Add(new ParameterDefinition(parameterType));
            }

            {
                var calli = Instruction.Create(OpCodes.Calli, callSite);
                ilProcessor.InsertAfter(instruction, calli);
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                return(calli.Next);
            }
        }
Ejemplo n.º 8
0
        Instruction ReplaceInstruction(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var nextInstruction = instruction.Next;

            var    opcodeField = OpcodesFields.FirstOrDefault(info => info.Name == calledMethod.Name);
            OpCode opcode;

            if (opcodeField == null)
            {
                // Special case stelem because we don't want to call it Stelem_Any
                if (calledMethod.Name == "Stelem")
                {
                    opcode = OpCodes.Stelem_Any;
                }
                // Special case ldelem because we don't want to call it Ldelem_Any
                else if (calledMethod.Name == "Ldelem")
                {
                    opcode = OpCodes.Ldelem_Any;
                }
                else
                {
                    throw new Exception(string.Format("Unknown opcode {0}, ignoring", calledMethod.Name));
                }
            }
            else
            {
                opcode = (OpCode)opcodeField.GetValue(null);
            }

            if (calledMethod is GenericInstanceMethod)
            {
                var generic_method = calledMethod as GenericInstanceMethod;
                var typetok        = generic_method.GenericArguments[0];
                StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, typetok));
            }
            else
            {
                if (calledMethod.Parameters.Count == 0)
                {
                    StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode));
                }
                if (calledMethod.Parameters.Count == 1)
                {
                    var stack = Analysis[instruction.Previous];

                    var operandEntry = stack.Head;
                    StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, operandEntry.Item1, Analysis);

                    if (!operandEntry.Item2.IsConstant)
                    {
                        Console.WriteLine("Inline ({0}) without constant argument, ignoring.", opcode);
                        StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
                        return(nextInstruction);
                    }

                    var operand = operandEntry.Item2.Value;

                    if (opcode.OperandType == OperandType.InlineVar)
                    {
                        var variable = ilProcessor.Body.Variables[(int)operand];
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, variable));
                    }
                    else if (opcode.OperandType == OperandType.InlineArg)
                    {
                        var variable = ilProcessor.Body.Method.Parameters[(int)operand];
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, variable));
                    }
                    else if (opcode.OperandType == OperandType.InlineBrTarget)
                    {
                        var jump = Labels.GetJumpLocation(ilProcessor.Body, (string)operand);
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, jump));
                    }
                    else if (opcode.OperandType == OperandType.ShortInlineI)
                    {
                        var integer = (byte)operand;
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer));
                    }
                    else if (opcode.OperandType == OperandType.InlineI)
                    {
                        var integer = (int)operand;
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer));
                    }
                    else if (opcode.OperandType == OperandType.InlineI8)
                    {
                        var integer = (long)operand;
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, integer));
                    }
                    else if (opcode.OperandType == OperandType.ShortInlineR)
                    {
                        var real = (float)operand;
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, real));
                    }
                    else if (opcode.OperandType == OperandType.InlineR)
                    {
                        var real = (double)operand;
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, real));
                    }
                    else if (opcode.OperandType == OperandType.InlineSwitch)
                    {
                        var target_string = (string)operand;
                        var targets       = target_string.Split(';').Select(label => Labels.GetJumpLocation(ilProcessor.Body, label)).ToArray();

                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, targets));
                    }
                    else if (opcode.OperandType == OperandType.InlineField)
                    {
                        var module   = ilProcessor.Body.Method.Module;
                        var field    = (string)operand;
                        var fieldref = Reference.ParseFieldReference(
                            Reference.Scope.NewMethodScope(ilProcessor.Body.Method), field);
                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, fieldref));
                    }
                    else if (opcode.OperandType == OperandType.InlineMethod)
                    {
                        var module    = ilProcessor.Body.Method.Module;
                        var method    = (string)operand;
                        var methodref = Reference.ParseMethodReference(
                            Reference.Scope.NewMethodScope(ilProcessor.Body.Method), method);

                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, methodref));
                    }
                    else if (opcode.OperandType == OperandType.InlineType)
                    {
                        var module  = ilProcessor.Body.Method.Module;
                        var type    = (string)operand;
                        var typeref = Reference.ParseTypeReference(
                            Reference.Scope.NewMethodScope(ilProcessor.Body.Method), type);

                        StackAnalyser.ReplaceInstruction(ilProcessor, instruction, Instruction.Create(opcode, typeref));
                    }
                    else
                    {
                        throw new ArgumentException(string.Format("Inline opcode ({0}) without argument, ignoring.", opcode));
                    }
                }
                else
                {
                    if (opcode.OperandType == OperandType.InlineSig)
                    {
                        return(ReplaceCalli(ilProcessor, instruction, calledMethod));
                    }
                }
            }

            return(nextInstruction);
        }
Ejemplo n.º 9
0
        protected override Instruction Visit(ILProcessor ilProcessor, Instruction instruction)
        {
            var calledMethod = instruction.Operand as MethodReference;
            var next         = instruction.Next;

            if (calledMethod.Name == "KeepAlive")
            {
                StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
            }
            else if (calledMethod.Name == "Load" || calledMethod.Name == "Peek")
            {
                /*
                 * The compiler will have inserted the appropriate load
                 * instructions to put the value on the operand stack in
                 * preperation to call Load<T>. Thus all we have to do is
                 * remove the call instruction, that keeps the value on the
                 * stack instead of popping it for the call.
                 */
                StackAnalyser.RemoveInstruction(ilProcessor, instruction);
            }
            else if (calledMethod.Name == "LoadAddress")
            {
                /*
                 * The compiler will have inserted the a load instruction, we
                 * need to change it to the appropriate load address instruction.
                 */
                return(ReplaceLoadAddress(ilProcessor, instruction, calledMethod));
            }
            else if (calledMethod.Name == "Store")
            {
                /*
                 * The compiler will have inserted instructions to load the
                 * addr of the location we want to store to. We need to look
                 * at these instructions and replace them with the appropriate
                 * standard store instruction. We then remove the call to Store.
                 */

                return(ReplaceStore(ilProcessor, instruction, calledMethod));
            }
            else if (calledMethod.Name == "LoadByName")
            {
                return(ReplaceLoadByName(ilProcessor, instruction, calledMethod));
            }
            else if (calledMethod.Name == "StoreByName")
            {
                return(ReplaceStoreByName(ilProcessor, instruction, calledMethod));
            }
            else if (calledMethod.Name == "LoadAddressByName")
            {
                return(ReplaceLoadAddressByName(ilProcessor, instruction, calledMethod));
            }
            else if (calledMethod.Name == "DeclareLocal")
            {
                return(ReplaceDeclareLocal(ilProcessor, instruction, calledMethod));
            }
            else
            {
                return(ReplaceInstruction(ilProcessor, instruction, calledMethod));
            }

            return(next);
        }
Ejemplo n.º 10
0
        private void ReplaceProperty(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod)
        {
            var callingMethod = ilProcessor.Body.Method;
            var module        = callingMethod.Module;

            var name = Analysis[instruction.Previous].Head.Item2.Value as string;

            var propertyReference = Silk.Loom.Reference.ParsePropertyReference(Reference.Scope.NewMethodScope(callingMethod), name);

            var systemType = Silk.Loom.Reference.ParseTypeReference(Reference.Scope.NewMethodScope(callingMethod), "System.Type");

            var getTypeFromHandle = Silk.Loom.Reference.ParseMethodReference(
                Reference.Scope.NewMethodScope(callingMethod),
                "System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)");

            MethodReference getProperty;

            if (propertyReference.Parameters.Count != 0)
            {
                getProperty = Silk.Loom.Reference.ParseMethodReference(
                    Reference.Scope.NewMethodScope(callingMethod),
                    "System.Type::GetProperty(System.String,System.Type,System.Type[])");
            }
            else
            {
                getProperty = Silk.Loom.Reference.ParseMethodReference(
                    Reference.Scope.NewMethodScope(callingMethod),
                    "System.Type::GetProperty(System.String,System.Type)");
            }

            var insert_before = instruction.Next;

            // Push Declaring Type onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, propertyReference.DeclaringType));
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getTypeFromHandle));
            // Push name onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldstr, propertyReference.Name));
            // Push return type onto stack
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, propertyReference.PropertyType));
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getTypeFromHandle));
            if (propertyReference.Parameters.Count != 0)
            {
                // Push property array onto stack
                ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldc_I4, propertyReference.Parameters.Count));
                ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Newarr, systemType));
                // Assign property elems
                for (int i = 0; i < propertyReference.Parameters.Count; ++i)
                {
                    var param_type = propertyReference.Parameters[i].ParameterType;
                    // Duplicate the array value
                    ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Dup));
                    ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldc_I4, i));
                    ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Ldtoken, param_type));
                    ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getTypeFromHandle));
                    ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Stelem_Any, systemType));
                }
            }
            // Call GetProperty
            ilProcessor.InsertBefore(insert_before, Instruction.Create(OpCodes.Call, getProperty));

            StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis);
        }