<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET高級調(diào)試 | 通過JIT攔截無侵入調(diào)試 C# Emit 生成的動態(tài)代碼

          共 4315字,需瀏覽 9分鐘

           ·

          2022-04-19 12:27

          大家還記得上一篇的測試代碼嗎?我們用了:


          Console.WriteLine("Function?Pointer:?0x{0:x16}",?Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());

          來獲得 委托函數(shù)指針 地址,通過這個突破口最終實現(xiàn)了 動態(tài)代碼 的調(diào)試,這種方式可以是可以,但很顯然這是侵入式的,那有沒有辦法實現(xiàn) 非侵入 調(diào)試動態(tài)代碼呢?在 .NET高級調(diào)試 這本書上還真給找到了,方法就是在 ?JIT 編譯動態(tài)方法時進行攔截,獲取其中的 方法描述符。

          為了方便講解,先上測試代碼:


          ????class?Program
          ????{
          ????????private?delegate?int?AddDelegate(int?a,?int?b);

          ????????static?void?Main(string[]?args)
          ????????{
          ????????????var?dynamicAdd?=?new?DynamicMethod("Add",?typeof(int),?new[]?{?typeof(int),?typeof(int)?},?true);
          ????????????var?il?=?dynamicAdd.GetILGenerator();
          ????????????il.Emit(OpCodes.Ldarg_0);
          ????????????il.Emit(OpCodes.Ldarg_1);
          ????????????il.Emit(OpCodes.Add);
          ????????????il.Emit(OpCodes.Ret);

          ????????????var?addDelegate?=?(AddDelegate)dynamicAdd.CreateDelegate(typeof(AddDelegate));

          ????????????//Debugger.Break();
          ????????????//Console.WriteLine("Function?Pointer:?0x{0:x16}",?Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());

          ????????????Console.WriteLine(addDelegate(10,?20));
          ????????}
          ????}

          可以看到,我把上面兩行侵入式的代碼給屏蔽掉了,接下來在 il.Emit(OpCodes.Ret); 處下斷點,目的是為了在 clr 加載后尋找 JIT的 compileMethod 方法。


          0:000>?!mbp?Program.cs?28
          The?CLR?has?not?yet?been?initialized?in?the?process.
          Breakpoint?resolution?will?be?attempted?when?the?CLR?is?initialized.
          0:000>?g
          ModLoad:?76910000?7698a000???C:\Windows\SysWOW64\ADVAPI32.dll
          ...
          ModLoad:?77190000?77226000???C:\Windows\SysWOW64\OLEAUT32.dll
          Breakpoint:?JIT?notification?received?for?method?ConsoleApp1.Program.Main(System.String[])?in?AppDomain?00783758.
          Breakpoint?set?at?ConsoleApp1.Program.Main(System.String[])?in?AppDomain?00783758.
          Breakpoint?1?hit
          eax=00000001?ebx=0019f5ac?ecx=023c3684?edx=ffffffff?esi=023c230c?edi=0019f4fc
          eip=048a0a02?esp=0019f4ac?ebp=0019f508?iopl=0?????????nv?up?ei?pl?zr?na?pe?nc
          cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000246
          048a0a02?b901000000??????mov?????ecx,1

          接下來可以用 x 命令模糊搜索 compileMethod 簽名,找出簽名是為了更好的下斷點。


          0:000>?x?*!*compileMethod*
          ...
          61413700??????????clrjit!CILJit::compileMethod?(class?ICorJitInfo?*,?struct?CORINFO_METHOD_INFO?*,?unsigned?int,?unsigned?char?**,?unsigned?long?*)


          可以看到 compileMethod 的完整簽名是 clrjit!CILJit::compileMethod, 并且它的方法入口點地址是 61413700,有了它就可以對其下斷點啦!


          0:000>?bp?61413700
          0:000>?g
          Breakpoint?0?hit
          eax=61494698?ebx=80000004?ecx=61413700?edx=00005c10?esi=6148b3fc?edi=0019efa4
          eip=61413700?esp=0019ede0?ebp=0019ee38?iopl=0?????????nv?up?ei?ng?nz?na?po?nc
          cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000282
          clrjit!CILJit::compileMethod:
          61413700?55??????????????push????ebp
          0:000>?kb
          ?#?ChildEBP?RetAddr??????Args?to?Child??????????????
          00?0019ee38?62a4ccc3?????61494698?0019efa4?0019ef1c?clrjit!CILJit::compileMethod?[f:\dd\ndp\clr\src\jit32\ee_il_dll.cpp?@?151]?
          01?0019ee38?62a4cd9b?????0019ef1c?0019f06c?0019f024?clr!invokeCompileMethodHelper+0x10b

          很開心,成功命中,接下來提取 compileMethod 方法的第三個參數(shù),它就是需要編譯方法所指向的 方法描述符 地址,可以用 dp 給提取出來。


          0:000>?dp?0019ef1c?L1
          0019ef1c??0071537c
          0:000>?!dumpmd?0071537c
          Method?Name:??DynamicClass.Add(Int32,?Int32)
          Class:????????007152e8
          MethodTable:??0071533c
          mdToken:??????06000000
          Module:???????00714ea8
          IsJitted:?????no
          CodeAddr:?????ffffffff
          Transparency:?Transparent

          方法描述符果然給調(diào)出來了,但這里的方法字節(jié)碼是 CodeAddr: ffffffff ,說明此時動態(tài)方法還沒有開始編譯,為了能夠使其編譯,我們在 Console.WriteLine(addDelegate(10, 20)); 處再下一個斷點,因為代碼到此處時, JIT 肯定編譯了該辦法,自然就能看到編譯后的 CodeAddr 地址。


          0:000>?!mbp?Program.cs?35
          Breakpoint?set?at?ConsoleApp1.Program.Main(System.String[])?in?AppDomain?00783758.
          0:000>?g
          Breakpoint?3?hit
          eax=023c5f88?ebx=0019f5ac?ecx=023c5f3c?edx=00008f17?esi=023c230c?edi=0019f4fc
          eip=048a0a9b?esp=0019f4ac?ebp=0019f508?iopl=0?????????nv?up?ei?pl?zr?na?pe?nc
          cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000246
          048a0a9b?6a14????????????push????14h
          0:000>?!dumpmd?0071537c
          Method?Name:??DynamicClass.Add(Int32,?Int32)
          Class:????????007152e8
          MethodTable:??0071533c
          mdToken:??????06000000
          Module:???????00714ea8
          IsJitted:?????yes
          CodeAddr:?????04a00050
          Transparency:?Transparent

          可以看到,此時的 CodeAddr: 04a00050 ,也就表明已經(jīng)編譯完成了,接下來繼續(xù) bp 。


          0:000>?bp?04a00050
          0:000>?g
          Breakpoint?4?hit
          eax=023c5f98?ebx=0019f5ac?ecx=0000000a?edx=00000014?esi=023c230c?edi=0019f4fc
          eip=04a00050?esp=0019f4a8?ebp=0019f508?iopl=0?????????nv?up?ei?pl?nz?na?po?nc
          cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000202
          04a00050?8bc1????????????mov?????eax,ecx

          可以看到,全部搞定,非侵入式,??


          瀏覽 116
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  蜜桃视频色五月婷婷 | 日韩精品在线免费观看 | 蜜乳一区二区三区四区五区六区 | 中圆A1变臉性爱免费视频在线 | 国产黄色片片片 |