рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛

рд░рди рд╕рдордп рдореЗрдВ MSIL рдХреЛрдб рдХреА .NET рд╡рд┐рдзрд┐ рдХреЛ рдмрджрд▓рдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред рдпрд╣ рдЗрддрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рдЖрдк рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ (рд╣реБрдХрд┐рдВрдЧ) рдХреЛ рд░реЛрдХ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдкрдиреЗ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдФрд░ рдЕрдиреНрдп рдЕрджреНрднреБрдд рдЪреАрдЬрд╝реЛрдВ рдХреА рд░рдХреНрд╖рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдРрд╕рд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рдереА - рдЗрд╕ рдХреЛрдб рдХреЗ рд╕рд╛рде рдХреБрдЫ рднреА рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ MSIL рдХреЛрдб рдХреЛ JIT рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдорд╢реАрди рдХреЛрдб рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдЪреВрдВрдХрд┐ .NET рд╕реАрдПрд▓рдЖрд░ рдкреНрд░рд▓реЗрдЦрд┐рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рдФрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдкрде рдХреА рддрд▓рд╛рд╢ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдореЗрдореЛрд░реА рдореЗрдВ рдкрддреЗ рдХреЗ рд╕рдЯреАрдХ рд╕реНрдерд╛рди рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд╣реИред
рдЕрдВрдд рдореЗрдВ, рдЕрдиреБрд╕рдВрдзрд╛рди рдХреЗ рдПрдХ рдкреВрд░реЗ рд╕рдкреНрддрд╛рд╣ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрд┐рдпрд╛ред рдЖрдкрдХреЗ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡рд┐рдзрд┐ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╣реИ:
protected string CompareOneAndTwo() { int a = 1; int b = 2; if (a < b) { return "Number 1 is less than 2"; } else { return "Number 1 is greater than 2 (O_o)"; } }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ "рдирдВрдмрд░ 1 2 рд╕реЗ рдХрдо рд╣реИ"ред рдЖрдЗрдП рдЗрд╕ рдЧрд▓рддрдлрд╣рдореА рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдФрд░ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд▓реМрдЯрд╛ рдкрд░рд┐рдгрд╛рдо "рд╕рдВрдЦреНрдпрд╛ 1 2 (O_o)" рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛред
рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП MSIL рдХреЛрдб рдХреЛ рджреЗрдЦрдХрд░, рд╣рдо Bt_S opcode рдХреЛ Blt_S рдХреЗ рд╕рд╛рде рдмрджрд▓рдХрд░ рдЕрдкрдирд╛ рд▓рдХреНрд╖реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдФрд░ рдпрджрд┐ рдЖрдк рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЖрдкрдХреЛ рдЧрд▓рдд рдкрд░рд┐рдгрд╛рдо рджрд┐рдЦрд╛рдПрдЧрд╛ред

