闲来无事,随便写点,老话题了,高手略过。
compileMethod方法在各类.NET内核的文章中出现频率相当高,因为它是JIT引擎工作的关键函数。其原型如下(参考sscli代码):
代码:
CorJitResult __stdcall FJitCompiler::compileMethod ( ICorJitInfo* compHnd, /* IN */ CORINFO_METHOD_INFO* info, /* IN */ unsigned flags, /* IN */ BYTE ** entryAddress, /* OUT */ ULONG * nativeSizeOfCode /* OUT */ )
代码:
/********************************************************************************* * a ICorJitInfo is the main interface that the JIT uses to call back to the EE and * get information *********************************************************************************/ class ICorJitInfo : public virtual ICorDynamicInfo {//省略}
代码:
/***************************************************************************** * ICorDynamicInfo contains EE interface methods which return values that may * change from invocation to invocation. They cannot be embedded in persisted * data; they must be requeried each time the EE is run. *****************************************************************************/ class ICorDynamicInfo : public virtual ICorStaticInfo {//省略}
代码:
/***************************************************************************** * ICorStaticInfo contains EE interface methods which return values that are * constant from invocation to invocation. Thus they may be embedded in * persisted information like statically generated code. (This is of course * assuming that all code versions are identical each time.) *****************************************************************************/ class ICorStaticInfo : public virtual ICorMethodInfo, public virtual ICorModuleInfo, public virtual ICorClassInfo, public virtual ICorFieldInfo, public virtual ICorDebugInfo, public virtual ICorArgInfo, public virtual ICorLinkInfo, public virtual ICorErrorInfo
比如我们需要取得当前hook方法的方法名,可以调用ICorMethodInfo中的如下方法:
代码:
virtual const char* __stdcall getMethodName ( CORINFO_METHOD_HANDLE ftn, /* IN */ const char **moduleName /* OUT */ ) = 0;
代码:
struct CORINFO_METHOD_INFO { CORINFO_METHOD_HANDLE ftn; CORINFO_MODULE_HANDLE scope; BYTE * ILCode; unsigned ILCodeSize; unsigned short maxStack; unsigned short EHcount; CorInfoOptions options; CORINFO_SIG_INFO args; CORINFO_SIG_INFO locals; };
代码:
virtual CORINFO_CLASS_HANDLE __stdcall findClass ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK, /* IN */ CORINFO_CONTEXT_HANDLE context, /* IN */ CorInfoTokenKind tokenKind = CORINFO_TOKENKIND_Default /* IN */ ) = 0;
具体在VS中编程时,可以添加corinfo.h和corjit.h,并在同一目录下添加corhdr.h,便可顺利编译通过。
最后还有一个问题,sscli毕竟是早期框架了,还是精简版,现在还能直接使用吗?不妨分析一下。随便运行一个.NET程序,用WinDbg调试并中断在compileMethod处,查看ICorJitInfo值所指的内存:
代码:
0012ea38 79f10654 mscorwks!CEEJitInfo::`vbtable' 0012ea3c 00174d18 0012ea40 00997850 0012ea44 00107210 0012ea48 00000000 0012ea4c 0018a610 0012ea50 00000000 0012ea54 00000000 0012ea58 00000000 0012ea5c 0012ea40 0012ea60 00000000 0012ea64 00000000 0012ea68 00000000 0012ea6c 79f105b8 mscorwks!CEEJitInfo::`vftable' 0012ea70 00000000 0012ea74 79f10584 mscorwks!CEEJitInfo::`vftable' 0012ea78 00000000 0012ea7c 79f104e0 mscorwks!CEEJitInfo::`vftable' 0012ea80 00000000 0012ea84 79f104bc mscorwks!CEEJitInfo::`vftable' 0012ea88 00000000 0012ea8c 79f104a4 mscorwks!CEEJitInfo::`vftable' 0012ea90 00000000 0012ea94 79f10498 mscorwks!CEEJitInfo::`vftable' 0012ea98 00000000 0012ea9c 79f10494 mscorwks!CEEJitInfo::`vftable' ...//下略
代码:
79f10624 79f106ac mscorwks!CEEJitInfo::getMemoryManager 79f10628 79f11d82 mscorwks!CEEJitInfo::allocMem 79f1062c 79f11f39 mscorwks!CEEJitInfo::allocGCInfo 79f10630 7a12b8cb mscorwks!CEEJitInfo::getEHInfo 79f10634 7a12b6cf mscorwks!CEEJitInfo::yieldExecution 79f10638 79f16373 mscorwks!CEEJitInfo::setEHcount 79f1063c 79f16491 mscorwks!CEEJitInfo::setEHinfo 79f10640 7a12ed41 mscorwks!CEEJitInfo::logMsg 79f10644 7a27ffcc mscorwks!ZapperModule::doAssert 79f10648 7a12eeb6 mscorwks!CEEJitInfo::allocBBProfileBuffer 79f1064c 7a2c2fa1 mscorwks!MDInternalRO::ConvertTextSigToComSig 79f10650 79f0efee mscorwks!CEEJitInfo::isVerifyOnly 79f10654 fffffffc
这样,我们就得到如下的结论:.NET内核框架从2.0开始,内核变化不大,包括sscli的内核代码,这些可以从内部函数的定义看出来;通过hook compileMethod,可以得到ICorJitInfo等关键接口,并调用其中的许多内部方法;具体编写时,可以在VS中引入sscli的corinfo.h、corjit.h和corhdr.h等文件,之后便可以直接调用。因此,通过compileMethod,我们可以做的事很多很多,远不限于仅获得某个方法的IL。
个人观点,若有错误,欢迎指正!