public static IMethod ResolveOrImport(this PatchConfiguration patch, ModuleDef module, MethodBase method)
 {
     if (patch.TryResolve(module, method.ToSignature(), out MethodDef def))
     {
         return(def);
     }
     return(new MemberRefUser(module, method.GetName(), module.ToSig(method.ToSignature()), patch.ResolveOrImport(module, method.DeclaringType)));
 }
Beispiel #2
0
 private static TypeMixin.Builder LoadMixin(this PatchConfiguration patch, TypeInfo type)
 {
     TypeMixin.Builder builder = new TypeMixin.Builder(patch.LoadDependency(type), patch.LoadInject(type));
     foreach (MethodBase method in type.AllMethods().Where(IsMixin))
     {
         builder.Mixin(new MethodMixin(method.ToSignature(), method.ApplyMixin(patch)));
     }
     return(builder);
 }
        public static IField ResolveOrImport(this PatchConfiguration patch, ModuleDef module, FieldInfo field)
        {
            if (patch.TryResolve(module, field.ToSignature(), out FieldDef def))
            {
                return(def);
            }
            MemberRef fieldRef = module.Import(field);

            fieldRef.Name = field.GetName();
            return(fieldRef);
        }
Beispiel #4
0
 private static TypeInject.Builder LoadInject(this PatchConfiguration patch, TypeInfo type)
 {
     TypeInject.Builder builder = new TypeInject.Builder(type.ToDescriptor());
     foreach (FieldInfo field in type.DeclaredFields.Where(IsInject))
     {
         builder.Inject(new FieldInject(field.ToDescriptor(), a => { }));
     }
     foreach (MethodInfo method in type.AllMethods().Where(IsInject))
     {
         builder.Inject(new MethodInject(method.ToDescriptor(), method.ApplyInject(patch)));
     }
     return(builder);
 }
        public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub =>
        {
            CilBody            stubBody       = stub.Body;
            MethodBody         injectBody     = inject.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(stubBody.Instructions);
            List <Local>       originalLocals = new List <Local>(stubBody.Variables);
            stubBody.Variables.Clear();
            foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                stubBody.Variables.Add(stub.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters);
            IList <Instruction> newIL = stubBody.Instructions;
            newIL.Clear();
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(stub.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        throw new InvalidOperationException("attempt to inject a body with a base dependency call");
                    }
                    inst.Operand = patch.ResolveOrImport(stub.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(stub.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            stubBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses)
            {
                stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL));
            }
            stubBody.OptimizeMacros();
        };
        public static ITypeDefOrRef ResolveOrImport(this PatchConfiguration patch, ModuleDef module, Type type)
        {
            if (patch.TryResolve(module, type.ToSignature(), out TypeDef def))
            {
                return(def);
            }
            type = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType(type.GetName())).First(t => t != null);
            return(module.Import(type));

            /*string fullName = type.GetName();
             * int nsEnd = fullName.LastIndexOf('.');
             * string ns = null, name = fullName;
             * if (nsEnd >= 0)
             * {
             *  ns = fullName.Substring(0, nsEnd);
             *  name = fullName.Substring(nsEnd + 1);
             * }
             * return new TypeRefUser(module, ns, name, new AssemblyNameInfo(type.Assembly.GetName()).ToAssemblyRef());//new AssemblyRefUser(module, type.Module.Name.Substring(0, type.Module.Name.Length - 4)));*/
        }
Beispiel #7
0
        private static TypeDependency.Builder LoadDependency(this PatchConfiguration patch, TypeInfo type)
        {
            TypeSignature typeSig      = type.ToSignature();
            TypeSignature mixinTypeSig = type.ToMixinSignature();

            patch.AddSubstitution(mixinTypeSig, typeSig);
            TypeDependency.Builder builder = new TypeDependency.Builder(type.ToDescriptor());
            foreach (FieldInfo field in type.DeclaredFields.Where(IsDependency))
            {
                patch.AddSubstitution(mixinTypeSig.Field(field.GetName(), field.FieldType.ToSignature()), typeSig.Field(field.GetName(), field.FieldType.ToSignature()));
                builder.FieldDependency(field.ToSignature(), field.Import());
            }
            foreach (MethodBase method in type.AllMethods().Where(IsDependency))
            {
                IEnumerable <Func <ModuleDef, TypeSig> > parameterTypes = method.GetParameters().Select(p => p.ParameterType.ToSig()).ToArray();
                patch.AddSubstitution(mixinTypeSig.Method(method.GetName(), method.CallingConvention.ToPatcher(), parameterTypes), typeSig.Method(method.GetName(), method.CallingConvention.ToPatcher(), parameterTypes));
                builder.MethodDependency(method.ToSignature(), method.Import());
            }
            return(builder);
        }
Beispiel #8
0
        public static PatchConfiguration ToPatch(this Assembly assembly, string patchName)
        {
            assembly.LoadReferencedAssemblies();
            PatchConfiguration patch = new PatchConfiguration(patchName, assembly.ManifestModule.GetCustomAttribute <PatchAttribute>().Assembly, assembly.ManifestModule.GetCustomAttributes <RequiredAttribute>().Select(a => a.Assembly));

            foreach (TypeInfo type in assembly.DefinedTypes)
            {
                if (type.IsInject())
                {
                    patch.AddInjected(patch.LoadInject(type));
                }
                if (type.IsDependencyExplicit())
                {
                    patch.AddDependency(patch.LoadDependency(type));
                }
                if (type.IsMixin())
                {
                    patch.AddMixin(patch.LoadMixin(type));
                }
            }
            return(patch);
        }
        public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original =>
        {
            CilBody            originalBody   = original.Body;
            MethodBody         mixinBody      = mixin.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(originalBody.Instructions);
            List <Local>       originalLocals = new List <Local>(originalBody.Variables);
            originalBody.Variables.Clear();
            foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                originalBody.Variables.Add(original.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters);
            IList <Instruction> newIL = originalBody.Instructions;
            newIL.Clear();
            int ilStart = 0;
            if (mixin.IsConstructor)
            {
                foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL)
                {
                    ilStart++;
                    newIL.Add(inst);
                    if (inst.OpCode.FlowControl == FlowControl.Call)
                    {
                        break;
                    }
                }
                RemoveCall(originalIL);
                RemoveCall(mixinIL);
            }
            MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr);
            bool      useBase  = false;
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(original.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        useBase      = true;
                        inst.Operand = baseCopy;
                        break;
                    }
                    inst.Operand = patch.ResolveOrImport(original.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(original.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            if (useBase)
            {
                baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables);
                original.DeclaringType.Methods.Add(baseCopy);
            }
            originalBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses)
            {
                originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL));
            }
            originalBody.OptimizeMacros();

            void RemoveCall(List <Instruction> il)
            {
                for (int index = 0; index < il.Count; index++)
                {
                    if (il[index].OpCode.FlowControl != FlowControl.Call)
                    {
                        continue;
                    }
                    il.RemoveRange(0, index + 1);
                    break;
                }
            }
        };