рдиреАрдЪреЗ IL рдХреА рдЬрдЧрд╣ рдХреЛрдб рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдХреЛрдб рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рд╣реИрдВред
// Type type=this.GetType(); MethodInfo methodInfo=type.GetMethod("CompareOneAndTwo", BindingFlags.NonPublic|BindingFlags.Instance); // , , // , , JIT // , JIT- :) RuntimeHelpers.PrepareMethod(methodInfo.MethodHandle); // IL- byte[] ilCodes=methodInfo.GetMethodBody().GetILAsByteArray(); // // for (int i=0; i<ilCodes.Length; i++) { if (ilCodes[i]==OpCodes.Bge_S.Value) { // Bge_S Blt_S ilCodes[i]=(byte)OpCodes.Blt_S.Value; } } // IL- InjectionHelper.UpdateILCodes(methodInfo, ilCodes);
рдЖрдк рдЕрдкрдиреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдореЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
- .NET 2.0 рд╕реЗ 4.0 рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ
- рдпрд╣ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реАрдХреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЧрддрд┐рд╢реАрд▓ рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
- .NET рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд░рд┐рд▓реАрдЬрд╝ рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ
- X86 рдФрд░ x64 рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ
рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ
InjectionHelper.cs рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдПрдБ, рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╕рдорд╛рд╣рд┐рдд рд╣реИрдВред
public static class InjectionHelper { // Load the unmanaged injection.dll, the initlaization happens in a background thread // you can check if the initialization is completed by GetStatus() public static void Initialize() // Unload the unmanaged injection.dll public static void Uninitialize() // Update the IL Code of a Method. public static void UpdateILCodes(MethodInfo method, byte[] ilCodes) // The method returns until the initialization is completed public static Status WaitForIntializationCompletion() // Query the current status of the unmanaged dll, returns immediately. public static Status GetStatus() }
Injectionhelper :: рдЖрд░рдВрднрд┐рдХ рд╡рд┐рдзрд┐ рдореЗрдВ injection.dll рд▓реЛрдб рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЕрд╕реЗрдВрдмрд▓реА рдХреЛрдб рд╣реЛрддрд╛ рд╣реИ, рдЙрд╕ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реЗ рдЬрд┐рд╕рдореЗрдВ рдЕрд╕реЗрдВрдмрд▓реА рд╕реНрдерд┐рдд рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡реЗ рд╕рднреА рдлрд╛рдЗрд▓реЗрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЖрдк рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдпрд╛ рдЖрдк рд╕реНрд░реЛрдд рдХреЛ рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ :)
рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА:
рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо | рд╡рд┐рд╡рд░рдг |
Injection32.dll | рдЕрдкреНрд░рдмрдВрдзрд┐рдд dll рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп (x86 рд╕рдВрд╕реНрдХрд░рдг) рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░ рд░рд╣рд╛ рд╣реИ |
Injection64.dll | рдЕрдкреНрд░рдмрдВрдзрд┐рдд dll рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░ рд░рд╣рд╛ рд╣реИ (x64 рд╕рдВрд╕реНрдХрд░рдг) |
EasyHook32.dll | x86 рдЗрдЬрд╝реАрд╣реБрдХ рдбреАрдПрд▓рдПрд▓ (http://easyhook.codeplex.com/) (рдЗрдВрдЬреЗрдХреНрд╢рди32.dll рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) |
EasyHook64.dll | X64 EasyHook DLL (http://easyhook.codeplex.com/) (Injection64.dll рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) |
x86 / * | X86 рдХреЗ рд▓рд┐рдП рд╡рд┐рдВрдбреЛрдЬ рдбрд┐рдмрдЧ рдЯреВрд▓ |
x64 / * | X64 рдХреЗ рд▓рд┐рдП рд╡рд┐рдВрдбреЛрдЬ рдбрд┐рдмрдЧ рдЯреВрд▓ |
PDB_symbols / * | рдкреАрдбреАрдмреА рдлрд╛рдЗрд▓реЗрдВред рдЙрдиреНрд╣реЗрдВ рд╣рдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЖрд░рдВрдн рдХреЛ рдзреАрдорд╛ рдХрд░ рджреЗрдЧрд╛ред |
рдкрд░реНрджреЗ рдХреЗ рдкреАрдЫреЗ
рдЖрдЗрдП рдкрд╣рд▓реЗ рджреЗрдЦреЗрдВ рдХрд┐ рд╕реАрдПрд▓рдЖрд░ рдФрд░ рдЬреЗрдЖрдИрдЯреА рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

JIT рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (.NET 2.0 рдХреЗ рд▓рд┐рдП .NET 4.0 / mscorwks.dll рдХреЗ рд▓рд┐рдП clr.dll) + _stdcall getJit рд╡рд┐рдзрд┐ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рдЬреЛ ICorJitCompiler рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓реМрдЯрд╛рддреА рд╣реИред
CLR (.NET 4.0 / mscorwks.dll .NET 2.0 рдХреЗ рд▓рд┐рдП clr.dll) рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп ICJJitCompiler рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреЗрдЯ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
CorJitResult compileMethod(ICorJitInfo * pJitInfo, CORINFO_METHOD_INFO * pMethodInfo, UINT nFlags, LPBYTE * pEntryAddress, ULONG * pSizeOfCode)
рдпрд╣ рд╣рд┐рд╕реНрд╕рд╛ рдЖрд╕рд╛рди рд╣реИ, рдЖрдкрдХреЛ рдмрд╕ рд╕рдВрдХрд▓рдирдорд┐рдереЛрдб рд╡рд┐рдзрд┐ рдХрд╛ рдкрддрд╛ рдвреВрдВрдврдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕реЗ EasyHook рдХреЗ рд╕рд╛рде рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ред
// ICorJitCompiler interface from JIT dll class ICorJitCompiler { public: typedef CorJitResult (__stdcall ICorJitCompiler::*PFN_compileMethod)(ICorJitInfo * pJitInfo, CORINFO_METHOD_INFO * pMethodInfo, UINT nFlags, LPBYTE * pEntryAddress, ULONG * pSizeOfCode); CorJitResult compileMethod(ICorJitInfo * pJitInfo, CORINFO_METHOD_INFO * pMethodInfo, UINT nFlags, LPBYTE * pEntryAddress, ULONG * pSizeOfCode) { return (this->*s_pfnComplieMethod)( pJitInfo, pMethodInfo, nFlags, pEntryAddress, pSizeOfCode); } private: static PFN_compileMethod s_pfnComplieMethod; }; // LPVOID pAddr = tPdbHelper.GetJitCompileMethodAddress(); LPVOID* pDest = (LPVOID*)&ICorJitCompiler::s_pfnComplieMethod; *pDest = pAddr; // compileMethod CorJitResult __stdcall CInjection::compileMethod(ICorJitInfo * pJitInfo , CORINFO_METHOD_INFO * pCorMethodInfo , UINT nFlags , LPBYTE * pEntryAddress , ULONG * pSizeOfCode ) { ICorJitCompiler * pCorJitCompiler = (ICorJitCompiler *)this; // TO DO: IL- CorJitResult result = pCorJitCompiler->compileMethod( pJitInfo, pCorMethodInfo, nFlags, pEntryAddress, pSizeOfCode); return result; } // JIT- NTSTATUS ntStatus = LhInstallHook( (PVOID&)ICorJitCompiler::s_pfnComplieMethod , &(PVOID&)CInjection::compileMethod , NULL , &s_hHookCompileMethod );
JIT рд╕рдВрдХрд▓рд┐рдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП IL рдХреЛрдб рдмрджрд▓рдирд╛
рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╕рдВрдХрд▓рди рд╡рд┐рдзрд┐ рдЬреЗрдПрд▓рдЯреА-рд╕рдВрдХрд▓рд┐рдд рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рд╕реАрдПрд▓рдЖрд░ рджреНрд╡рд╛рд░рд╛ рдирд╣реАрдВ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕реАрдПрд▓рдЖрд░ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдФрд░ рдлрд┐рд░ рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рди рд╕реЗ рдкрд╣рд▓реЗ рдЙрдиреНрд╣реЗрдВ рдмрд╣рд╛рд▓ рдХрд┐рдпрд╛ред рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬреИрд╕реЗ рд╣реА compileMethod рдХреЛ рдлрд┐рд░ рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рдо IL рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ CLR рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдереЛрдбрд╝рд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, SSCLI (рд╕рд╛рдЭрд╛ рд╕реНрд░реЛрдд рд╕рд╛рдорд╛рдиреНрдп рднрд╛рд╖рд╛ рдЗрдиреНрдлреНрд░рд╛рд╕реНрдЯреНрд░рдХреНрдЪрд░) рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕реНрд░реЛрдд рд╣реИ, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдпрд╣ рдХрд╛рдлреА рдкреБрд░рд╛рдирд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рд╛рдВ, рдпрд╣ рдпрд╣ рдЖрд░реЗрдЦ рд╣реИ рдЬреЛ рдкреБрд░рд╛рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдордЧреНрд░ рд╕рдВрд░рдЪрдирд╛ рд╕рдВрд░рдХреНрд╖рд┐рдд рд╣реИред .NET рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрдЧ рдореЗрдВ рдореЗрдореЛрд░реА рдореЗрдВ рдХрдо рд╕реЗ рдХрдо рдПрдХ MethodTable рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИред рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдердбрдЯреЗрдмрд▓ рд╕рдВрд░рдЪрдирд╛ рдПрдХ рдИрдИрд╕реАрд▓реИрд╕ рд╕реЗ рдЬреБрдбрд╝реА рд╣реИ рдЬреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдФрд░ рдЕрдиреНрдп рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд░рдирдЯрд╛рдЗрдо рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИред
рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП, рдХрдо рд╕реЗ рдХрдо рдПрдХ MethodDesc рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЭрдВрдбреЗ, рд╕реНрд▓реЙрдЯ рдкрддреЗ, рдЗрдирдкреБрдЯ рдкрддрд╛ рдЖрджрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрддреА рд╣реИред
рд╡рд┐рдзрд┐ JIT- рд╕рдВрдХрд▓рд┐рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╕реНрд▓реЙрдЯ рдПрдХ JMI рдХрдирд╡рд░реНрдЯрд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ JIT рд╕рдВрдХрд▓рди рдХреЛ рд╕реНрд╡рд┐рдЪ рдХрд░рддрд╛ рд╣реИ; рдЬрдм рдЖрдИрдПрд▓-рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЬреЗрдПрдордЖрдИ рдХреЛ рдПрдХ рд╕реВрдЪрдХ рд╕реНрд▓реЙрдЯ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╕реАрдзреЗ рд╕рдВрдХрд▓рд┐рдд рдХреЛрдб рдкрд░ рдЬрд╛рдПрдЧрд╛ред
рдЬрд╛рдирдХрд╛рд░реА рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рдЭрдВрдбреЗ рдХреЛ рд╕рд╛рдл рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдлрд┐рд░ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдХреЗ рдкрддреЗ рдХреЛ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдПрдХ рдЖрджрд┐ рдореЗрдВ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди, рдореИрдВрдиреЗ рдореЗрдореЛрд░реА рдХреЛ рд╕реАрдзреЗ рдмрджрд▓рдХрд░ рдРрд╕рд╛ рдХрд┐рдпрд╛ред рд▓реЗрдХрд┐рди рдпрд╣ рдЧрдВрджрд╛ рд╣реИ, рдХрдо рд╕реЗ рдХрдо, рдХреНрдпреЛрдВрдХрд┐ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдкрддреЗ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реИ рдФрд░ рд╡рд┐рднрд┐рдиреНрди .NET рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХрд╛ рдХреЛрдб рдЕрд▓рдЧ рд╣реИред
рдореИрдВ рд╕рд╣реА рддрд░реАрдХреЗ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣рд╛ рдерд╛, рдФрд░ рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдореБрдЭреЗ SSCLI рд╕реНрд░реЛрдд рдХреЛрдб (vm / method.cpp) рдореЗрдВ MethodDesc :: рд░реАрд╕реЗрдЯ рд╡рд┐рдзрд┐ рдорд┐рд▓реАред
void MethodDesc::Reset() { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END // , . // _ASSERTE(IsEnCMethod() || // IsDynamicMethod() || GetLoaderModule()->IsReflection()); // ClearFlagsOnUpdate(); if (HasPrecode()) { GetPrecode()->Reset(); } else { // Reflection- _ASSERTE(GetLoaderModule()->IsReflection()); InterlockedUpdateFlags2(enum_flag2_HasStableEntryPoint | enum_flag2_HasPrecode, FALSE); *GetAddrOfSlotUnchecked() = GetTemporaryEntryPoint(); } _ASSERTE(!HasNativeCode()); }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдХреЛрдб рд╕рд╣реА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореБрдЭреЗ рд╕рд┐рд░реНрдл JIT рд╕рдВрдХрд▓рди рд╕реЗ рдкрд╣рд▓реЗ MethodDesc рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдХрдбрд╝рд╛рдИ рд╕реЗ рдХрд╣реЗ рддреЛ, рдореИрдВ SSCLI рд╕реЗ рдореЗрдердбреЗрд╕рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрдердбрд╕реНрдХ рдХреЛ рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рджреНрд╡рд╛рд░рд╛ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдХреЛрдИ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рдХрд┐ рдЗрд╕рдХреЗ рдХрд╛рд░рдг рдХреНрдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЗрд╕ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рдзрд┐ рдХрд╛ рдкрддрд╛ Microsoft рдкреНрд░рддреАрдХ рд╕рд░реНрд╡рд░ рдХреЗ PDB c рдореЗрдВ рдореМрдЬреВрдж рд╣реИ, рдФрд░ рдпрд╣ рдореЗрд░реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред рд╕реАрдПрд▓рдЖрд░ рдбреАрдПрд▓рдПрд▓ рдореЗрдВ рд░реАрд╕реЗрдЯ () рд╡рд┐рдзрд┐ рдХрд╛ рдкрддрд╛ рдмрд╕ рдкреАрдбреАрдмреА рдкрд╛рд░реНрд╕ рдХрд░рдХреЗ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ!
рдЕрдм, рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреИрд░рд╛рдореАрдЯрд░ рдмрдирд╛ рд╣реБрдЖ рд╣реИ - MethodDesc рдХреЛ рдпрд╣ рдкреЙрдЗрдВрдЯрд░ред рдЗрд╕реЗ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдирд╛ рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, MethodBase.MethodHandle.Value == CORINFO_METHOD_HANDLE == MethodDesc рдкрддрд╛ == MethodDesc рдХреЛ рдпрд╣ рдкреЙрдЗрдВрдЯрд░ред
class MethodDesc { typedef void (MethodDesc::*PFN_Reset)(void); typedef BOOL (MethodDesc::*PFN_IsGenericMethodDefinition)(void); typedef ULONG (MethodDesc::*PFN_GetNumGenericMethodArgs)(void); typedef MethodDesc * (MethodDesc::*PFN_StripMethodInstantiation)(void); typedef BOOL (MethodDesc::*PFN_HasClassOrMethodInstantiation)(void); typedef BOOL (MethodDesc::*PFN_ContainsGenericVariables)(void); typedef MethodDesc * (MethodDesc::*PFN_GetWrappedMethodDesc)(void); typedef AppDomain * (MethodDesc::*PFN_GetDomain)(void); typedef Module * (MethodDesc::*PFN_GetLoaderModule)(void); public: void Reset(void) { (this->*s_pfnReset)(); } BOOL IsGenericMethodDefinition(void) { return (this->*s_pfnIsGenericMethodDefinition)(); } ULONG GetNumGenericMethodArgs(void) { return (this->*s_pfnGetNumGenericMethodArgs)(); } MethodDesc * StripMethodInstantiation(void) { return (this->*s_pfnStripMethodInstantiation)(); } BOOL HasClassOrMethodInstantiation(void) { return (this->*s_pfnHasClassOrMethodInstantiation)(); } BOOL ContainsGenericVariables(void) { return (this->*s_pfnContainsGenericVariables)(); } MethodDesc * GetWrappedMethodDesc(void) { return (this->*s_pfnGetWrappedMethodDesc)(); } AppDomain * GetDomain(void) { return (this->*s_pfnGetDomain)(); } Module * GetLoaderModule(void) { return (this->*s_pfnGetLoaderModule)(); } private: static PFN_Reset s_pfnReset; static PFN_IsGenericMethodDefinition s_pfnIsGenericMethodDefinition; static PFN_GetNumGenericMethodArgs s_pfnGetNumGenericMethodArgs; static PFN_StripMethodInstantiation s_pfnStripMethodInstantiation; static PFN_HasClassOrMethodInstantiation s_pfnHasClassOrMethodInstantiation; static PFN_ContainsGenericVariables s_pfnContainsGenericVariables; static PFN_GetWrappedMethodDesc s_pfnGetWrappedMethodDesc; static PFN_GetDomain s_pfnGetDomain; static PFN_GetLoaderModule s_pfnGetLoaderModule; };
рд╕реНрдЯреЗрдЯрд┐рдХ рд╡реИрд░рд┐рдПрдмрд▓ рдЖрдВрддрд░рд┐рдХ рдореЗрдердбреЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдкрддреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЬрдм рдПрдХ рдЕрдкреНрд░рдмрдВрдзрд┐рдд рдбреАрдПрд▓рдПрд▓ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рддрд░реАрдХреЗ рд╕рд┐рд░реНрдл рдЖрдВрддрд░рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВред
рдЕрдм рд╣рдо рдЖрд╕рд╛рдиреА рд╕реЗ Microsoft рдЖрдВрддрд░рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
MethodDesc * pMethodDesc = (MethodDesc*)pMethodHandle
рдПрдХ рдкреАрдбреАрдмреА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдкрддреЗ рдвреВрдБрдврдирд╛
рдЬрдм рдПрдХ рдорд╛рдирд╡рд░рд╣рд┐рдд DLL рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ CLR / JIT рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рдЙрд╕ рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдФрд░ рд╡рд╣ рдкреАрдбреАрдмреА рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдкрддреЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реА рд╣реИред рдпрджрд┐ рд╡реЗ рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХреЗ, рддреЛ рд╡рд╣ Microsoft рдбреАрдмрдЧ рд╕рд░реНрд╡рд░ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд PDB рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Windows Debug Tools рд╕реЗ symchk.exe рдЪрд▓рд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдЧрд╛ред рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХреБрдЫ рд╕реЗрдХрдВрдб рд╕реЗ рд▓реЗрдХрд░ рдХрдИ рдорд┐рдирдЯ рддрдХ рдХрд╛рдлреА рд▓рдВрдмрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИред рд╢рд╛рдпрдж рд╣рдо рдЕрдкрдиреЗ рд╣реИрд╢ рдХреА рдЧрд┐рдирддреА рдХрд░рдХреЗ рд╕реАрдПрд▓рдЖрд░ / рдЬреЗрдЖрдИрдЯреА рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рдкрддреЗ рдХреЛ рдХреИрд╢рд┐рдВрдЧ рдХрд░рдХреЗ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЧрддрд┐ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред
рдЧреИрд░-рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рдмрд╣рд╛рд▓ рдХрд░рдирд╛
рдЕрдм рд╕рдм рдХреБрдЫ рддреИрдпрд╛рд░ рд╣реИред рдкреНрд░рдмрдВрдзрд┐рдд рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЕрдкреНрд░рдмрдВрдзрд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдирд┐рд░реНрдпрд╛рдд рд╡рд┐рдзрд┐рдпреЛрдВ, IL рдХреЛрдб рдФрд░ MethodBase.MethodHandle.Value рдкреНрд░рдмрдВрдзрд┐рдд рдХреЛрдб рд╕реЗ рд▓реЗрддрд╛ рд╣реИред
// structure to store the IL code for replacement typedef struct _ILCodeBuffer { LPBYTE pBuffer; DWORD dwSize; } ILCodeBuffer, *LPILCodeBuffer; // method to be called by managed code BOOL CInjection::StartUpdateILCodes( MethodTable * pMethodTable , CORINFO_METHOD_HANDLE pMethodHandle , mdMethodDef md , LPBYTE pBuffer , DWORD dwSize ) { MethodDesc * pMethodDesc = (MethodDesc*)pMethodHandle; // reset this MethodDesc pMethodDesc->Reset(); ILCodeBuffer tILCodeBuffer; tILCodeBuffer.pBuffer = pBuffer; tILCodeBuffer.dwSize = dwSize; tILCodeBuffer.bIsGeneric = FALSE; // save the IL code for the method s_mpILBuffers.insert( std::pair< CORINFO_METHOD_HANDLE, ILCodeBuffer>( pMethodHandle, tILCodeBuffer) ); return TRUE; }
рдпрд╣ рдХреЛрдб рдмрд╕ рд░реАрд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ () рдФрд░ рдПрдХ рдорд╛рдирдЪрд┐рддреНрд░ рдореЗрдВ IL рдХреЛрдб рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ compileMethod рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рд╡рд┐рдзрд┐ рд╕рдВрдХрд▓рд┐рдд рд╣реЛрддреА рд╣реИред
рдФрд░ compileMethod рдореЗрдВ, рдмрд╕ IL рдХреЛрдб рдмрджрд▓реЗрдВ:
CorJitResult __stdcall CInjection::compileMethod(ICorJitInfo * pJitInfo , CORINFO_METHOD_INFO * pCorMethodInfo , UINT nFlags , LPBYTE * pEntryAddress , ULONG * pSizeOfCode ) { ICorJitCompiler * pCorJitCompiler = (ICorJitCompiler *)this; LPBYTE pOriginalILCode = pCorMethodInfo->ILCode; unsigned int nOriginalSize = pCorMethodInfo->ILCodeSize; ILCodeBuffer tILCodeBuffer = {0}; MethodDesc * pMethodDesc = (MethodDesc*)pCorMethodInfo->ftn; // find the method to be replaced std::map< CORINFO_METHOD_HANDLE, ILCodeBuffer>::iterator iter = s_mpILBuffers.find((CORINFO_METHOD_HANDLE)pMethodDesc); if( iter != s_mpILBuffers.end() ) { tILCodeBuffer = iter->second; pCorMethodInfo->ILCode = tILCodeBuffer.pBuffer; pCorMethodInfo->ILCodeSize = tILCodeBuffer.dwSize; } CorJitResult result = pCorJitCompiler->compileMethod( pJitInfo, pCorMethodInfo, nFlags, pEntryAddress, pSizeOfCode); return result; }
рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐
рдЬреЗрдиреЗрд░рд┐рдХ рд╡рд┐рдзрд┐ MethodDesc рдореЗрдВ рдореЗрдореЛрд░реА рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддреА рд╣реИред рд▓реЗрдХрд┐рди рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЬреЗрдиреЗрд░рд┐рдХ рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рд╕реАрдПрд▓рдЖрд░ рдПрдХ рд╣реА рд╡рд┐рдзрд┐ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдирд┐рдХрд╛рдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдиреАрдЪреЗ рджреА рдЧрдИ рд▓рд╛рдЗрди рдПрдХ рдбреЗрдореЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╕реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЬреЗрдиреЗрд░рд┐рдХ рд╣реИред
string GenericMethodToBeReplaced<T, K>(T t, K k)
GenericMethodToBeReplaced <string, int> ("11", 2) рдХреЛ рдкрд╣рд▓реА рдмрд╛рд░ рдХреЙрд▓ рдХрд░рдХреЗ, CLR рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рдмрдирд╛рддрд╛ рд╣реИ InstantiatedMethodDesc (MethodDesc рдХрд╛ рдмрдЪреНрдЪрд╛, рдФрд░ рдЗрд╕рдХрд╛ рдзреНрд╡рдЬ mcInstantied рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рд╣реИ), рдЬреЛ InstMethodHashTash рдореЗрдВ рд╡рд┐рдзрд┐ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред
рдФрд░ GenericMethodToBeReplaced <long, int> (1, 2) рдХреЙрд▓ рдХрд░рдХреЗ, CLR рдПрдХ рдФрд░ InstantMatedMethodDesc рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рднреА InstantiatedMethodDesc рдЬреЗрдиреЗрд░рд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдФрд░ рдЙрди рдкрд░ рд░реАрд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
SSCLI рд╕реНрд░реЛрдд рдХреЛрдб (vm / proftoeeinterfaceimpl.cpp) рдореЗрдВ рдПрдХ LoadedMethodDescIterator рд╡рд░реНрдЧ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рддреАрди рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╡рд┐рдзрд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ (MethodToken) рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИред
LoadedMethodDescIterator MDIter(ADIter.GetDomain(), pModule, methodId); while(MDIter.Next()) { MethodDesc * pMD = MDIter.Current(); if (pMD) { _ASSERTE(pMD->IsIL()); pMD->SetRVA(rva); } }
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдкреАрдбреАрдмреА рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░, рдиреЗрдХреНрд╕реНрдЯ, рдХрд░рдВрдЯ рддрд░реАрдХреЛрдВ рдХреЗ рдкрддреЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рдЗрддрдирд╛ рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдореЗрдВ LoadedMethodDescIterator рдХрд╛ рд╕рдЯреАрдХ рдЖрдХрд╛рд░ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ, рд╣рдо рд╕рд┐рд░реНрдл рдЗрд╕рдХреЗ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рдмреНрд▓реЙрдХ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
class LoadedMethodDescIterator { private: BYTE dummy[10240]; };
рдореИрдВ рдЗрд╕ рддрдереНрдп рдкрд░ рднреА рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рд╕рдВрд╕реНрдХрд░рдг 2.0 рд╕реЗ 4.5 рддрдХ .NET рдХреЗ рд╕рдВрдХреНрд░рдордг рдХреЗ рджреМрд░рд╛рди рдиреЗрдХреНрд╕реНрдЯ () рд╡рд┐рдзрд┐ рдореЗрдВ рдЫреЛрдЯреЗ рдмрджрд▓рд╛рд╡ рдереЗред
// .Net 2.0 & 4.0 LoadedMethodDescIterator(AppDomain * pAppDomain, Module *pModule, mdMethodDef md) BOOL LoadedMethodDescIterator::Next(void) // .Net 4.5 LoadedMethodDescIterator(AppDomain * pAppDomain, Module *pModule, mdMethodDef md,enum AssemblyIterationMode mode) BOOL LoadedMethodDescIterator::Next(CollectibleAssemblyHolder<DomainAssembly *> *)
рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП .NET рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
// detect the version of CLR BOOL DetermineDotNetVersion(void) { WCHAR wszPath[MAX_PATH] = {0}; ::GetModuleFileNameW( g_hClrModule, wszPath, MAX_PATH); CStringW strPath(wszPath); int nIndex = strPath.ReverseFind('\\'); if( nIndex <= 0 ) return FALSE; nIndex++; CStringW strFilename = strPath.Mid( nIndex, strPath.GetLength() - nIndex); if( strFilename.CompareNoCase(L"mscorwks.dll") == 0 ) { g_tDotNetVersion = DotNetVersion_20; return TRUE; } if( strFilename.CompareNoCase(L"clr.dll") == 0 ) { DWORD dwHandle = NULL; UINT nSize = 0; LPBYTE lpBuffer = NULL; BYTE szTempBuf[2048] = {0}; DWORD dwSize = GetFileVersionInfoSizeW( wszPath, &dwHandle); if (dwSize != NULL) { LPVOID pData = szTempBuf; if (GetFileVersionInfo( wszPath, dwHandle, dwSize, pData)) { if (VerQueryValueW( pData, L"\\",(VOID FAR* FAR*)&lpBuffer,&nSize)) { if (nSize) { VS_FIXEDFILEINFO * pVerInfo = (VS_FIXEDFILEINFO *)lpBuffer; if (pVerInfo->dwSignature == 0xfeef04bd) { int nMajor = HIWORD(pVerInfo->dwFileVersionMS); int nMinor = LOWORD(pVerInfo->dwFileVersionMS); int nBuildMajor = HIWORD(pVerInfo->dwFileVersionLS); int nBuildMinor = LOWORD(pVerInfo->dwFileVersionLS); if( nMajor == 4 && nMinor == 0 && nBuildMajor == 30319 ) { if( nBuildMinor < 10000 ) g_tDotNetVersion = DotNetVersion_40; else g_tDotNetVersion = DotNetVersion_45; return TRUE; } } } } } return FALSE; } } return FALSE; }
рдЕрдм рд╣рдо рдЕрдкрдиреЗ LoadMethodDescIterator рдХреА рдШреЛрд╖рдгрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╕реАрдПрд▓рдЖрд░ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред
enum AssemblyIterationMode { AssemblyIterationMode_Default = 0 }; class LoadedMethodDescIterator { typedef void (LoadedMethodDescIterator::*PFN_LoadedMethodDescIteratorConstructor)(AppDomain * pAppDomain, Module *pModule, mdMethodDef md); typedef void (LoadedMethodDescIterator::*PFN_LoadedMethodDescIteratorConstructor_v45)(AppDomain * pAppDomain, Module *pModule, mdMethodDef md, AssemblyIterationMode mode); typedef void (LoadedMethodDescIterator::*PFN_Start)(AppDomain * pAppDomain, Module *pModule, mdMethodDef md); typedef BOOL (LoadedMethodDescIterator::*PFN_Next_v4)(LPVOID pParam); typedef BOOL (LoadedMethodDescIterator::*PFN_Next_v2)(void); typedef MethodDesc* (LoadedMethodDescIterator::*PFN_Current)(void); public: LoadedMethodDescIterator(AppDomain * pAppDomain, Module *pModule, mdMethodDef md) { memset( dummy, 0, sizeof(dummy)); memset( dummy2, 0, sizeof(dummy2)); if( s_pfnConstructor ) (this->*s_pfnConstructor)( pAppDomain, pModule, md); if( s_pfnConstructor_v45 ) (this->*s_pfnConstructor_v45)( pAppDomain, pModule, md, AssemblyIterationMode_Default); } void Start(AppDomain * pAppDomain, Module *pModule, mdMethodDef md) { (this->*s_pfnStart)( pAppDomain, pModule, md); } BOOL Next() { if( s_pfnNext_v4 ) return (this->*s_pfnNext_v4)(dummy2); if( s_pfnNext_v2 ) return (this->*s_pfnNext_v2)(); return FALSE; } MethodDesc* Current() { return (this->*s_pfnCurrent)(); } private:
рдЕрдВрдд рдореЗрдВ, рд╣рдо рдЬреЗрдиреЗрд░рд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд░реАрд╕реИрдЯ () рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП LoadedMethodDescIterator рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
Module * pModule = pMethodDesc->GetLoaderModule(); AppDomain * pAppDomain = pMethodDesc->GetDomain(); if( pModule ) { LoadedMethodDescIterator * pLoadedMethodDescIter = new LoadedMethodDescIterator( pAppDomain, pModule, md); while(pLoadedMethodDescIter->Next()) { MethodDesc * pMD = pLoadedMethodDescIter->Current(); if( pMD ) pMD->Reset(); } delete pLoadedMethodDescIter; }
рд╕рдВрдХрд▓рди рдФрд░ рдЕрдиреБрдХреВрд▓рди
рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдпрджрд┐ рд╡рд┐рдзрд┐ рдмрд╣реБрдд рдЫреЛрдЯреА рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рдЖрдХрд╛рд░ рдХреЗрд╡рд▓ рдХреБрдЫ рдмрд╛рдЗрдЯреНрд╕ рд╣реИ, рддреЛ рдпрд╣ рдЗрдирд▓рд╛рдЗрди рдореЛрдб рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, MethodDesc :: Reset () рдорджрдж рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд░рди рдЯрд╛рдЗрдо рдкрд░, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдХреЙрд▓ рднреА рдирд╣реАрдВ рдорд┐рд▓реЗрдЧрд╛ред рдХреБрдЫ рдФрд░ рдЬрд╛рдирдХрд╛рд░реА CEEInfo :: canInline (vmред / / Jitinterface.cpp рдореЗрдВ SSCLC) рд╕реЗ рдорд┐рд▓ рд╕рдХрддреА рд╣реИред
рдЧрддрд┐рд╢реАрд▓ рд╡рд┐рдзрд┐рдпрд╛рдБ
IL рдХреЛрдб рдореЗрдВ рдбрд╛рдпрдирд╛рдорд┐рдХ рддрд░реАрдХреЗ рдЬреЛрдбрд╝рдиреЗ рдкрд░, рдЖрдкрдХреЛ рдмрд╣реБрдд рд╕рд╛рд╡рдзрд╛рди рд░рд╣рдирд╛ рд╣реЛрдЧрд╛ред рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдЧрд▓рдд IL рдХреЛрдб рдЬреЛрдбрд╝рдирд╛ рдХреЗрд╡рд▓ InvalidApplicationException рдХреЛ рдмрдврд╝рд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдбрд╛рдпрдиреЗрдорд┐рдХ рд╡рд┐рдзрд┐ рдореЗрдВ рдЧрд▓рдд IL рдХреЛрдб рдЬреЛрдбрд╝рдиреЗ рд╕реЗ CLR рдФрд░ рд╣рдорд╛рд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рдкреВрд░реНрдг рд╡рд┐рдлрд▓рддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред рдбрд╛рдпрдиреЗрдорд┐рдХ рдХреЛрдб IL рдмрд╛рдХреА рд╕реЗ рдЕрд▓рдЧ рд╣реИред рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ рдПрдХ рдФрд░ рдЧрддрд┐рд╢реАрд▓ рд╡рд┐рдзрд┐ рд╕реЗ рдЖрдИрдПрд▓ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛, рдФрд░ рдлрд┐рд░ рдХреЙрдкреА рдФрд░ рдкреЗрд╕реНрдЯ рдХрд░рдирд╛ред
рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓реЗрдВ