예제 #1
0
        /// <summary>
        /// Convert some method data into a method signature.
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>Signature</returns>
        MethodSig GetMethodSig(MethodData data)
        {
            TypeSig returnType = ResolveType(data.ReturnType);

            TypeSig[] paramTypes = new TypeSig[data.Parameters.Length];
            for (Int32 i = 0; i < paramTypes.Length; i++)
            {
                paramTypes[i] = ResolveType(data.Parameters[i]);
            }

            UInt32 genericTypeCount = (UInt32)data.GenericArguments.Length;

            MethodSig methodSig;

            if (genericTypeCount == 0)
            {
                if (data.IsStatic)
                {
                    methodSig = MethodSig.CreateStatic(returnType, paramTypes);
                }
                else
                {
                    methodSig = MethodSig.CreateInstance(returnType, paramTypes);
                }
            }
            else
            {
                if (data.IsStatic)
                {
                    methodSig = MethodSig.CreateStaticGeneric(genericTypeCount, returnType, paramTypes);
                }
                else
                {
                    methodSig = MethodSig.CreateInstanceGeneric(genericTypeCount, returnType, paramTypes);
                }
            }

            return(methodSig);
        }
예제 #2
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            /*
             *  {IL_0046: ldarg.0}
             *  {IL_0047: ldarg.0}
             *  {IL_0048: call UnityEngine.GameObject UnityEngine.Component::get_gameObject()}
             *  {IL_004D: callvirt TrainerManager UnityEngine.GameObject::AddComponent<TrainerManager>()}
             *  {IL_0052: stfld TrainerManager GameManager::trainerManager}
             *  {IL_0057: ret}
             */

            var gameManagerTypeDef    = targetModule.Find("GameManager", true);
            var trainerManagerTypeDef = targetModule.Find("TrainerManager", true);

            var trainerManagerFieldDef = InjectionHelpers.AddField(targetModule, "GameManager", "trainerManager", trainerManagerTypeDef.ToTypeSig(), FieldAttributes.Private);

            if (trainerManagerFieldDef == null)
            {
                return(await Task.FromResult(1));
            }

            var gameManagerStartMethodDef = gameManagerTypeDef.FindMethod("Start");

            var unityEngine = targetModule.GetAssemblyRef(new UTF8String("UnityEngine"));
            var unityEngineComponentTypeRefUser  = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("Component"), unityEngine);
            var unityEngineGameObjectTypeRefUser = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("GameObject"), unityEngine);

            var gameObjectTypeSig = unityEngineGameObjectTypeRefUser.ToTypeSig();

            var getGameObjectMethodSig    = MethodSig.CreateInstance(gameObjectTypeSig);
            var gameManagerStartMethodSig = MethodSig.CreateInstanceGeneric(1, new GenericMVar(0, gameManagerStartMethodDef));

            // {UnityEngine.GameObject UnityEngine.Component::get_gameObject()}
            var getGameObjectMethodRefUser = new MemberRefUser(targetModule, new UTF8String("get_gameObject"), getGameObjectMethodSig, unityEngineComponentTypeRefUser);

            // {TrainerManager UnityEngine.GameObject::AddComponent<TrainerManager>()}
            var addComponentMethodRefUser = new MemberRefUser(targetModule, new UTF8String("AddComponent"), gameManagerStartMethodSig, unityEngineGameObjectTypeRefUser);

            var trainerManagerGenericInstMethodSig = new GenericInstMethodSig(trainerManagerTypeDef.ToTypeSig());
            var addComponentMethodSpecUser         = new MethodSpecUser(addComponentMethodRefUser, trainerManagerGenericInstMethodSig);

            var trainerManagerDefinitionMethodInstructions = new List <Instruction>
            {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Call, getGameObjectMethodRefUser),
                new Instruction(OpCodes.Callvirt, addComponentMethodSpecUser),
                new Instruction(OpCodes.Stfld, trainerManagerFieldDef),
                new Instruction(OpCodes.Ret),
            };

            var retInstruction = gameManagerStartMethodDef.Body.Instructions.LastOrDefault();

            if (retInstruction != null && retInstruction.OpCode == OpCodes.Ret)
            {
                gameManagerStartMethodDef.Body.Instructions.Remove(retInstruction);
            }

            foreach (var instruction in trainerManagerDefinitionMethodInstructions)
            {
                gameManagerStartMethodDef.Body.Instructions.Add(instruction);
            }

            return(await Task.FromResult(0));
        }
