国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

這篇具有很好參考價(jià)值的文章主要介紹了Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、簡介
    今天是 Net 高級調(diào)試的第二篇文章,第一篇文章記錄了自己學(xué)習(xí) Net 高級調(diào)試的第一步,認(rèn)識一些調(diào)試工具,有了工具的倚仗,我們開始仗劍走天涯了,開始Net 高級調(diào)試正式的征程了。我先說一下,我的文章,【調(diào)試測試】這部分一般分為兩個(gè)部分,第一部分是要用到的所有測試代碼樣例,也為大家提供方便,我第一次做測試還是走了不少彎路的。第二部分,就是使用 Windbg 調(diào)試器調(diào)試代碼的部分,但是,需要說明一下,使用 Windbg還是有一些技巧的,或者說是方法的,如果大家不熟悉,建議提前熟悉一下,因?yàn)槲业臏y試過程,不會(huì)把所有的過程都照搬下來,會(huì)省略一下不太重要的步驟,但是,如果是第一次使用這個(gè)軟件的,調(diào)試的時(shí)候,得到的結(jié)果可能就和我的不一樣,這也是我的一步一步的、痛苦的經(jīng)驗(yàn)。
    如果在沒有說明的情況下,所有代碼的測試環(huán)境都是 Net Framewok 4.8,但是,有時(shí)候?yàn)榱瞬榭丛创a,可能需要使用 Net Core 的項(xiàng)目,我會(huì)在項(xiàng)目章節(jié)里進(jìn)行說明。好了,廢話不多說,開始我們今天的調(diào)試工作。
    調(diào)試環(huán)境我需要進(jìn)行說明,以防大家不清楚,具體情況我已經(jīng)羅列出來。
          操作系統(tǒng):Windows Professional 10
          調(diào)試工具:Windbg Preview(可以去Microsoft Store 去下載)
          開發(fā)工具:Visual Studio 2022
          Net 版本:Net Framework 4.8
          CoreCLR源碼:源碼下載
二、相關(guān)概念
    1、Net 框架
        Net 是一個(gè)虛擬的運(yùn)行時(shí)環(huán)境,包含了一個(gè)虛擬的執(zhí)行引擎(CLR)和一組相關(guān)的框架類庫,如圖:
        Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹
        1.1、宏觀概念
            
         ??   a)、ECMA
                C# 語言和公共語言基礎(chǔ)結(jié)構(gòu) (CLI) 規(guī)范通過 Ecma International? 進(jìn)行標(biāo)準(zhǔn)化。用通俗的話來說,ECMA是一個(gè)標(biāo)準(zhǔn),它就是一個(gè)CLR的開發(fā)規(guī)范,或者說是一個(gè)設(shè)計(jì)文檔。
                https://learn.microsoft.com/zh-cn/dotnet/fundamentals/standards

            b)、CLR
                公共語言運(yùn)行時(shí)。是我們 C#,VB.Net,F(xiàn)#的運(yùn)行時(shí)環(huán)境,當(dāng)然,這也是高級調(diào)試要關(guān)注的部分。
                CLR 處理內(nèi)存分配和管理。
                CLR 也是一種虛擬機(jī),不僅可執(zhí)行應(yīng)用,還可使用 JIT 編譯器快速生成和編譯代碼。
                最后,我們總結(jié)一下,CLR是針對 ECMA 標(biāo)準(zhǔn)的落地實(shí)現(xiàn)。

            c)、NET 框架
                NET框架有很多,比如:WPF,WinForm,WebForm,Mvc,WebAPI 等。

            d)、Net應(yīng)用程序
                NET 應(yīng)用程序,更多的指的是用戶編寫的應(yīng)用程序,比如:基于 Winform 的ERP,基于 MVC、API 實(shí)現(xiàn)的網(wǎng)站系統(tǒng)。

        1.2、Net程序的編譯過程
            Net程序的編譯一般分為兩個(gè)階段,第一個(gè)階段就是編譯器編譯,將C# 源碼編譯成為 IL 代碼,第二個(gè)階段就是 JIT 編譯,將 IL 代碼編譯成為可以直接運(yùn)行的機(jī)器代碼。
            a)、編譯器編譯
                將我們的C#、VB.Net、F#等源碼使用 Visual Studio,或者是 CSC 等類似的工具轉(zhuǎn)換為 IL 代碼。當(dāng)然 IL 代碼是不能直接運(yùn)行的。
                當(dāng)然,IL 代碼也是可以看到的,我們可以使用 ILSpy,或者DnSpy工具,加載相應(yīng)的程序集,就可以查看了,很簡單,就不細(xì)說了。

            b)、JIT編譯
                CLR 運(yùn)行時(shí)會(huì)將 IL 代碼轉(zhuǎn)換成 機(jī)器代碼。

            流程如下:【C# 源碼】======》【編譯器】=======》【Net 程序集(Exe或者Dll)】=====》【JIT即時(shí)編譯(CLR)】=====》【機(jī)器代碼】
                Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

    2、PE頭及Windows 加載器
        
        2.1、什么是PE文件
            PE文件的全稱是Portable Executable,意為可移植的可執(zhí)行的文件,常見的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微軟Windows操作系統(tǒng)上的程序文件,它的一個(gè)非常大的作用就是幫助 Windows 加載器 執(zhí)行程序的入口。
            對于 Net 的 PE 文件,有幾點(diǎn)需要注意:
            a)、AddressOfEntryPoint
               程序的入口點(diǎn)相對偏移地址,即(exe+AddressOfEntryPoint)。
              Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

            b)、DIRECTORY_ENTRY_COM_DESCRIPTOR
               Net 程序獨(dú)有的節(jié)點(diǎn)配置。
              Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

               ILSpy 查看 Example_2_1_1.exe 的元數(shù)據(jù)。
                Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

            c)、EntryPointToken
                這個(gè)標(biāo)簽的地址,就是我們程序 Program.Main 方法的入口點(diǎn)地址。
                IL 代碼里面也是有標(biāo)記的。
                Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹 
             
        2.2、小知識
             Windbg 有一個(gè)偽寄存器命令 ?? $exentry,可以直接告訴我們 exe 程序的入口點(diǎn)地址。

    3、應(yīng)用程序域        
        ?3.1、簡介
          
