Пример #1
0
        static bool injectGenericMethod(AssemblyDefinition assembly, MethodDefinition method, HotfixFlagInTool hotfixType, FieldReference stateTable)
        {
            var type = method.DeclaringType;

            bool isFinalize = (method.Name == "Finalize" && method.IsSpecialName);
            bool isIntKey   = hotfixType.HasFlag(HotfixFlagInTool.IntKey) && !type.HasGenericParameters;
            //isIntKey = !type.HasGenericParameters;

            FieldReference     fieldReference = null;
            VariableDefinition injection      = null;

            if (!isIntKey)
            {
                var luaDelegateName = getDelegateName(method);
                if (luaDelegateName == null)
                {
                    Error("too many overload!");
                    return(false);
                }

                FieldDefinition fieldDefinition = new FieldDefinition(luaDelegateName, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private,
                                                                      delegateBridgeType);
                type.Fields.Add(fieldDefinition);

                fieldReference = fieldDefinition.GetGeneric();
            }

            injection = new VariableDefinition(delegateBridgeType);
            method.Body.Variables.Add(injection);

            int param_start = method.IsStatic ? 0 : 1;
            int param_count = method.Parameters.Count + param_start;
            var insertPoint = method.Body.Instructions[0];
            var processor   = method.Body.GetILProcessor();

            if (method.IsConstructor)
            {
                insertPoint = findNextRet(method.Body.Instructions, insertPoint);
            }

            bool isStateful = hotfixType.HasFlag(HotfixFlagInTool.Stateful);

            while (insertPoint != null)
            {
                if (isIntKey)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, bridgeIndexByKey.Count));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, hotfixFlagGetter));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Brfalse, insertPoint));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, bridgeIndexByKey.Count));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, delegateBridgeGetter));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stloc, injection));
                }
                else
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldsfld, fieldReference));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stloc, injection));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Brfalse, insertPoint));
                }

                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));

                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, invokeSessionStart));

                bool statefulConstructor = isStateful && method.IsConstructor && !method.IsStatic;

                TypeReference returnType = statefulConstructor ? luaTableType : method.ReturnType;

                bool isVoid = returnType.FullName == "System.Void";

                int outCout = 0;

                for (int i = 0; i < param_count; i++)
                {
                    if (i == 0 && !method.IsStatic)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
                        if (isStateful && !method.IsConstructor)
                        {
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldfld, stateTable));
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, luaTableType)));
                        }
                        else
                        {
                            if (type.IsValueType)
                            {
                                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldobj, method.DeclaringType.GetGeneric()));
                            }
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, method.DeclaringType.GetGeneric())));
                        }
                    }
                    else
                    {
                        var param = method.Parameters[i - param_start];
                        if (param.ParameterType.IsByReference)
                        {
                            outCout++;
                        }
                        if (!param.IsOut)
                        {
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));

                            if (i < ldargs.Length)
                            {
                                processor.InsertBefore(insertPoint, processor.Create(ldargs[i]));
                            }
                            else if (i < 256)
                            {
                                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_S, (byte)i));
                            }
                            else
                            {
                                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg, (short)i));
                            }

                            var paramType = param.ParameterType;

                            if (param.ParameterType.IsByReference)
                            {
                                paramType = ((ByReferenceType)paramType).ElementType;
                                if (paramType.IsValueType || paramType.IsGenericParameter)
                                {
                                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldobj, paramType));
                                }
                                else
                                {
                                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldind_Ref));
                                }
                            }
                            if (i == param_count - 1 && param.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.ParamArrayAttribute"))
                            {
                                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParams, ((ArrayType)paramType).ElementType)));
                            }
                            else
                            {
                                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, paramType)));
                            }
                        }
                    }
                }

                int outStart = (isVoid ? 0 : 1);

                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, outCout + outStart));
                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, functionInvoke));

                int outPos = outStart;
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    if (method.Parameters[i].ParameterType.IsByReference)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, outPos));
                        int arg_pos = param_start + i;
                        if (arg_pos < ldargs.Length)
                        {
                            processor.InsertBefore(insertPoint, processor.Create(ldargs[arg_pos]));
                        }
                        else if (arg_pos < 256)
                        {
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_S, (byte)arg_pos));
                        }
                        else
                        {
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg, (short)arg_pos));
                        }
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(outParam,
                                                                                                                 ((ByReferenceType)method.Parameters[i].ParameterType).ElementType)));
                        outPos++;
                    }
                }
                if (statefulConstructor)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
                }
                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                if (isVoid)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, invokeSessionEnd));
                }
                else
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, MakeGenericMethod(invokeSessionEndWithResult, returnType)));
                }
                if (statefulConstructor)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
                }
                if (isFinalize && isStateful)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldnull));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
                }
                if (!method.IsConstructor && !isFinalize)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ret));
                }

                if (!method.IsConstructor)
                {
                    break;
                }
                insertPoint = findNextRet(method.Body.Instructions, insertPoint);
            }

            if (isFinalize)
            {
                method.Body.ExceptionHandlers[0].TryStart = method.Body.Instructions[0];
            }

            return(true);
        }