예제 #3
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            // Fetch assembly refs
            var unityEngine = targetModule.GetAssemblyRef("UnityEngine");

            // Fetch target type defs
            var characterActionsTypeDef = targetModule.Find("CharacterActions", true);
            var controllerTypeDef       = targetModule.Find("Controller", true);
            var aiTypeDef = targetModule.Find("AI", true);

            // Fetch target method defs
            var aiStartMethodDef         = aiTypeDef.FindMethod("Start");
            var controllerStartMethodDef = controllerTypeDef.FindMethod("Start");
            var characterActionsCreateWithControllerBindingsMethodDef = characterActionsTypeDef.FindMethod("CreateWithControllerBindings");

            // Fetch target field defs
            var aiGoForGunsFieldDef             = aiTypeDef.FindField("goForGuns");
            var controllerHasControlFieldDef    = controllerTypeDef.FindField("mHasControl");
            var controllerPlayerActionsFieldDef = controllerTypeDef.FindField("mPlayerActions");

            // Fetch type ref users
            var unityEngineComponentTypeRefUser = new TypeRefUser(targetModule, "UnityEngine", "Component", unityEngine);
            var unityEngineBehaviourTypeRefUser = new TypeRefUser(targetModule, "UnityEngine", "Behaviour", unityEngine);

            // Create method ref users
            var getComponentMethodRefUser = new MemberRefUser(targetModule, "GetComponent", MethodSig.CreateInstanceGeneric(1, new GenericMVar(0, aiStartMethodDef)), unityEngineComponentTypeRefUser);
            var setEnabledMethodRefUser   = new MemberRefUser(targetModule, "set_enabled", MethodSig.CreateInstance(targetModule.CorLibTypes.Void, targetModule.CorLibTypes.Boolean), unityEngineBehaviourTypeRefUser);

            // Create method spec users
            var getComponentMethodSpecUser = new MethodSpecUser(getComponentMethodRefUser, new GenericInstMethodSig(aiTypeDef.ToTypeSig()));

            /*
             *
             *  {IL_00C3: ldarg.0}
             *  {IL_00C4: call AI UnityEngine.Component::GetComponent<AI>()}
             *  {IL_00C9: ldc.i4.1}
             *  {IL_00CA: callvirt System.Void UnityEngine.Behaviour::set_enabled(System.Boolean)}
             *
             */

            var controllerStartInstructionSignature = new List <Instruction> {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Call, getComponentMethodSpecUser),
                new Instruction(OpCodes.Ldc_I4_1),
                new Instruction(OpCodes.Callvirt, setEnabledMethodRefUser)
            };

            var matchedControllerStartMethodInstructions = InjectionHelpers.FetchInstructionsBySigComparerSignature(controllerStartMethodDef.Body.Instructions, controllerStartInstructionSignature);

            if (matchedControllerStartMethodInstructions != null)
            {
                var lastMatchedInstruction = matchedControllerStartMethodInstructions.Last();
                var injectionIndex         = controllerStartMethodDef.Body.Instructions.IndexOf(lastMatchedInstruction) + 1;

                var controllerStartInstructionsToInject = new List <Instruction>
                {
                    new Instruction(OpCodes.Ldarg_0),
                    new Instruction(OpCodes.Call, getComponentMethodSpecUser),
                    new Instruction(OpCodes.Ldc_I4_1),
                    new Instruction(OpCodes.Stfld, aiGoForGunsFieldDef),
                    new Instruction(OpCodes.Ldarg_0),
                    new Instruction(OpCodes.Ldc_I4_1),
                    new Instruction(OpCodes.Stfld, controllerHasControlFieldDef),
                    new Instruction(OpCodes.Ldarg_0),
                    new Instruction(OpCodes.Call, characterActionsCreateWithControllerBindingsMethodDef),
                    new Instruction(OpCodes.Stfld, controllerPlayerActionsFieldDef),
                };

                // Add new instructions after the matched signature
                for (var i = 0; i < controllerStartInstructionsToInject.Count; i++)
                {
                    controllerStartMethodDef.Body.Instructions.Insert(injectionIndex + i, controllerStartInstructionsToInject[i]);
                }

                controllerStartMethodDef.Body.UpdateInstructionOffsets();
            }
            else
            {
                return(await Task.FromResult(1));
            }

            return(await Task.FromResult(0));
        }
