在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風(fēng)下載站 > 技術(shù)開發(fā)教程 > 詳細頁面

用WinDbg探索CLR世界 [3] 跟蹤辦法的 JIT 過程

用WinDbg探索CLR世界 [3] 跟蹤辦法的 JIT 過程

更新時間:2022-04-26 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

本來想按照 sos 的幫助文件上命令的分類逐步介紹 WinDbg 下使用 sos 調(diào)試 CLR 程序,但發(fā)現(xiàn)這樣實在不夠直觀。索性改成根據(jù)我分析 CLR 的實際案例,step by step 介紹功能,這樣結(jié)構(gòu)上雖然混亂一點,但更加直觀,也易于上手 :P

前面兩篇文章里面分別介紹了 WinDbg 的調(diào)試配置和線程的基本概念,這篇文章將針對 JIT 編譯對象方法的流程進行分析,逐步介紹如何使用 WinDbg 調(diào)試 CLR 程序。

用WinDbg探索CLR世界 [1] - 安裝與環(huán)境配置
用WinDbg探索CLR世界 [2] - 線程

首先寫一個簡單的例子程序 demo.cs 并編譯為 demo.exe,使用配置好的 WinDbg 打開之:


以下為引用:

using System;

namespace flier
{
class EntryPoint
{
public void m1()
{
System.Console.Write("EntryPoint.m1()");
}

public void m2()
{
System.Console.Write("EntryPoint.m2()");
}

public static void Main()
{
EntryPoint ep = new EntryPoint();

ep.m1();
ep.m2();
}
}
}




WinDbg 會在載入 demo.exe 后中斷執(zhí)行。此時可以使用 .load sos 命令加載 sos.dll 命令擴展,并用 .chain 驗證加載是否成功;然后用 ld demo 命令加載 demo.exe 的調(diào)試符號文件,用 lm 命令驗證加載是否成功。
然后用 ld kernel32 加載 Kernel32 的調(diào)試符號文件,并用 bp kernel32!LoadLibraryExW "du poi(esp+4)" 命令在載入 DLL 的函數(shù)入口加上斷點。接下來就是一路 g 指令,直到 mscorwks.dll 被加載。這個 mscorwks.dll 就是類似 JVM 中 jvm.dll 的虛擬機實現(xiàn)代碼,我們要了解的大部分功能都在其中。詳細的解釋可以參看我以前的一篇文章《.Net平臺下CLR程序載入原理分析》

在 mscorwks.dll 被載入后用 ld mscorwks 命令載入其調(diào)試符號庫,就可以正式開始我們的探索工作了 :D

目前使用到的 WinDbg 命令如下



以下為引用:

.load sos // 加載 sos 調(diào)試擴展模塊,可使用 .chain 命令驗證

ld demo // 加載 demo.exe 調(diào)試符號庫,可使用 lm 命令驗證

ld kernel32 // 加載 kernel32.exe 調(diào)試符號庫

bp kernel32!LoadLibraryExW "du poi(esp+4)" // 設(shè)置斷點監(jiān)視何時 mscorwks.dll 被載入

g // 執(zhí)行直到 mscorwks.dll被加載

bd 0 // 清除前面設(shè)置的斷點,開始對 mscorwks.dll 進行處理

ld mscorwks // 加載 mscorwks.dll 調(diào)試符號庫





Don Box 在《.NET本質(zhì)論 第1卷:公共語言運行庫》的第六章介紹了方法調(diào)用的內(nèi)部實現(xiàn)流程。其中提到方法表在 JIT 之前,保存的都是 call mscorwks.dll!PreStubWorker 調(diào)用,直到第一次使用時,才會對目標 IL 代碼進行 JIT 編譯,并調(diào)用之。因此我們第一步可以在此函數(shù)上設(shè)置斷點(bp mscorwks!PreStubWorker),看看系統(tǒng)是如何調(diào)用此函數(shù)的。


以下為引用:

0:000> bp mscorwks!PreStubWorker
0:000> g
ModLoad: 70ad0000 70bb6000 E:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.100.0_x-ww_8417450B\comctl32.dll
ModLoad: 79780000 79980000 e:\windows\microsoft.net\framework\v1.1.4322\mscorlib.dll
ModLoad: 79980000 79ca6000 e:\windows\assembly\nativeimages1_v1.1.4322\mscorlib\1.0.5000.0__b77a5c561934e089_ed6bc96c\mscorlib.dll
ModLoad: 79510000 79523000 E:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorsn.dll
Breakpoint 1 hit
eax=0012f7c0 ebx=00148c60 ecx=04aa112c edx=00000004 esi=0012f784 edi=0012f9a8
eip=791d6a4a esp=0012f764 ebp=0012f79c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
mscorwks!PreStubWorker:
791d6a4a 55 push ebp




斷點被激活就代表函數(shù)被調(diào)用。我們先使用 k 看看函數(shù)被調(diào)用時的上下文環(huán)境。


以下為引用:

0:000> k
ChildEBP RetAddr
0012f760 0014930e mscorwks!PreStubWorker
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012f79c 791da434 0x14930e
0012f8b4 791dd2ec mscorwks!MethodDesc::CallDescr+0x1b6
0012f96c 79240405 mscorwks!MethodDesc::Call+0xc5
0012fa18 79240520 mscorwks!AppDomain::InitializeDomainContext+0x10f
0012fa7c 7923d744 mscorwks!SystemDomain::InitializeDefaultDomain+0x11c
0012fd60 791c6e73 mscorwks!SystemDomain::ExecuteMainMethod+0x120
0012ffa0 791c6ef3 mscorwks!ExecuteEXE+0x1c0
0012ffb0 7880a53e mscorwks!_CorExeMain+0x59
0012ffc0 77e1f38c mscoree!_CorExeMain+0x30 [f:\dd\ndp\clr\src\dlls\shim\shim.cpp @ 5426]
0012fff0 00000000 KERNEL32!BaseProcessStart+0x23




這里可以看到從 mscoree!_CorExeMain 一路執(zhí)行下來的步驟,而那個警告說明這個 stack frame 不在任意一個已知模塊中。這是很正常的,因為這個棧幀實際上是指向由 JIT 動態(tài)生成的代碼。我們監(jiān)視的 mscorwks!PreStubWorker 函數(shù)只是作為方法表中函數(shù)的入口 stub,系統(tǒng)啟動時還會通過其他方式調(diào)用 JIT 完成代碼的編譯執(zhí)行。
接下來用 SOS 的 !clrstack 命令看看 CLR 的調(diào)用堆棧,顯示如下:


以下為引用:

0:000> !clrstack
succeeded
Loaded Son of Strike data table version 5 from "E:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"
Thread 0
ESP EIP
0012f784 791d6a4a [FRAME: PrestubMethodFrame] [DEFAULT] [hasThis] Void System.AppDomain.SetupDomain(ValueClass System.LoaderOptimization,String,String)
0012f9a8 791d6a4a [FRAME: GCFrame]
0012fad0 791d6a4a [FRAME: DebuggerClassInitMarkFrame]
0012fa94 791d6a4a [FRAME: GCFrame]




如果需要更為詳細的詳細,可以使用 -p, -l 或 -r 參數(shù)分別顯示參數(shù)、局部變量和寄存器,當然前兩者需要調(diào)試符號庫的支持才行。

如此一路 g; !clrstack 執(zhí)行下去,直到 flier.EntryPoint.m1 函數(shù)需要被處理為止:


以下為引用:

0:000> !clrstack
Thread 0
ESP EIP
0012f68c 791d6a4a [FRAME: PrestubMethodFrame] [DEFAULT] [hasThis] Void flier.EntryPoint.m1()
0012f69c 06d90080 [DEFAULT] Void flier.EntryPoint.Main()
0012f9b0 791da717 [FRAME: GCFrame]
0012fa94 791da717 [FRAME: GCFrame]




此時用 !dumpstackobjects 命令可以查看當前線程堆棧中使用的所有對象


以下為引用:

0:000> !dumpstackobjects
ESP/REG Object Name
ecx 04aa1a90 flier.EntryPoint
0012f678 04aa1a90 flier.EntryPoint
0012f67c 04aa1a90 flier.EntryPoint
0012f680 04aa1a90 flier.EntryPoint




這里的 flier.EntryPoint 對象地址 0x04aa1a90 就是我們要分析的對象在內(nèi)存中的位置。

這一階段使用到的 WinDbg 命令如下:


以下為引用:

bp mscorwks!PreStubWorker // 設(shè)置代碼斷點

g // 繼續(xù)運行至斷點

k // 查看函數(shù)調(diào)用時的 Native 堆棧調(diào)用

!clrstack // 查看函數(shù)調(diào)用時的 CLR 堆棧調(diào)用

!dumpstackobjects // 查看線程堆棧中使用到的所有對象





知道地址后,就可以用 !dumpobj 命令查看對象的詳細信息


以下為引用:

0:000> !dumpobj 04aa1a90
Name: flier.EntryPoint
MethodTable 0x009750a8
EEClass 0x06c632e8
Size 12(0xc) bytes
mdToken: 02000002 (D:\Temp\demo.exe)




信息包括對象的類型名字(Name)和類型信息的地址(EEClass),以及對象的大小(Size)和 Token (mdToken),而方法表 (MethodTable) 正是我們分析方法調(diào)用的目標。我們可以用 !dumpclass 命令先進一步查看對象的類型信息:


以下為引用:

0:000> !dumpclass 0x6c632e8
Class Name : flier.EntryPoint
mdToken : 02000002 ()
Parent Class : 79b7c3c8
ClassLoader : 00153850
Method Table : 009750a8
Vtable Slots : 4
Total Method Slots : 8
Class Attributes : 100000 :
Flags : 1000003
NumInstanceFields: 0
NumStaticFields: 0
ThreadStaticOffset: 0
ThreadStaticsSize: 0
ContextStaticOffset: 0
ContextStaticsSize: 0




可以發(fā)現(xiàn)其信息與對象信息有很多符合之處,正如 Don Box 所說,一個對象引用指向一個類型 EEClass 實例,而方法表為類型所有,其對象共有。我們可以使用 !dumpmt 命令進一步查看方法表的信息,-md 參數(shù)表示需要查看每個方法描述 (MethodDesc):


以下為引用:

0:000> !dumpmt -md 0x09750a8
EEClass : 06c632e8
Module : 0014e090
Name: flier.EntryPoint
mdToken: 02000002 (D:\Temp\demo.exe)
MethodTable Flags : 80000
Number of IFaces in IFaceMap : 0
Interface Map : 009750f4
Slots in VTable : 8
--------------------------------------
MethodDesc Table
Entry MethodDesc JIT Name
79b7c4eb 79b7c4f0 None [DEFAULT] [hasThis] String System.Object.ToString()
79b7c473 79b7c478 None [DEFAULT] [hasThis] Boolean System.Object.Equals(Object)
79b7c48b 79b7c490 None [DEFAULT] [hasThis] I4 System.Object.GetHashCode()
79b7c52b 79b7c530 None [DEFAULT] [hasThis] Void System.Object.Finalize()
0097506b 00975070 None [DEFAULT] [hasThis] Void flier.EntryPoint.m1()
0097507b 00975080 None [DEFAULT] [hasThis] Void flier.EntryPoint.m2()
0097508b 00975090 None [DEFAULT] Void flier.EntryPoint.Main()
0097509b 009750a0 None [DEFAULT] [hasThis] Void flier.EntryPoint..ctor()




可以看到方法表中共有8個表項,其中前4個已經(jīng)綁定到使用 ngen 預(yù)編譯好的靜態(tài)函數(shù)上


以下為引用:

0:000> u 79b7c4eb
mscorlib_79980000+0x1fc4eb:
79b7c4eb e8909cfeff call mscorlib_79980000+0x1e6180 (79b66180)
79b7c4f0 0000 add [eax],al
79b7c4f2 0080d86206c0 add [eax+0xc00662d8],al
79b7c4f8 06 push es
79b7c4f9 00fc add ah,bh
79b7c4fb e8809cfeff call mscorlib_79980000+0x1e6180 (79b66180)
79b7c500 07 pop es
79b7c501 0010 add [eax],dl




后四個則作為可被覆蓋的虛方法在方法表中,這也是為什么在查看類型信息時 Vtable Slots = 4 而 Total Method Slots = 8 的原因。

對方法表的每個項目,可以用 !DumpMD 命令查看詳細描述,如


以下為引用:

0:000> !DumpMD 0x00975070
Method Name : [DEFAULT] [hasThis] Void flier.EntryPoint.m1()
MethodTable 9750a8
Module: 14e090
mdToken: 06000001 (D:\Temp\demo.exe)
Flags : 0
IL RVA : 00002050




IL RVA 說明此方法的 IL 代碼相對虛擬地址(IL RVA),也就是說此方法還沒有被 JIT,仍以 IL 代碼形式存在。對于已經(jīng)完成 JIT 的方法,將顯示其 JIT 后函數(shù)體代碼的虛擬地址(Method VA):


以下為引用:

0:000> !DumpMD 0x009750a0
Method Name : [DEFAULT] [hasThis] Void flier.EntryPoint..ctor()
MethodTable 9750a8
Module: 14e090
mdToken: 06000004 (D:\Temp\demo.exe)
Flags : 0
Method VA : 06d900a8





這一階段使用到的 WinDbg 命令如下:


以下為引用:

!dumpobj 04aa1a90 // 查看對象的詳細信息

!dumpclass 0x6c632e8 // 查看類型的詳細信息

!dumpmt -md 0x09750a8 // 查看方法表的詳細信息

!dumpmd 0x00975070 // 查看方法表項的方法描述的詳細信息

u 0x79b7c4eb // 反匯編指定地址的指令





我們反匯編一下 !DumpMT 命令列出的幾個方法,就會發(fā)現(xiàn)正如 Don Box 所說,已經(jīng)被 JIT 的代碼指向一個jmp指令,直接跳轉(zhuǎn)到編譯后的方法體,如:


以下為引用:

0:000> u 0097509b
0097509b e908b04106 jmp 06d900a8




而沒有被 JIT 的函數(shù),則指向一個call指令,調(diào)用一個 prolog 代碼,間接調(diào)用 mscorwks!PreStubWorker 函數(shù)完成實際 JIT 工作,如:


以下為引用:

0:000> u 0x0097506b
0097506b e878427dff call 001492e8

0:000> u 0x0097507b
0097507b e868427dff call 001492e8




這個 prolog 代碼很簡單,負責(zé)構(gòu)造 mscorwks!PreStubWorker 所需的調(diào)用堆棧


以下為引用:

0:000> u 0x001492e8
001492e8 52 push edx
001492e9 68f0301b79 push 0x791b30f0
001492ee 55 push ebp
001492ef 53 push ebx
001492f0 56 push esi
001492f1 57 push edi
001492f2 8d742410 lea esi,[esp+0x10]
001492f6 51 push ecx
001492f7 52 push edx
001492f8 648b1d2c0e0000 mov ebx,fs:[00000e2c]
001492ff 8b7b08 mov edi,[ebx+0x8]
00149302 897e04 mov [esi+0x4],edi
00149305 897308 mov [ebx+0x8],esi
00149308 56 push esi
00149309 e83cd70879 call mscorwks!PreStubWorker (791d6a4a)
0014930e 897b08 mov [ebx+0x8],edi
00149311 894604 mov [esi+0x4],eax
00149314 5a pop edx
00149315 59 pop ecx
00149316 5f pop edi
00149317 5e pop esi
00149318 5b pop ebx
00149319 5d pop ebp
0014931a 83c404 add esp,0x4
0014931d 8f0424 pop [esp]
00149320 c3 ret




而這段 prolog 代碼是由類似 ROTOR 中的 GeneratePrestub 函數(shù)(vm\i386\cgenx86.cpp:1829) 動態(tài)生成的,完成對 PreStubWorker 函數(shù)調(diào)用的封裝。而 PreStubWorker 函數(shù)會調(diào)用 JIT 完成真正的函數(shù)編譯工作,并將方法表的入口改為指向編譯后函數(shù)體的 jmp 指令。具體的流程請參考Don Box 在《.NET本質(zhì)論 第1卷:公共語言運行庫》的第六章中的介紹,這里就不再羅嗦了。以后有機會再寫篇文章詳細分析一下 JIT 的工作流程。

在 JIT 處理 flier.EntryPoint.m1 時,用 g 命令執(zhí)行,再回頭來分析 m1 函數(shù)的入口,就會發(fā)現(xiàn)如前面所述,調(diào)用 JIT 過程的 call 指令變成了直接調(diào)用 Native 函數(shù)體的 jmp 指令。:D


這一小節(jié),我們介紹了使用 WinDbg 跟蹤調(diào)試 CLR 程序的一遍流程,并了解了對堆棧、對象和類信息進行分析的 SOS 命令,希望大家能夠借此開始探索 CLR 內(nèi)部世界的旅程。 :P

Jason Zander在其 BLog 的一篇文章,SOS Debugging with the CLR (Part 1),里面也詳細介紹了使用 WinDbg 和 SOS 調(diào)試 CLR 程序的部分方法,

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統(tǒng)下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 国风产精品一区二区| 国产精品国产三级国产专区51| 五月天男人天堂| 成人性做爰aaa片免费看不忠| 蜜臀av色欲a片无码精品一区| 国产高清免费在线| 日本一二三区在线| 日韩av片免费观看| 亚洲高清av一区二区三区| 亚洲免费黄色录像| 精品国产三级a∨在线| 99精品视频免费版的特色功能| 欧美第一页浮力影院| 成年网站在线播放| 国产探花在线观看视频| 色撸撸在线观看| 免费成人深夜夜行网站视频| 特级西西人体www高清大胆| 日本丰满大乳奶| 人人妻人人做人人爽| 91免费视频网站在线观看| 久久精品影视大全| 色黄视频免费看| 免费观看国产精品视频| 成人免费在线小视频| www.超碰97.com| 国产精品国产三级国产专区51| 日韩精品xxxx| 超碰在线资源站| 国产中文字幕二区| 国产一伦一伦一伦| 日韩精品一区二区免费| 日本va中文字幕| 欧美与动交zoz0z| 无码内射中文字幕岛国片| 午夜福利123| 精品久久久久av| 国产奶头好大揉着好爽视频| 免费毛片小视频| 久久免费视频2| 激情综合网婷婷| 麻豆映画在线观看| 中文字幕一区二区三区四区在线视频| 91网址在线观看精品| 丰满少妇被猛烈进入高清播放| 成人黄色一级大片| 北条麻妃在线视频| 极品粉嫩国产18尤物| 亚洲黄色av片| av无码精品一区二区三区| 日韩一级性生活片| 亚洲国产精品女人| 手机免费av片| 污污视频网站免费观看| 国产精品成人久久电影| 国产又黄又爽免费视频| 免费看涩涩视频| 在线观看免费成人av| www.浪潮av.com| 亚洲国产成人精品无码区99| 91网址在线观看精品| www.色就是色.com| 国产免费又粗又猛又爽| 乱妇乱女熟妇熟女网站| 国产黄色片免费在线观看| 中文字幕av久久| 99热都是精品| 欧美日韩午夜爽爽| 国产精品无码电影在线观看| www.亚洲一区二区| 麻豆一区二区三区在线观看| 国产一二三四五| 亚洲精品少妇一区二区| 艳母动漫在线观看| 国产美女在线一区| 免费看的黄色大片| wwwwww.色| 欧美视频亚洲图片| 日韩精品手机在线观看| 18禁裸男晨勃露j毛免费观看| 国产成人一二三区| 鲁一鲁一鲁一鲁一澡| 久久久久久久久久久免费视频| 欧美性大战久久久久xxx| 国产无套粉嫩白浆内谢的出处| 蜜桃免费在线视频| 日本一级淫片演员| 成年人午夜免费视频| 日本三区在线观看| 日本一二区免费| av动漫在线播放| 99视频精品免费| 欧美一级特黄aaaaaa在线看片| 精品人妻少妇一区二区| 污污视频网站免费观看| 青青草影院在线观看| 波多野结衣家庭教师在线| 宅男噜噜噜66国产免费观看| www.桃色.com| 超碰97人人射妻| 日韩精品一区二区三区电影| 日本免费不卡一区二区| 精品亚洲视频在线| 日本韩国欧美在线观看| 欧美成人乱码一二三四区免费| 韩日视频在线观看| 老司机午夜性大片| 国产男女在线观看| 水蜜桃在线免费观看| 国产91色在线观看| 国产中文字幕视频在线观看| 日本中文字幕精品—区二区| 免费不卡av在线| 亚洲第一综合网站| 性欧美1819| 国产网站免费在线观看| 黄色高清视频网站| 国产精品嫩草影院8vv8| 激情五月开心婷婷| 奇米精品一区二区三区| 男女激烈动态图| 久久精品一卡二卡| av亚洲天堂网| 欧美伦理片在线看| 成人黄色片视频| 日韩 欧美 高清| 各处沟厕大尺度偷拍女厕嘘嘘| 青青草原网站在线观看| 日本免费在线视频观看| 97超碰成人在线| 色91精品久久久久久久久| 五月婷婷丁香综合网| 亚洲国产高清av| 国产精品人人爽人人爽| 久久婷婷国产91天堂综合精品| 国产精品va无码一区二区| 国产黄色片免费在线观看| 国产二区视频在线| 凹凸国产熟女精品视频| 好吊妞无缓冲视频观看| 无码人妻h动漫| mm1313亚洲国产精品无码试看| 少妇人妻互换不带套| 性欧美1819| www亚洲国产| www.激情网| 国产深夜男女无套内射| 人妻无码视频一区二区三区| 丁香婷婷激情网| 岛国毛片在线播放| 中文字幕超清在线免费观看| 国产欧美自拍视频| 久在线观看视频| 日本特黄a级片| 精品免费久久久久久久| 337p粉嫩大胆噜噜噜鲁| av网站在线不卡| 天堂а√在线中文在线| 久久久性生活视频| 久久国产激情视频| 国产精品69久久久| 国产v亚洲v天堂无码久久久| 黄色高清视频网站| www黄色av| 97av中文字幕| 免费看涩涩视频| 日韩av中文字幕第一页| 免费成年人高清视频| 久久精品xxx| 中文字幕亚洲影院| 欧美日韩二三区| 欧美日韩在线免费观看视频| 亚洲熟女乱色一区二区三区| 中文字幕日韩综合| 日韩欧美精品在线观看视频| 免费一区二区三区在线观看| 日韩极品视频在线观看| 国产高清视频网站| 成人在线免费观看av| 免费在线精品视频| mm131国产精品| 久久久久久久久久久久久久国产| 激情五月五月婷婷| 欧美激情第3页| 人妻丰满熟妇av无码区app| 国产青草视频在线观看| 手机在线国产视频| 欧美精品性生活| 91黄色小网站| 波多野结衣家庭教师在线| 成年丰满熟妇午夜免费视频| 亚洲国产日韩欧美在线观看| 成人一区二区三| 国产av无码专区亚洲精品| 黄色一级视频在线播放| 激情成人开心网| 日韩 欧美 视频| 久久久久久免费看| 欧美精品卡一卡二| 青青青青草视频|