Example #1
0
        public static void UpdateWrapper(MethodBase original, PatchInfo patchInfo)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

            if (HarmonyInstance.DEBUG)
            {
                //MethodPatcher.SavePatchedMethod(original, sortedPrefixes, sortedPostfixes, sortedTranspilers);
            }

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

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

            var originalCodeStart = Memory.GetMethodStart(original);
            var patchCodeStart    = Memory.GetMethodStart(replacement);

            Memory.WriteJump(originalCodeStart, patchCodeStart);

            PatchTools.RememberObject(original, replacement);             // no gc for new value + release old value to gc
        }
        public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

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

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

            var errorString = Memory.DetourMethod(original, replacement);

            if (errorString != null)
            {
                throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
            }

            if (UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType))
            {
                var il2CppShim = CreateIl2CppShim(replacement, original.DeclaringType);
                Imports.Hook(UnhollowerSupport.MethodBaseToIntPtr(original), il2CppShim.MethodHandle.GetFunctionPointer());
                PatchTools.RememberObject(original, new PotatoTuple {
                    First = replacement, Second = il2CppShim
                });
            }
            else
            {
                PatchTools.RememberObject(original, replacement);                 // no gc for new value + release old value to gc
            }
            return(replacement);
        }
Example #3
0
        private static PatchHandle Apply(MethodBase original, MethodInfo postfix)
        {
            if (postfix == null)
            {
                throw new ArgumentNullException(nameof(postfix));
            }

            var originalCodeStart = Memory.GetMethodStart(original);

            var replacement = MethodPatcher.CreatePatchedMethod(original, postfix);

            if (replacement == null)
            {
                throw new MissingMethodException($"Cannot create dynamic replacement for {original}");
            }
            var patchCodeStart = Memory.GetMethodStart(replacement);

            // This part effectively corrupts the original compiled method, so we should prepare to restore the overwritten part later
            // (It doesn't look like it breaks something, but... better safe than sorry?)
            var oldBytes = new byte[IntPtr.Size == sizeof(long) ? 12 : 6];

            Marshal.Copy((IntPtr)originalCodeStart, oldBytes, 0, oldBytes.Length);

            Memory.WriteJump(originalCodeStart, patchCodeStart);

            return(new PatchHandle(patchedMethod: replacement, overwrittenCode: oldBytes));
        }
Example #4
0
        public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

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

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

            var errorString = Memory.DetourMethod(original, replacement);

            if (errorString != null)
            {
                throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
            }

            if (IsIl2CppType(original.DeclaringType))
            {
                var il2CppShim = CreateIl2CppShim(replacement, original.DeclaringType);
                Imports.Hook(NET_SDK.SDK.GetClass(original.DeclaringType.FullName).GetMethod(original.Name).Ptr, il2CppShim.MethodHandle.GetFunctionPointer());

                PatchTools.RememberObject(original, new Tuple <MethodBase, MethodBase>(replacement, il2CppShim));
            }
            else
            {
                PatchTools.RememberObject(original, replacement);                 // no gc for new value + release old value to gc
            }

            return(replacement);
        }
        public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var  sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var  sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var  sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);
            bool isIl2Cpp          = UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType);

            if (isIl2Cpp)
            {
                if (sortedTranspilers.Count > 0)
                {
                    throw new NotSupportedException("IL2CPP patches cannot use transpilers (got " + sortedTranspilers.Count + ")");
                }

                if (patchInfo.copiedMethodInfoPointer == IntPtr.Zero)
                {
                    IntPtr origMethodPtr = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(original);
                    patchInfo.copiedMethodInfoPointer = CopyMethodInfoStruct(origMethodPtr);
                    HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                }

                sortedTranspilers.Add(AccessTools.DeclaredMethod(typeof(PatchFunctions), "UnhollowerTranspiler"));
            }

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

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

            if (isIl2Cpp)
            {
                DynamicMethod il2CppShim = CreateIl2CppShim(replacement, original);
                InstallIl2CppPatch(patchInfo, il2CppShim);
                PatchTools.RememberObject(original, new PotatoTuple {
                    First = replacement, Second = il2CppShim
                });
            }
            else
            {
                var errorString = Memory.DetourMethod(original, replacement);
                if (errorString != null)
                {
                    throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
                }

                PatchTools.RememberObject(original, replacement);                 // no gc for new value + release old value to gc
            }

            return(replacement);
        }
Example #6
0
        public static void UpdateWrapper(MethodBase original, PatchInfo patchInfo)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

            var originalCodeStart = Memory.GetMethodStart(original);

            // If we're overwriting an old patch, restore the original 12 (or 6) bytes of the method beforehand
            object oldHandle;

            if (PatchTools.RecallObject(original, out oldHandle))
            {
                var oldPatchHandle = (PatchHandle)oldHandle;
                Memory.WriteBytes(originalCodeStart, oldPatchHandle.OverwrittenCode);
            }

            if (patchInfo.postfixes.Length + patchInfo.prefixes.Length + patchInfo.transpilers.Length == 0)
            {
                // No patches, can just leave the original method intact
                PatchTools.ForgetObject(originalCodeStart);
                return;
            }

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

            if (replacement == null)
            {
                throw new MissingMethodException("Cannot create dynamic replacement for " + original);
            }
            var patchCodeStart = Memory.GetMethodStart(replacement);

            // This part effectively corrupts the original compiled method, so we should prepare to restore the overwritten part later
            // (It doesn't look like it breaks something, but... better safe than sorry?)
            var oldBytes = new byte[(IntPtr.Size == sizeof(long)) ? 12 : 6];

            Marshal.Copy((IntPtr)originalCodeStart, oldBytes, 0, oldBytes.Length);
            // Store code being overwritten by the jump for the restoration
            PatchTools.RememberObject(original, new PatchHandle {
                PatchedMethod = replacement, OverwrittenCode = oldBytes
            });
            Memory.WriteJump(originalCodeStart, patchCodeStart);
        }
Example #7
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
        }
Example #8
0
        /// <summary>Creates new dynamic method with the latest patches and detours the original method</summary>
        /// <param name="original">The original method</param>
        /// <param name="patchInfo">Information describing the patches</param>
        /// <param name="instanceID">Harmony ID</param>
        /// <returns>The newly created dynamic method</returns>
        ///
        internal static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo patchInfo, string instanceID)
        {
            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers);

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

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

            var errorString = Memory.DetourMethod(original, replacement);

            if (errorString != null)
            {
                throw new FormatException("Method " + original.FullDescription() + " cannot be patched. Reason: " + errorString);
            }

            PatchTools.RememberObject(original, replacement);             // no gc for new value + release old value to gc

            return(replacement);
        }