Пример #2
0
        static bool injectMethod(AssemblyDefinition assembly, MethodDefinition method, HotfixFlagInTool hotfixType, FieldReference stateTable)
        {
            var type = method.DeclaringType;

            bool isFinalize = (method.Name == "Finalize" && method.IsSpecialName);

            MethodReference invoke = null;

            int param_count = method.Parameters.Count + (method.IsStatic ? 0 : 1);

            if (!findHotfixDelegate(assembly, method, out invoke, hotfixType))
            {
                Error("can not find delegate for " + method.DeclaringType + "." + method.Name + "! try re-genertate code.");
                return(false);
            }

            if (invoke == null)
            {
                throw new Exception("unknow exception!");
            }

            FieldReference     fieldReference = null;
            VariableDefinition injection      = null;
            bool isIntKey = hotfixType.HasFlag(HotfixFlagInTool.IntKey) && !type.HasGenericParameters;

            //isIntKey = !type.HasGenericParameters;

            if (!isIntKey)
            {
                injection = new VariableDefinition(delegateBridgeType);
                method.Body.Variables.Add(injection);

                var luaDelegateName = getDelegateName(method);
                if (luaDelegateName == null)
                {
                    Error("too many overload!");
                    return(false);
                }

                FieldDefinition fieldDefinition = new FieldDefinition(luaDelegateName, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private,
                                                                      delegateBridgeType);
                type.Fields.Add(fieldDefinition);
                fieldReference = fieldDefinition.GetGeneric();
            }

            bool isStateful          = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
            bool ignoreValueType     = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);
            bool statefulConstructor = isStateful && method.IsConstructor && !method.IsStatic;

            var insertPoint = method.Body.Instructions[0];
            var processor   = method.Body.GetILProcessor();

            if (method.IsConstructor)
            {
                insertPoint = findNextRet(method.Body.Instructions, insertPoint);
            }

            while (insertPoint != null)
            {
                if (isIntKey)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, bridgeIndexByKey.Count));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, hotfixFlagGetter));
                }
                else
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldsfld, fieldReference));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stloc, injection));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                }
                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Brfalse, insertPoint));

                if (statefulConstructor)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
                }
                if (isIntKey)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, bridgeIndexByKey.Count));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, delegateBridgeGetter));
                }
                else
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
                }

                for (int i = 0; i < param_count; i++)
                {
                    if (i < ldargs.Length)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(ldargs[i]));
                    }
                    else if (i < 256)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_S, (byte)i));
                    }
                    else
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg, (short)i));
                    }
                    if (i == 0 && isStateful && !method.IsStatic && !method.IsConstructor)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldfld, stateTable));
                    }
                    else if (i == 0 && !method.IsStatic && type.IsValueType)
                    {
                        processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldobj, type));
                    }
                    if (ignoreValueType)
                    {
                        TypeReference paramType;
                        if (method.IsStatic)
                        {
                            paramType = method.Parameters[i].ParameterType;
                        }
                        else
                        {
                            paramType = (i == 0) ? type : method.Parameters[i - 1].ParameterType;
                        }
                        if (paramType.IsValueType)
                        {
                            processor.InsertBefore(insertPoint, processor.Create(OpCodes.Box, paramType));
                        }
                    }
                }

                processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, invoke));
                if (statefulConstructor)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
                }
                if (isFinalize && isStateful)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldnull));
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
                }
                if (!method.IsConstructor && !isFinalize)
                {
                    processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ret));
                }

                if (!method.IsConstructor)
                {
                    break;
                }
                insertPoint = findNextRet(method.Body.Instructions, insertPoint);
            }

            if (isFinalize)
            {
                if (method.Body.ExceptionHandlers.Count == 0)
                {
                    throw new InvalidProgramException("Finalize has not try-catch? Type :" + method.DeclaringType);
                }
                method.Body.ExceptionHandlers[0].TryStart = method.Body.Instructions[0];
            }
            if (isIntKey)
            {
                bridgeIndexByKey.Add(method);
            }
            return(true);
        }