對于 Windows 上的應(yīng)用程序,大家都知道是按照【進(jìn)程】進(jìn)行隔離的Net 將這種進(jìn)程隔離縮小到了【應(yīng)用程序域】層,即一個(gè)進(jìn)程會(huì)有多個(gè)【應(yīng)用程序域】,然后將應(yīng)用程序部署在【應(yīng)用程序域】上。
          
在 CLR 上,應(yīng)用程序域分為三類,分別是:SystemDomain、SharedDomain、Domain1。當(dāng)然,這是說的在 Net Framework 的情況下,在 Net Core 框架下,只有兩個(gè)應(yīng)用程序域,分別是:SystemDomain、Domain1,去掉了 SharedDomain 這個(gè)應(yīng)用程序域。

      
3.2、應(yīng)用程序域
          ?? a)、SystemDomain
               ???
系統(tǒng)及作用域,用于創(chuàng)建其他作用域。
                
將 mscorlib.dll 加載到 SharedDomain 共享及應(yīng)用程序域。
                記錄字符串池中字符串常量。
                初始化特定異常(OutOfMemoryException、StackOverflowException)。

           b)、SharedDomain
                
加載 System 命名空間下的基本類型(String,Enum,ValueType)。

           c)、Domain1
                用戶的應(yīng)用程序都是在這個(gè)域中運(yùn)行。

三、調(diào)試測試
    這個(gè)章節(jié)里,很簡單,一共分為兩個(gè)部分,第一部分是要用到的測試代碼的樣例,第二部分,就是具體的測試操作過程,說明一下,假設(shè)大家對 Windbg 有些熟悉。

    1、測試代碼

        1.1、代碼樣例1           
 1 namespace Example_2_1_1
 2 {
 3     internal class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Console.WriteLine("Hello World");
 8             Console.ReadLine();
 9         }
10     }
11 }

    2、調(diào)試過程
        2.1、驗(yàn)證 CLR 和 JIT 的 存在。
            驗(yàn)證代碼:Example_2_1_1
            操作描述:編譯 Example_2_1_1 項(xiàng)目,打開 Windbg,通過【launch executable】加載我們的程序集。當(dāng)我們成功加載程序集,還必須通過【g】命令,或者【Go】按鈕執(zhí)行程序,這個(gè)時(shí)候,才能加載所有的東西。當(dāng)我們運(yùn)行完之后,就能看到運(yùn)行界面,就可以看到和 CLR 和 JIT 有關(guān)的東西。紅色字體表明加載了 CLR 和 JIT 兩個(gè)組件。
    
 1 0:000> g
 2 ModLoad: 74ec0000 74f39000   C:\Windows\SysWOW64\ADVAPI32.dll
 3 ModLoad: 771f0000 772af000   C:\Windows\SysWOW64\msvcrt.dll
 4 ModLoad: 757e0000 75855000   C:\Windows\SysWOW64\sechost.dll
 5 ModLoad: 753c0000 7547a000   C:\Windows\SysWOW64\RPCRT4.dll
 6 ModLoad: 711c0000 7124d000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll
 7 ModLoad: 771a0000 771e5000   C:\Windows\SysWOW64\SHLWAPI.dll
 8 ModLoad: 757d0000 757df000   C:\Windows\SysWOW64\kernel.appcore.dll
 9 ModLoad: 74eb0000 74eb8000   C:\Windows\SysWOW64\VERSION.dll
10 ModLoad: 70a10000 711c0000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll(CLR組件,加載的起始地址:70a1000011 ModLoad: 75870000 75a04000   C:\Windows\SysWOW64\USER32.dll
12 ModLoad: 77070000 77088000   C:\Windows\SysWOW64\win32u.dll
13 ModLoad: 70940000 709eb000   C:\Windows\SysWOW64\ucrtbase_clr0400.dll
14 ModLoad: 75fb0000 75fd3000   C:\Windows\SysWOW64\GDI32.dll
15 ModLoad: 709f0000 70a04000   C:\Windows\SysWOW64\VCRUNTIME140_CLR0400.dll
16 ModLoad: 750c0000 7519b000   C:\Windows\SysWOW64\gdi32full.dll
17 ModLoad: 76390000 7640b000   C:\Windows\SysWOW64\msvcp_win.dll
18 ModLoad: 75550000 75670000   C:\Windows\SysWOW64\ucrtbase.dll
19 ModLoad: 74fa0000 74fc5000   C:\Windows\SysWOW64\IMM32.DLL
20 ModLoad: 75ff0000 76270000   C:\Windows\SysWOW64\combase.dll
21 (7fc.b18): Unknown exception - code 04242420 (first chance)
22 ModLoad: 6f530000 7093e000   C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\218db16dceaef380c6daf35c6a48f313\mscorlib.ni.dll
23 ModLoad: 76490000 76573000   C:\Windows\SysWOW64\ole32.dll
24 ModLoad: 75ff0000 76270000   C:\Windows\SysWOW64\combase.dll
25 ModLoad: 752a0000 752fc000   C:\Windows\SysWOW64\bcryptPrimitives.dll
26 ModLoad: 6f4a0000 6f52a000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll(這個(gè)就是JIT編譯器組件,在進(jìn)程中的起始地址:6f4a000027 ModLoad: 751a0000 7523b000   C:\Windows\SysWOW64\OLEAUT32.dll

            
        2.2、證明 Windows 加載器如何加載一個(gè) Net 的程序集。
            驗(yàn)證代碼:Example_2_1_1
            PPEE是綠色軟件,不用安裝,直接下載就可以使用。打開 PPEE 軟件,打開 Example_2_1_1.exe,就可以看到 PE 文件。
            當(dāng)我們雙加一個(gè) Net 的Exe應(yīng)用程序的時(shí)候,操作系統(tǒng)會(huì)做很多工作,比如:在內(nèi)核態(tài)生成進(jìn)行的地址空間,地址空間生成成功后,然后在生成一個(gè)Process 的進(jìn)程,再給這個(gè)進(jìn)程生成一個(gè)主線程,在內(nèi)核態(tài)還要針對進(jìn)程生成 EProcess 的數(shù)據(jù)結(jié)構(gòu),針對線程生成一個(gè) ETHREAD 的數(shù)據(jù)結(jié)構(gòu)。當(dāng)所有的準(zhǔn)備工作都完成后,要開始執(zhí)行程序,從哪里開始執(zhí)行程序呢?我們來證明一下,或者說熟悉一下,這個(gè)過程就和 PE 頭文件有關(guān)了。


            a、Windows 加載器會(huì)讀取 PE 文件頭里面的數(shù)據(jù),來確定從哪里開始執(zhí)行,第一步,我們通過 PPEE 查看 Example_2_1_1.exe PE 文件,在 PE 頭里依次點(diǎn)擊【NT Header】-->【Optional Header】,在窗體的右側(cè)就可以看到,有一項(xiàng)【AddressOfEntryPoint】,它的值是:00002782,這個(gè)地址是相對地址,是相對程序進(jìn)程起始地址來說的。
              如圖:
              Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

              我們有了入口程序的相對起始地址,我們找一下應(yīng)用程序的進(jìn)程起始地址,二者相加,就是 Windows 加載器要執(zhí)行的地址。想要查看?Example_2_1_1.exe 進(jìn)程地址,需要借助 Windbg,紅色部分就是 Example_2_1_1.exe 進(jìn)程的起始地址。

              代碼如下:

1 Executable search path is: 
2 ModLoad: 00ca0000 00ca8000   Example_2_1_1.exe
3 ModLoad: 770d0000 77272000   ntdll.dll
4 ModLoad: 71050000 710a2000   C:\Windows\SysWOW64\MSCOREE.DLL
5 ModLoad: 74cc0000 74db0000   C:\Windows\SysWOW64\KERNEL32.dll
6 ModLoad: 767a0000 769b3000   C:\Windows\SysWOW64\KERNELBASE.dll

              二者相加就是WIndows 加載器的入口點(diǎn)地址,還不是我們的 Program.Main的地址,00ca0000(Example_2_1_1進(jìn)程起始地址),00002782 是 PE 頭告訴的入口點(diǎn)地址,我們通過 U 命令,可以查看匯編代碼。通過代碼我們可以看到,執(zhí)行了 jmp 指令,跳轉(zhuǎn)的地址是:402000h。
              

 1 0:000> u 00ca0000+00002782
 2 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x2782(PE 頭里的值)):
 3 00ca2782 ff2500204000    jmp(執(zhí)行跳轉(zhuǎn)指令)     dword ptr ds:[402000h]
 4 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x2788):
 5 00ca2788 0000            add     byte ptr [eax],al
 6 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x278a):
 7 00ca278a 0000            add     byte ptr [eax],al
 8 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x278c):
 9 00ca278c 0000            add     byte ptr [eax],al
10 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x278e):
11 00ca278e 0000            add     byte ptr [eax],al
12 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x2790):
13 00ca2790 0000            add     byte ptr [eax],al
14 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x2792):
15 00ca2792 0000            add     byte ptr [eax],al
16 Example_2_1_1!COM+_Entry_Point <PERF> (Example_2_1_1+0x2794):
17 00ca2794 0000            add     byte ptr [eax],al

                接下來,我們看看?402000h 這個(gè)地址有什么東西。

               ? ?? 再次執(zhí)行 Windbg,重新加載 Example_2_1_1.exe,通過【g】命令繼續(xù)運(yùn)行,暫停時(shí),【break】開始調(diào)試狀態(tài),必須切換到主線程,也就是 0號線程。
                

 1 //g 繼續(xù)運(yùn)行
 2 0:000> g
 3 ModLoad: 76c30000 76ca9000   C:\Windows\SysWOW64\ADVAPI32.dll
 4 ModLoad: 765b0000 7666f000   C:\Windows\SysWOW64\msvcrt.dll
 5 ModLoad: 76e30000 76ea5000   C:\Windows\SysWOW64\sechost.dll
 6 ModLoad: 75c40000 75cfa000   C:\Windows\SysWOW64\RPCRT4.dll
 7 ModLoad: 70fc0000 7104d000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll
 8 ModLoad: 75d20000 75d65000   C:\Windows\SysWOW64\SHLWAPI.dll
 9 ModLoad: 75530000 7553f000   C:\Windows\SysWOW64\kernel.appcore.dll
10 ModLoad: 74cb0000 74cb8000   C:\Windows\SysWOW64\VERSION.dll
11 ModLoad: 70810000 70fc0000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
12 ModLoad: 76410000 765a4000   C:\Windows\SysWOW64\USER32.dll
13 ModLoad: 707f0000 70804000   C:\Windows\SysWOW64\VCRUNTIME140_CLR0400.dll
14 ModLoad: 76180000 76198000   C:\Windows\SysWOW64\win32u.dll
15 ModLoad: 70740000 707eb000   C:\Windows\SysWOW64\ucrtbase_clr0400.dll
16 ModLoad: 75b80000 75ba3000   C:\Windows\SysWOW64\GDI32.dll
17 ModLoad: 76670000 7674b000   C:\Windows\SysWOW64\gdi32full.dll
18 ModLoad: 76b30000 76bab000   C:\Windows\SysWOW64\msvcp_win.dll
19 ModLoad: 75550000 75670000   C:\Windows\SysWOW64\ucrtbase.dll
20 ModLoad: 754f0000 75515000   C:\Windows\SysWOW64\IMM32.DLL
21 Breakpoints 3 and 0 match
22 ModLoad: 75f00000 76180000   C:\Windows\SysWOW64\combase.dll
23 (3624.36d8): Unknown exception - code 04242420 (first chance)
24 ModLoad: 6f330000 7073e000   C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\218db16dceaef380c6daf35c6a48f313\mscorlib.ni.dll
25 ModLoad: 76cb0000 76d93000   C:\Windows\SysWOW64\ole32.dll
26 ModLoad: 75f00000 76180000   C:\Windows\SysWOW64\combase.dll
27 ModLoad: 76fa0000 76ffc000   C:\Windows\SysWOW64\bcryptPrimitives.dll
28 ModLoad: 6f2a0000 6f32a000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
29 ModLoad: 76eb0000 76f4b000   C:\Windows\SysWOW64\OLEAUT32.dll
30 (3624.20f0): Break instruction exception - code 80000003 (first chance)
31 eax=0106b000 ebx=00000000 ecx=7717cee0 edx=7717cee0 esi=7717cee0 edi=7717cee0
32 eip=77143410 esp=05a2fa9c ebp=05a2fac8 iopl=0         nv up ei pl zr na pe nc
33 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
34 ntdll!DbgBreakPoint:
35 77143410 cc              int     3
36 
37 //切換到主線程
38 0:006> ~0s
39 eax=00000000 ebx=0000009c ecx=00000000 edx=00000000 esi=0138ee3c edi=00000000
40 eip=771410fc esp=0138ed24 ebp=0138ed84 iopl=0         nv up ei pl nz na pe nc
41 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
42 ntdll!NtReadFile+0xc:
43 771410fc c22400          ret     24h

                我們通過【k】命令,查看顯示調(diào)用棧

 1 0:000> k
 2  # ChildEBP RetAddr      
 3 00 0138ed84 768af25c     ntdll!NtReadFile+0xc
 4 01 0138ed84 6f7e9b71     KERNELBASE!ReadFile+0xec
 5 02 0138edf4 6ff1b275     mscorlib_ni+0x4b9b71
 6 03 0138ee20 6ff1b17b     mscorlib_ni!System.IO.__ConsoleStream.ReadFileNative+0x89 [f:\dd\ndp\clr\src\BCL\system\io\__consolestream.cs @ 205] 
 7 04 0138ee4c 6f7ce6a3     mscorlib_ni!System.IO.__ConsoleStream.Read+0x9f [f:\dd\ndp\clr\src\BCL\system\io\__consolestream.cs @ 134] 
 8 05 0138ee64 6f7ceb5b     mscorlib_ni!System.IO.StreamReader.ReadBuffer+0x33 [f:\dd\ndp\clr\src\BCL\system\io\streamreader.cs @ 595] 
 9 06 0138ee80 70063786     mscorlib_ni!System.IO.StreamReader.ReadLine+0xe3 [f:\dd\ndp\clr\src\BCL\system\io\streamreader.cs @ 748] 
10 07 0138ee90 6fec1845     mscorlib_ni!System.IO.TextReader.SyncTextReader.ReadLine+0x1a [f:\dd\ndp\clr\src\BCL\system\io\textreader.cs @ 363] 
11 08 0138ee98 03250876     mscorlib_ni!System.Console.ReadLine+0x15 [f:\dd\ndp\clr\src\BCL\system\console.cs @ 1984] 
12 WARNING: Frame IP not in any known module. Following frames may be wrong.
13 09 0138eea8 7081f036     0x3250876
14 0a 0138eeb4 708222da     clr!CallDescrWorkerInternal+0x34
15 0b 0138ef08 7082859b     clr!CallDescrWorkerWithHandler+0x6b
16 0c 0138ef7c 709cb11b     clr!MethodDescCallSite::CallTargetWorker+0x16a
17 0d 0138f0a0 709cb7fa     clr!RunMain+0x1b3
18 0e 0138f30c 709cb727     clr!Assembly::ExecuteMainMethod+0xf7
19 0f 0138f7f0 709cb8a8     clr!SystemDomain::ExecuteMainMethod+0x5ef
20 10 0138f848 709cb9ce     clr!ExecuteEXE+0x4c
21 11 0138f888 709c7305     clr!_CorExeMainInternal+0xdc
22 12 0138f8c4 70fcfa84     clr!_CorExeMain+0x4d
23 13 0138f8fc 7105e81e     mscoreei!_CorExeMain+0xd6
24 14 0138f90c 71064338     MSCOREE!ShellShim__CorExeMain+0x9e
25 15 0138f924 74cdf989     MSCOREE!_CorExeMain_Exported+0x8
26 16 0138f924 77137084     KERNEL32!BaseThreadInitThunk+0x19
27 17 0138f980 77137054     ntdll!__RtlUserThreadStart+0x2f
28 18 0138f990 00000000     ntdll!_RtlUserThreadStart+0x1b

              以上就是線程的調(diào)用棧,我們查找一下 _CorExeMain,這個(gè)方法,可以在 PPEE 軟件里,在查看 Example_2_1_1.exe 的PE 頭文件 DIRECTORY_ENTRY_IAT 里,效果如圖:
                  Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

                 接著上面的說,我們在【k】命令的結(jié)果中查找?_CorExeMain 方法。這里的執(zhí)行結(jié)果是一部分,紅色部分是重點(diǎn),MSCOREE 就是 mscoree.dll。

 1 0a 0138eeb4 708222da     clr!CallDescrWorkerInternal+0x34
 2 0b 0138ef08 7082859b     clr!CallDescrWorkerWithHandler+0x6b
 3 0c 0138ef7c 709cb11b     clr!MethodDescCallSite::CallTargetWorker+0x16a
 4 0d 0138f0a0 709cb7fa     clr!RunMain+0x1b3(運(yùn)行 Main 方法)
 5 0e 0138f30c 709cb727     clr!Assembly::ExecuteMainMethod+0xf7(加載必須的 dll 程序集)
 6 0f 0138f7f0 709cb8a8     clr!SystemDomain::ExecuteMainMethod+0x5ef(初始化系統(tǒng)程序域)
 7 10 0138f848 709cb9ce     clr!ExecuteEXE+0x4c(開始執(zhí)行 exe)
 8 11 0138f888 709c7305     clr!_CorExeMainInternal+0xdc
 9 12 0138f8c4 70fcfa84     clr!_CorExeMain+0x4d(從這里開始執(zhí)行入口地址的方法)
10 13 0138f8fc 7105e81e     mscoreei!_CorExeMain+0xd6(加載 CLR)
11 14 0138f90c 71064338     MSCOREE!ShellShim__CorExeMain+0x9e
12 15 0138f924 74cdf989     MSCOREE!_CorExeMain_Exported+0x8(這里就是在 PPEE 看到的入口地址 AddressOfEntryPoint:00002782)
13 16 0138f924 77137084     KERNEL32!BaseThreadInitThunk+0x19
14 17 0138f980 77137054     ntdll!__RtlUserThreadStart+0x2f
15 18 0138f990 00000000     ntdll!_RtlUserThreadStart+0x1b(ntdll是windows 32位的API)

                第12行代碼就是?mscoree.dll 執(zhí)行?_CorExeMain 方法,初始化環(huán)境,10 行代碼加載 CLR,CLR 從第9 行執(zhí)行入口函數(shù),知道最后進(jìn)入我們的托管層,我們可以使用 !clrstack 命令查看托管棧。
                

 1 0:000> !clrstack
 2 OS Thread Id: 0x36d8 (0)
 3 Child SP       IP Call Site
 4 0138eda4 771410fc [InlinedCallFrame: 0138eda4] 
 5 0138eda0 6f7e9b71 DomainNeutralILStubClass.IL_STUB_PInvoke(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
 6 0138eda4 6ff1b275 [InlinedCallFrame: 0138eda4] Microsoft.Win32.Win32Native.ReadFile(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
 7 0138ee08 6ff1b275 System.IO.__ConsoleStream.ReadFileNative(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte[], Int32, Int32, Boolean, Boolean, Int32 ByRef) [f:\dd\ndp\clr\src\BCL\system\io\__consolestream.cs @ 205]
 8 0138ee3c 6ff1b17b System.IO.__ConsoleStream.Read(Byte[], Int32, Int32) [f:\dd\ndp\clr\src\BCL\system\io\__consolestream.cs @ 134]
 9 0138ee5c 6f7ce6a3 System.IO.StreamReader.ReadBuffer() [f:\dd\ndp\clr\src\BCL\system\io\streamreader.cs @ 595]
10 0138ee6c 6f7ceb5b System.IO.StreamReader.ReadLine() [f:\dd\ndp\clr\src\BCL\system\io\streamreader.cs @ 748]
11 0138ee88 70063786 System.IO.TextReader+SyncTextReader.ReadLine() [f:\dd\ndp\clr\src\BCL\system\io\textreader.cs @ 363]
12 0138ee98 6fec1845 System.Console.ReadLine() [f:\dd\ndp\clr\src\BCL\system\console.cs @ 1984]
13 0138eea0 03250876 Example_2_1_1.Program.Main(System.String[]) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_2_1_1\Program.cs @ 10]
14 0138f020 7081f036 [GCFrame: 0138f020] 

                系統(tǒng)進(jìn)入了托管棧,那它怎么知道要執(zhí)行程序的 Main 方法呢?其實(shí),在 PE 頭文件里也有說明,在【DIRECTORY_ENTRY_COM_DESCRIPTOR】配置項(xiàng)里,我們點(diǎn)擊該節(jié)點(diǎn),在右側(cè)顯示詳情,請注意【EntryPointToken】,值是:06000001,這個(gè)標(biāo)記就是 Main方法。

                 效果如圖:
                  Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

                  我們?yōu)榱俗C明?06000001就是 Main 方法,我們使用 ILSpy 或者 DnSpy 查看程序集的元數(shù)據(jù),效果如圖:
                  Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹

                  其實(shí),我們在 Main 方法的 IL 代碼里也有標(biāo)記,紅色部分就是,注意。

 1 .method private hidebysig static 
 2     void Main (
 3         string[] args
 4     ) cil managed 
 5 {
 6     // Method begins at RVA 0x2050
 7     // Header size: 1
 8     // Code size: 19 (0x13)
 9     .maxstack 8
10     .entrypoint
11 
12     IL_0000: nop
13     IL_0001: ldstr "Hello World"
14     IL_0006: call void [mscorlib]System.Console::WriteLine(string)
15     IL_000b: nop
16     IL_000c: call string [mscorlib]System.Console::ReadLine()
17     IL_0011: pop
18     IL_0012: ret
19 } // end of method Program::Main


        2.3、查看應(yīng)用程序域
            驗(yàn)證代碼:Example_2_1_1
            EECLASS 存放在 LowFrequencyHeap ,MethodTable 存放在?HighFrequencyHeap

 1 0:000> !dumpdomain(執(zhí)行的命令)
 2 --------------------------------------
 3 System Domain:      7115caf8(系統(tǒng)級程序域)
 4 LowFrequencyHeap:   7115ce1c(低頻堆)
 5 HighFrequencyHeap:  7115ce68(高頻堆)
 6 StubHeap:           7115ceb4(樁堆)
 7 Stage:              OPEN
 8 Name:               None
 9 --------------------------------------
10 Shared Domain:      7115c7a8(共享程序域)
11 LowFrequencyHeap:   7115ce1c(低頻堆)
12 HighFrequencyHeap:  7115ce68(高頻堆)
13 StubHeap:           7115ceb4(樁堆)
14 Stage:              OPEN
15 Name:               None
16 Assembly:           00b4f3d8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
17 ClassLoader:        00b4de08
18   Module Name
19 6f531000    C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
20 
21 --------------------------------------
22 Domain 1:           00b01518(應(yīng)用程序域)
23 LowFrequencyHeap:   00b01984(低頻堆)
24 HighFrequencyHeap:  00b019d0(高頻堆)
25 StubHeap:           00b01a1c(樁堆)
26 Stage:              OPEN
27 SecurityDescriptor: 00b02a58
28 Name:               Example_2_1_1.exe
29 Assembly:           00b4f3d8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
30 ClassLoader:        00b4de08
31 SecurityDescriptor: 00b4f340
32   Module Name
33 6f531000    C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
34 
35 Assembly:           00b5b4d8 [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_2_1_1\bin\Debug\Example_2_1_1.exe]
36 ClassLoader:        00b5afa8
37 SecurityDescriptor: 00b5aea0
38   Module Name
39 00d44044    E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_2_1_1\bin\Debug\Example_2_1_1.exe

         2.4、通過命令 ? $exentry? 查看入口點(diǎn)。
0:000> ?  $exentry
Evaluate expression: 5711746 = 00572782

            Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹文章來源地址http://www.zghlxwxcb.cn/news/detail-711338.html


三、總結(jié)
    今天的內(nèi)容真不少,完全記錄下來還是挺費(fèi)勁的,俗話說,沒有苦哪里來的甜呢,一天的辛苦還是值得的,自己的收獲也不少。學(xué)習(xí)如逆水行舟,不進(jìn)則退,但是也也有另外一句話,學(xué)的越多,好像懂得越少。不管如何,不忘初心,繼續(xù)努力,老天不會(huì)辜負(fù)努力的人。

到了這里,關(guān)于Net 高級調(diào)試之二:CLR和Windows加載器及應(yīng)用程序域介紹的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Net 高級調(diào)試之一:開始認(rèn)識一些調(diào)試工具

    Net 高級調(diào)試之一:開始認(rèn)識一些調(diào)試工具

    一、簡介 從今天開始一個(gè)長系列,Net 高級調(diào)試的相關(guān)文章,我自從學(xué)習(xí)了之后,以前很多模糊的地方現(xiàn)在很清楚了,原來自己的功力還是不夠,所以有很多不明白,通過學(xué)習(xí) Net 高級調(diào)試,眼前豁然開朗,茅塞頓開。其實(shí),剛開始要學(xué)習(xí)《Net 高級調(diào)試》,還是很是很困難的

    2024年02月08日
    瀏覽(24)
  • Net 高級調(diào)試之十:輕量級代碼生成的調(diào)試

    Net 高級調(diào)試之十:輕量級代碼生成的調(diào)試

    一、簡介 今天是《Net 高級調(diào)試》的第十篇文章。說起來,高級調(diào)試,調(diào)試的內(nèi)容還是挺多的,技巧也不少,但是,要想做一個(gè)合格的高級調(diào)試人員,還需要掌握如何調(diào)試動(dòng)態(tài)生成的IL代碼。今天要探討的高級調(diào)試的技巧是如何調(diào)試通過 Emit 動(dòng)態(tài)生成 IL 代碼??赡苡腥藭?huì)問,

    2024年02月05日
    瀏覽(95)
  • 聊一聊 .NET高級調(diào)試 內(nèi)核模式堆泄露

    聊一聊 .NET高級調(diào)試 內(nèi)核模式堆泄露

    前幾天有位朋友找到我,說他的機(jī)器內(nèi)存在不斷的上漲,但在任務(wù)管理器中查不出是哪個(gè)進(jìn)程吃的內(nèi)存,特別奇怪,截圖如下: 在我的分析旅程中都是用戶態(tài)模式的內(nèi)存泄漏,像上圖中的異常征兆已經(jīng)明確告訴你了,不是用戶態(tài)程序吃的內(nèi)存,那就是內(nèi)核態(tài)程序吃的,比如:

    2024年02月04日
    瀏覽(20)
  • Net 高級調(diào)試之九:SOSEX 擴(kuò)展命令介紹

    Net 高級調(diào)試之九:SOSEX 擴(kuò)展命令介紹

    一、介紹 今天是《Net 高級調(diào)試》的第九篇文章。這篇文章設(shè)計(jì)的內(nèi)容挺多的,比如:擴(kuò)展的斷點(diǎn)支持,如何查找元數(shù)據(jù),棧回溯,對象檢查,死鎖檢測等等,內(nèi)容挺多的。功能特別強(qiáng)大,使用特別方便, 但是需要說明一點(diǎn),這些功能不是 SOS 的功能,是 SOSEX 的擴(kuò)展功能,但

    2024年02月05日
    瀏覽(16)
  • 聊一聊 .NET高級調(diào)試 中的一些內(nèi)存術(shù)語

    聊一聊 .NET高級調(diào)試 中的一些內(nèi)存術(shù)語

    在高級調(diào)試的旅程中,經(jīng)常會(huì)有一些朋友問我什么是 工作集(內(nèi)存) ,什么是 提交大小 ,什么是 Virtual Size , 什么是 Working Set 。。。截圖如下: 既然有很多朋友問,這些用口頭也不怎么好描述,剛好上午有時(shí)間就系統(tǒng)的聊一下吧。 可能有些朋友知道,內(nèi)存中的虛擬地址被劃分

    2024年02月05日
    瀏覽(20)
  • Net 高級調(diào)試之七:線程操作相關(guān)命令介紹

    Net 高級調(diào)試之七:線程操作相關(guān)命令介紹

    一、簡介 今天是《Net 高級調(diào)試》的第七篇文章。上一篇文章我們說了值類型,引用類型,數(shù)組等的內(nèi)存表現(xiàn)形式。有了這個(gè)基礎(chǔ),我們可以更好的了解我們的程序在運(yùn)行時(shí)的狀態(tài),內(nèi)存里有什么東西,它們的結(jié)構(gòu)組成是什么樣子的,對我們調(diào)試程序是更有幫助的。今天,我

    2024年02月05日
    瀏覽(17)
  • Net 高級調(diào)試之八:代碼審查及雜項(xiàng)命令

    Net 高級調(diào)試之八:代碼審查及雜項(xiàng)命令

    一、簡介 今天是《Net 高級調(diào)試》的第八篇文章。這篇文章設(shè)計(jì)的內(nèi)容挺多的,比如:如何查看方法的匯編代碼,如何獲取方法的描述符,對象同步塊的轉(zhuǎn)儲(chǔ),對象方法表的轉(zhuǎn)儲(chǔ),托管堆和垃圾回收器信息的轉(zhuǎn)儲(chǔ),CLR 的版本,GC 模式,等等,內(nèi)容挺多的。內(nèi)容雖然挺多,但是

    2024年02月05日
    瀏覽(33)
  • 聊一聊 .NET高級調(diào)試 中必知的符號表

    聊一聊 .NET高級調(diào)試 中必知的符號表

    在高級調(diào)試的旅行中,發(fā)現(xiàn)有不少人對符號表不是很清楚,其實(shí)簡而言之符號表中記錄著一些程序的生物特征,比如哪個(gè)地址是函數(shù)(簽名信息),哪個(gè)地址是全局變量,靜態(tài)變量,行號是多少,數(shù)據(jù)類型是什么 等等,目的就是輔助我們可視化的調(diào)試,如果沒有這些輔助我們看

    2024年02月05日
    瀏覽(23)
  • Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)

    Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)

    一、簡介 今天是《Net 高級調(diào)試》的第五篇文章。今天這篇文章開始介紹如何在托管方法和非托管方法設(shè)置斷點(diǎn),我們要想調(diào)試程序,必須掌握調(diào)試的一些命令,動(dòng)態(tài)調(diào)試的命令,我們在上一篇文章已經(jīng)講過了。光有命令也是不行的,要讓這些調(diào)試命令有用,必須可以在方法

    2024年02月06日
    瀏覽(22)
  • Net 高級調(diào)試之十一:托管堆布局架構(gòu)和對象分配機(jī)制

    Net 高級調(diào)試之十一:托管堆布局架構(gòu)和對象分配機(jī)制

    一、簡介 今天是《Net 高級調(diào)試》的第十一篇文章,這篇文章來的有點(diǎn)晚,因?yàn)?,最近比較忙,就沒時(shí)間寫文章了?,F(xiàn)在終于有點(diǎn)時(shí)間,繼續(xù)開始我們這個(gè)系列。這篇文章我們主要介紹托管堆的架構(gòu),對象的分配機(jī)制,我們?nèi)绾尾檎以谕泄芏焉系膶ο螅覍W(xué)完這章,很多以前

    2024年02月05日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包