Пример #1
0
        /// <summary>
        /// 执行Patch
        /// </summary>
        /// <returns></returns>
        public PatchInfoData Patch(PatchFlags flags)
        {
            PatchInfo patchInfo = null;

            lock (locker)
            {
#if RECORD_PATCH_STATE
                patchInfo = HarmonySharedState.GetPatchInfo(original);
                if (patchInfo == null)
                {
                    patchInfo = new PatchInfo();
                }
#endif
                patchInfo = new PatchInfo();

                PatchFunctions.AddPrefix(patchInfo, instance.id, prefix);
                PatchFunctions.AddPostfix(patchInfo, instance.id, postfix);
                PatchFunctions.AddTranspiler(patchInfo, instance.id, transpiler);
                PatchFunctions.UpdateWrapper(original, patchInfo, flags);
#if RECORD_PATCH_STATE
                HarmonySharedState.UpdatePatchInfo(original, patchInfo);
#endif
            }

            return(patchInfo.patchdata);
        }
Пример #2
0
 public PatchEntry(long address, long size, long sectionIndex, PatchFlags flags)
 {
     this.Address      = address;
     this.Size         = size;
     this.SectionIndex = sectionIndex;
     this.Flags        = flags;
 }
Пример #3
0
 public PatchHeader(uint index, uint address, int length, PatchCommand command, PatchFlags flags)
 {
     Index   = index;
     Address = address;
     Length  = length;
     Command = command;
     Flags   = flags;
 }
Пример #4
0
        public static void UpdateWrapper(MethodBase original, PatchInfo patchInfo, PatchFlags flags)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers).Select(m => TranspilerImpl.From(m)).ToList();

            var replacement = MethodPatcher.CreatePatchedMethod(original, sortedPrefixes, sortedPostfixes, sortedTranspilers, flags);

            if (replacement == null)
            {
                throw new MissingMethodException("Cannot create dynamic replacement for " + original);
            }

            patchInfo.patchdata.orgaddress = Memory.GetMethodStart(original);
            patchInfo.patchdata.jmpaddress = Memory.GetMethodStart(replacement);

            Memory.WriteJump(patchInfo.patchdata.orgaddress, patchInfo.patchdata.jmpaddress, out patchInfo.patchdata.orgbytes, out patchInfo.patchdata.jmpbytes);

            PatchTools.RememberObject(original, replacement);             // no gc for new value + release old value to gc
        }
Пример #5
0
        public PatchInfoData Patch(MethodBase original, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod transpiler, PatchFlags flags)
        {
            var processor = new PatchProcessor(this, original, prefix, postfix, transpiler);

            return(processor.Patch(flags));
        }
Пример #6
0
        public static DynamicMethod CreatePatchedMethod(MethodBase original, List <MethodInfo> prefixes, List <MethodInfo> postfixes, List <TranspilerImpl> transpilers, PatchFlags flags)
        {
            if (HarmonyInstance.DEBUG)
            {
                FileLog.Log("PATCHING " + original.DeclaringType + " " + original);
            }

            var idx   = prefixes.Count() + postfixes.Count();
            var patch = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx);
            var il    = patch.GetILGenerator();

            var originalVariables = DynamicTools.DeclareLocalVariables(original, il);
            var privateVars       = new Dictionary <string, LocalBuilder>();

            LocalBuilder resultVariable = null;

            if (idx > 0)
            {
                resultVariable          = DynamicTools.DeclareLocalVariable(il, AccessTools.GetReturnedType(original));
                privateVars[RESULT_VAR] = resultVariable;
            }

            prefixes.ForEach(prefix =>
            {
                prefix.GetParameters()
                .Where(patchParam => patchParam.Name == STATE_VAR)
                .Do(patchParam =>
                {
                    var privateStateVariable = DynamicTools.DeclareLocalVariable(il, patchParam.ParameterType);
                    privateVars[prefix.DeclaringType.FullName] = privateStateVariable;
                });
            });

            var  afterOriginal1 = il.DefineLabel();
            var  afterOriginal2 = il.DefineLabel();
            bool canHaveJump    = false;

            if (flags.HasFlag(PatchFlags.PF_Detour) == false)
            {
                canHaveJump = AddPrefixes(il, original, prefixes, privateVars, afterOriginal2);

                if (flags.HasFlag(PatchFlags.PF_NoOrigin) == false)
                {
                    var copier = new MethodCopier(original, patch, originalVariables);
                    foreach (var transpiler in transpilers)
                    {
                        copier.AddTranspiler(transpiler);
                    }
                    copier.Emit(afterOriginal1);
                    Emitter.MarkLabel(il, afterOriginal1);
                    if (resultVariable != null)
                    {
                        Emitter.Emit(il, OpCodes.Stloc, resultVariable);
                    }
                }
            }
            if (canHaveJump)
            {
                Emitter.MarkLabel(il, afterOriginal2);
            }

            if (AddPostfixes(il, original, postfixes, privateVars))
            {
                if (resultVariable != null)
                {
                    Emitter.Emit(il, OpCodes.Stloc, resultVariable);
                }
            }
            if (resultVariable != null)
            {
                Emitter.Emit(il, OpCodes.Ldloc, resultVariable);
            }
            Emitter.Emit(il, OpCodes.Ret);

            if (HarmonyInstance.DEBUG)
            {
                FileLog.Log("DONE");
                FileLog.Log("");
            }

            DynamicTools.PrepareDynamicMethod(patch);
            return(patch);
        }