Пример #3
0
        static bool findHotfixDelegate(AssemblyDefinition assembly, MethodDefinition method, out MethodReference invoke, HotfixFlagInTool hotfixType)
        {
            bool isStateful      = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
            bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);

            for (int i = 0; i < hotfix_bridges.Count; i++)
            {
                MethodDefinition hotfix_bridge = hotfix_bridges[i];
                var returnType = (isStateful && method.IsConstructor && !method.IsStatic) ? luaTableType : method.ReturnType;
                if (isSameType(returnType, hotfix_bridge.ReturnType))
                {
                    var parametersOfDelegate = hotfix_bridge.Parameters;
                    int compareOffset        = 0;
                    if (!method.IsStatic)
                    {
                        var typeOfSelf = (isStateful && !method.IsConstructor) ? luaTableType :
                                         ((!ignoreValueType && method.DeclaringType.IsValueType) ? method.DeclaringType : objType);
                        if ((parametersOfDelegate.Count == 0) || parametersOfDelegate[0].ParameterType.IsByReference || !isSameType(typeOfSelf, parametersOfDelegate[0].ParameterType))
                        {
                            continue;
                        }
                        compareOffset++;
                    }
                    if (method.Parameters.Count != (parametersOfDelegate.Count - compareOffset))
                    {
                        continue;
                    }
                    bool paramMatch = true;
                    for (int j = 0; j < method.Parameters.Count; j++)
                    {
                        var param_left  = method.Parameters[j];
                        var param_right = parametersOfDelegate[compareOffset++];
                        if (param_left.IsOut != param_right.IsOut ||
                            param_left.ParameterType.IsByReference != param_right.ParameterType.IsByReference)
                        {
                            paramMatch = false;
                            break;
                        }
                        if (!ignoreValueType && param_left.ParameterType.IsValueType != param_right.ParameterType.IsValueType)
                        {
                            paramMatch = false;
                            break;
                        }
                        bool isparam   = param_left.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "ParamArrayAttribute") != null;
                        var  type_left = (isparam || param_left.ParameterType.IsByReference || (!ignoreValueType && param_left.ParameterType.IsValueType)) ? param_left.ParameterType : objType;
                        if (!isSameType(type_left, param_right.ParameterType))
                        {
                            paramMatch = false;
                            break;
                        }
                    }

                    if (!paramMatch)
                    {
                        continue;
                    }
                    invoke = hotfix_bridge;
                    return(true);
                }
            }
            invoke = null;
            return(false);
        }
Пример #4
0
        static bool genericInOut(AssemblyDefinition assembly, MethodDefinition method, HotfixFlagInTool hotfixType)
        {
            bool isStateful      = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
            bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);

            if (hasGenericParameter(method.ReturnType) || isNoPublic(assembly, method.ReturnType))
            {
                return(true);
            }
            var parameters = method.Parameters;

            if (!method.IsStatic && (!isStateful || method.IsConstructor) &&
                (hasGenericParameter(method.DeclaringType) || ((!ignoreValueType && method.DeclaringType.IsValueType) && isNoPublic(assembly, method.DeclaringType))))
            {
                return(true);
            }
            for (int i = 0; i < parameters.Count; i++)
            {
                if (hasGenericParameter(parameters[i].ParameterType) || (((!ignoreValueType && parameters[i].ParameterType.IsValueType) || parameters[i].ParameterType.IsByReference) && isNoPublic(assembly, parameters[i].ParameterType)))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #5
0
 static bool HasFlag(this HotfixFlagInTool toCheck, HotfixFlagInTool flag)
 {
     return((toCheck != HotfixFlagInTool.Stateless) && ((toCheck & flag) == flag));
 }