コード例 #1
0
        /// <summary>
        /// Redirects all calls from method 'from' to method 'to'. This version works
        /// only if the 'from' method has already been compiled (use GetFunctionPointer to force
        /// this) but no function calling 'from' have already been compiled. In fact, this
        /// function forces compilation for 'to' and 'from'. 'to' and 'from' are assumed
        /// to be normal methods.
        /// After compilation, this method looks up the MonoJitInfo structs for both methods
        /// from domain->jit_info_hash and patches sets the pointer to native code to the code
        /// obtained from compiling 'to'.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        private static void RedirectCall(MethodInfo from, MethodInfo to)
        {
            /* We assume that we are only dealing with 'normal' functions (in Mono lingua).
             * This excludes in particular:
             *  - generic functions
             *  - PInvokes
             *  - methods built at runtime
             */
            IntPtr methodPtr1 = from.MethodHandle.Value;
            IntPtr methodPtr2 = to.MethodHandle.Value;

            // ensure that both methods are compiled
            from.MethodHandle.GetFunctionPointer();
            to.MethodHandle.GetFunctionPointer();

            // get domain->jit_code_hash
            IntPtr domain = mono_domain_get();

            unsafe
            {
                byte * jitCodeHash      = ((byte *)domain.ToPointer() + 0xE8);
                long **jitCodeHashTable = *(long ***)(jitCodeHash + 0x20);
                uint   tableSize        = *(uint *)(jitCodeHash + 0x18);

                void *jitInfoFrom = null, jitInfoTo = null;

                // imitate the behavior of mono_internal_hash_table_lookup to get both MonoJitInfo ptrs
                long mptr1  = methodPtr1.ToInt64();
                uint index1 = ((uint)mptr1) >> 3;
                for (long *value = jitCodeHashTable[index1 % tableSize];
                     value != null;
                     value = *(long **)(value + 1))
                {
                    if (mptr1 == *value)
                    {
                        jitInfoFrom = value;
                        break;
                    }
                }

                long mptr2  = methodPtr2.ToInt64();
                uint index2 = ((uint)mptr2) >> 3;
                for (long *value = jitCodeHashTable[index2 % tableSize];
                     value != null;
                     value = *(long **)(value + 1))
                {
                    if (mptr2 == *value)
                    {
                        jitInfoTo = value;
                        break;
                    }
                }
                if (jitInfoFrom == null || jitInfoTo == null)
                {
                    DebugLog.Log("Could not find methods");
                    return;
                }


                // copy over code_start, used_regs, code_size and ignore the rest for now.
                // code_start beings at +0x10, code_size goes til +0x20
                ulong *fromPtr, toPtr;
                fromPtr        = (ulong *)jitInfoFrom;
                toPtr          = (ulong *)jitInfoTo;
                *(fromPtr + 2) = *(toPtr + 2);
                *(fromPtr + 3) = *(toPtr + 3);
            }
        }