예제 #4
0
        IList <MethodSig> PossibleMethodSigs(ITypeDefOrRef declaringType, MethodSig sig, MethodData data)
        {
            // Setup generic types
            IList <TypeSig> typeGenerics = new List <TypeSig>(), methodGenerics = new List <TypeSig>();

            // Add all declaring spec generic types
            TypeSpec declaringSpec = declaringType as TypeSpec;

            if (declaringSpec != null)
            {
                var genericInstSig = declaringSpec.TryGetGenericInstSig();
                foreach (var garg in genericInstSig.GenericArguments)
                {
                    typeGenerics.Add(garg);
                }
            }

            // Add all method generic types
            if (data.HasGenericArguments)
            {
                foreach (var operand in data.GenericArguments)
                {
                    var gtype = this.ResolveType_NoLock(operand.Position);
                    methodGenerics.Add(gtype.ToTypeSig());
                }
            }

            // Todo: Combinations factoring in the possibility that return type might match
            // a generic type
            TypeSig         returnType  = ResolveType(data.ReturnType);
            IList <TypeSig> returnTypes = GenericUtils.PossibleTypeSigs(returnType, typeGenerics, methodGenerics);

            TypeSig[] paramTypes = new TypeSig[data.Parameters.Length];
            for (Int32 i = 0; i < paramTypes.Length; i++)
            {
                paramTypes[i] = ResolveType(data.Parameters[i]);
            }

            UInt32 genericTypeCount = (UInt32)data.GenericArguments.Length;

            IList <MethodSig> signatures = new List <MethodSig>();
            var paramCombos = GenericUtils.CreateGenericParameterCombinations(paramTypes, typeGenerics, methodGenerics);

            foreach (var rType in returnTypes)
            {
                foreach (var combo in paramCombos)
                {
                    var paramCombo = combo.ToArray();

                    MethodSig methodSig;

                    if (genericTypeCount == 0)
                    {
                        if (data.IsStatic)
                        {
                            methodSig = MethodSig.CreateStatic(rType, paramCombo);
                        }
                        else
                        {
                            methodSig = MethodSig.CreateInstance(rType, paramCombo);
                        }
                    }
                    else
                    {
                        if (data.IsStatic)
                        {
                            methodSig = MethodSig.CreateStaticGeneric(genericTypeCount, rType, paramCombo);
                        }
                        else
                        {
                            methodSig = MethodSig.CreateInstanceGeneric(genericTypeCount, rType, paramCombo);
                        }
                    }

                    signatures.Add(methodSig);
                }
            }

            return(signatures);
        }
