【转】托管函数的挂钩(完美版)
原文:http://blog.csdn.net/cstod/article/details/6262506
CLR Injection: Runtime Method Replacer
http://www.codeproject.com/Articles/37549/CLR-Injection-Runtime-Method-Replacer
CLR Injection: Modify IL Code during Run-time
http://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time
我之前發(fā)過(guò)一篇叫“托管函數(shù)的掛鉤”的文章,實(shí)現(xiàn)了對(duì)MarshalByRefObject繼承樹(shù)下的實(shí)例函數(shù)的掛鉤。?
最近,在CodeProject上看到一個(gè)關(guān)于托管函數(shù)掛鉤的文章,發(fā)現(xiàn)作者的方法很好用,但是正好不能用于MarshalByRefObject繼承樹(shù)下的實(shí)例函數(shù)(作者本人并沒(méi)有發(fā)現(xiàn)這個(gè)問(wèn)題),于是兩種方法正好互補(bǔ)。
你也許要用,我為什么要強(qiáng)調(diào)MarshalByRefObject繼承樹(shù)呢?這是因?yàn)榉浅6嗟念?lèi)都存在于該類(lèi)的繼承樹(shù)下,比如很多人習(xí)慣把代碼寫(xiě)在自己的窗體類(lèi)中,而Form就在MarshalByRefObject樹(shù)下,從我的實(shí)際經(jīng)驗(yàn)來(lái)看,它比非MarshalByRefObject繼承樹(shù)的范圍更廣。?
我對(duì)兩種代碼進(jìn)行了封裝,使用時(shí)只需調(diào)用ManagedReplacer.Replace方法即可。?
說(shuō)明:托管函數(shù)在第一次被調(diào)用時(shí)會(huì)被JIT成本地代碼,之后會(huì)復(fù)用被JIT的本地代碼,所以一定要在函數(shù)被JIT之前進(jìn)行掛鉤,否則將無(wú)效。
參考:http://www.sysnet.pe.kr/2/0/942
?
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.IO; using RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers; using System.Runtime.InteropServices; using System.Reflection.Emit;namespace System {public static class MethodUtil{/// <summary>/// 將源方法替換為新方法/// </summary> public static void Replace(this MethodBase source, MethodBase dest){ReplaceMethod(source, dest, false);}public static void ReplaceMethod(MethodBase source, MethodBase dest, bool isDynamicSource){if (!MethodSignaturesEqual(source, dest)){throw new ArgumentException("The method signatures are not the same.", "source");}ReplaceMethod(GetMethodAddress(source), dest, isDynamicSource);}public static void ReplaceMethod(IntPtr srcAdr, MethodBase dest, bool isDynamicSource){IntPtr destAdr = GetMethodAddress(dest);unsafe{if (IntPtr.Size == 8){ulong* d = (ulong*)destAdr.ToPointer();if (isDynamicSource == true){*d = (ulong)srcAdr.ToInt64();}else{*d = *((ulong*)srcAdr.ToPointer());}}else{uint* d = (uint*)destAdr.ToPointer();if (isDynamicSource == true){*d = (uint)srcAdr.ToInt32();}else{*d = *((uint*)srcAdr.ToPointer());}}}}public static IntPtr GetMethodAddress(MethodBase method){if ((method is DynamicMethod)){return GetDynamicMethodAddress(method);}// Prepare the method so it gets jited RuntimeHelpers.PrepareMethod(method.MethodHandle);// If 3.5 sp1 or greater than we have a different layout in memory.if (IsNet20Sp2OrGreater()){return GetMethodAddress20SP2(method);}unsafe{// Skip theseconst int skip = 10;// Read the method index.UInt64* location = (UInt64*)(method.MethodHandle.Value.ToPointer());int index = (int)(((*location) >> 32) & 0xFF);if (IntPtr.Size == 8){// Get the method tableulong* classStart = (ulong*)method.DeclaringType.TypeHandle.Value.ToPointer();ulong* address = classStart + index + skip;return new IntPtr(address);}else{// Get the method tableuint* classStart = (uint*)method.DeclaringType.TypeHandle.Value.ToPointer();uint* address = classStart + index + skip;return new IntPtr(address);}}}private static IntPtr GetDynamicMethodAddress(MethodBase method){unsafe{RuntimeMethodHandle handle = GetDynamicMethodRuntimeHandle(method);byte* ptr = (byte*)handle.Value.ToPointer();if (IsNet20Sp2OrGreater()){RuntimeHelpers.PrepareMethod(handle);return handle.GetFunctionPointer();//if (IntPtr.Size == 8)//{// ulong* address = (ulong*)ptr;// address = (ulong*)*(address + 5);// return new IntPtr(address + 12);//}//else//{// uint* address = (uint*)ptr;// address = (uint*)*(address + 5);// return new IntPtr(address + 12);//} }else{if (IntPtr.Size == 8){ulong* address = (ulong*)ptr;address += 6;return new IntPtr(address);}else{uint* address = (uint*)ptr;address += 6;return new IntPtr(address);}}}}private static RuntimeMethodHandle GetDynamicMethodRuntimeHandle(MethodBase method){RuntimeMethodHandle handle;if (Environment.Version.Major == 4){MethodInfo getMethodDescriptorInfo = typeof(DynamicMethod).GetMethod("GetMethodDescriptor",BindingFlags.NonPublic | BindingFlags.Instance);handle = (RuntimeMethodHandle)getMethodDescriptorInfo.Invoke(method, null);}else{FieldInfo fieldInfo = typeof(DynamicMethod).GetField("m_method", BindingFlags.NonPublic | BindingFlags.Instance);handle = ((RuntimeMethodHandle)fieldInfo.GetValue(method));}return handle;}private static IntPtr GetMethodAddress20SP2(MethodBase method){unsafe{return new IntPtr(((int*)method.MethodHandle.Value.ToPointer() + 2));}}private static bool MethodSignaturesEqual(MethodBase x, MethodBase y){if (x.CallingConvention != y.CallingConvention){return false;}Type returnX = GetMethodReturnType(x), returnY = GetMethodReturnType(y);if (returnX != returnY){return false;}ParameterInfo[] xParams = x.GetParameters(), yParams = y.GetParameters();if (xParams.Length != yParams.Length){return false;}for (int i = 0; i < xParams.Length; i++){if (xParams[i].ParameterType != yParams[i].ParameterType){return false;}}return true;}private static Type GetMethodReturnType(MethodBase method){MethodInfo methodInfo = method as MethodInfo;if (methodInfo == null){// Constructor info.throw new ArgumentException("Unsupported MethodBase : " + method.GetType().Name, "method");}return methodInfo.ReturnType;}private static bool IsNet20Sp2OrGreater(){if (Environment.Version.Major == 4){return true;}return Environment.Version.Major == NetFxVersions.Net20SP2.Major &&Environment.Version.MinorRevision >= NetFxVersions.Net20SP2.MinorRevision;}#region NetFxVersionspublic static class NetFxVersions{public static readonly Version Net35 = new Version(3, 5, 21022, 8);public static readonly Version Net35SP1 = new Version(3, 5, 30729, 1);public static readonly Version Net30 = new Version(3, 0, 4506, 30);public static readonly Version Net30SP1 = new Version(3, 0, 4506, 648);public static readonly Version Net30SP2 = new Version(3, 0, 4506, 2152);public static readonly Version Net20 = new Version(2, 0, 50727, 42);public static readonly Version Net20SP1 = new Version(2, 0, 50727, 1433);public static readonly Version Net20SP2 = new Version(2, 0, 50727, 3053);}#endregion} }?
??
?
devexpress patch for vs2015 packge :?devexpress.vspackage.vs2015.zip
?
?
IntelliJ IDEA 14?sn
(1)key:IDEA
value:61156-YRN2M-5MNCN-NZ8D2-7B4EW-U12L4?
(2)key:huangwei
value:97493-G3A41-0SO24-W57LI-Y2UGI-JGTU2?
(3)key:hkl520
value:34423-VZYXD-FQXZ7-O6I7U-J3ZK8-R7V62?
(4)key:Intelligent
value:40957-EG6O9-2915L-CF1RP-57IQJ-Y6VZ3?
(5)key:tommy
value:49164-YPNVL-OXUZL-XIWM4-Z9OHC-LF053?
(6)key:whuanghk
value:98220-IN97R-TV1ID-2JAPO-OXZEO-LAM70?
(7)key:itey
value:91758-T1CLA-C64F3-T7X5R-A7YDO-CRSN1
轉(zhuǎn)載于:https://www.cnblogs.com/zhahost/p/3660139.html
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的【转】托管函数的挂钩(完美版)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux中的ln
- 下一篇: 编程范式,程序员的编程世界观(转)