예제 #5
0
        public static void Run()
        {
            // This is the file that will be created
            string newFileName = "GenericExample3.exe";

            // Create the module
            var mod = new ModuleDefUser("GenericExample3", Guid.NewGuid(),
                                        new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName)));

            // It's a console app
            mod.Kind = ModuleKind.Console;
            // Create the assembly and add the created module to it
            new AssemblyDefUser("GenericExample3", new Version(1, 2, 3, 4)).Modules.Add(mod);

            // Add the startup type. It derives from System.Object.
            TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef);

            startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout |
                                     TypeAttributes.Class | TypeAttributes.AnsiClass;
            // Add the type to the module
            mod.Types.Add(startUpType);

            // Create the entry point method
            MethodDef entryPoint = new MethodDefUser("Main",
                                                     MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String)));

            entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static |
                                    MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
            entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
            // Name the 1st argument (argument 0 is the return type)
            entryPoint.ParamDefs.Add(new ParamDefUser("args", 1));
            // Add the method to the startup type
            startUpType.Methods.Add(entryPoint);
            // Set module entry point
            mod.EntryPoint = entryPoint;

            // Create a type with 2 generic parameters, A and B
            // Would look like: public class GClass<A, B>
            var genericType = new TypeDefUser("My.Namespace", "GClass", mod.CorLibTypes.Object.TypeDefOrRef);

            genericType.Attributes = TypeAttributes.Public | TypeAttributes.AutoLayout |
                                     TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit;
            genericType.GenericParameters.Add(new GenericParamUser(0, GenericParamAttributes.NonVariant, "A"));
            genericType.GenericParameters.Add(new GenericParamUser(1, GenericParamAttributes.NonVariant, "B"));
            // Add generic type to module
            mod.Types.Add(genericType);

            // Note: NestedPublic instead of Public, blank namespace
            // Would look like: public class GSubClass<A, B, C>
            var genericSubType = new TypeDefUser("", "GSubClass", mod.CorLibTypes.Object.TypeDefOrRef);

            genericSubType.Attributes = TypeAttributes.NestedPublic | TypeAttributes.AutoLayout |
                                        TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit;
            // Need to add the 2 generic parameters from the nested-parent class, A and B
            genericSubType.GenericParameters.Add(new GenericParamUser(0, GenericParamAttributes.NonVariant, "A"));
            genericSubType.GenericParameters.Add(new GenericParamUser(1, GenericParamAttributes.NonVariant, "B"));
            // Add a generic parameter specific to this nested class, C
            genericSubType.GenericParameters.Add(new GenericParamUser(2, GenericParamAttributes.NonVariant, "C"));

            // public void GSubClass<A, B, C>.SomeMethod(B arg1, C arg2) { ... }
            // or: public void GSubClass<!0, !1, !2>.SomeMethod(!1, !2) { ... }
            var someMethod = new MethodDefUser("SomeMethod",
                                               MethodSig.CreateInstance(mod.CorLibTypes.Void, new GenericVar(1), new GenericVar(2)));

            someMethod.Attributes     = MethodAttributes.Public;
            someMethod.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
            genericSubType.Methods.Add(someMethod);

            // Create method with a method generic parameter (GenericMVar)
            // public void GSubClass<A, B, C>.SomeOtherMethod<D>(D arg1, A arg2, C arg3) { ... }
            // or: public void GSubClass<!0, !1, !2>.SomeOtherMethod<!!0>(!!0, !0, !2) { ... }
            var someGenericMethod = new MethodDefUser("SomeOtherMethod",
                                                      MethodSig.CreateInstanceGeneric(1, mod.CorLibTypes.Void, new GenericMVar(0), new GenericVar(0), new GenericVar(2)));

            someGenericMethod.Attributes     = MethodAttributes.Public;
            someGenericMethod.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
            // Create GenericParam for !!0
            someGenericMethod.GenericParameters.Add(new GenericParamUser(0, GenericParamAttributes.NonVariant, "D"));
            genericSubType.Methods.Add(someGenericMethod);

            // Add as nested type
            genericType.NestedTypes.Add(genericSubType);

            someMethod.Body = new CilBody();
            someMethod.Body.Instructions.Add(OpCodes.Ret.ToInstruction());

            someGenericMethod.Body = new CilBody();
            someGenericMethod.Body.Instructions.Add(OpCodes.Ret.ToInstruction());

            entryPoint.Body = new CilBody();
            entryPoint.Body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction());
            entryPoint.Body.Instructions.Add(OpCodes.Ret.ToInstruction());

            mod.Write(newFileName);
        }