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

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

這篇具有很好參考價值的文章主要介紹了Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

一、簡介
    今天是《Net 高級調(diào)試》的第五篇文章。今天這篇文章開始介紹如何在托管方法和非托管方法設(shè)置斷點(diǎn),我們要想調(diào)試程序,必須掌握調(diào)試的一些命令,動態(tài)調(diào)試的命令,我們在上一篇文章已經(jīng)講過了。光有命令也是不行的,要讓這些調(diào)試命令有用,必須可以在方法上設(shè)置斷點(diǎn),然后,再使用調(diào)試命令,才能完成我們的調(diào)試任務(wù)。當(dāng)然了,第一次看視頻或者看書,是很迷糊的,不知道如何操作,還是那句老話,一遍不行,那就再來一遍,還不行,那就再來一遍,俗話說的好,書讀千遍,其意自現(xiàn),我這是第三遍。
     如果在沒有說明的情況下,所有代碼的測試環(huán)境都是 Net Framewok 4.8,但是,有時候?yàn)榱瞬榭丛创a,可能需要使用 Net Core 的項(xiàng)目,我會在項(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源碼:源碼下載

二、基礎(chǔ)知識
    
    1、非托管函數(shù)下斷點(diǎn)
        其實(shí)對非托管函數(shù)下斷點(diǎn)是十分方便的,因?yàn)镃/C++函數(shù)在編譯之后就成了【機(jī)器代碼】了,函數(shù)名就進(jìn)入了【符號表】,比如我們可以非常方便的 notepad 的 SaveFile 函數(shù)下斷點(diǎn)。

        操作步驟如下:
            a、打開 notepad 。
            b、使用? x notepad!SaveFile 下斷點(diǎn)。
            c、在 notepad 上保存一下文件,就會觸發(fā)斷點(diǎn)。
        
    2、托管函數(shù)下斷點(diǎn)
        
        2.1、簡介
            托管函數(shù)下斷點(diǎn)是很難的,因?yàn)槟阋聰帱c(diǎn)的方法的機(jī)器碼在內(nèi)存中可能還沒有生成,也就是 JIT 從來就沒有對該方法進(jìn)行編譯過,所以在還沒有生成的代碼上下斷點(diǎn)就比較麻煩。雖然比較麻煩,并不代表不能實(shí)現(xiàn),我們還是有三種方法可以對托管函數(shù)下斷點(diǎn)的。

        2.2、托管函數(shù)下斷點(diǎn)的三種方式

            1)、在編譯后的函數(shù)上下斷點(diǎn)
                這是最簡單的一種方式,既然方法已經(jīng)編譯完成,肯定就已經(jīng)生成了機(jī)器代碼,那在編譯后的函數(shù)上下斷點(diǎn)就容易很多了,和非托管的是一樣的。

            2)、在未編譯的函數(shù)上下斷點(diǎn)
                a、使用 !bpmd assembly.exe(模塊包含后綴名) namespace.ClassName.MethodName
                b、使用 sosex 擴(kuò)展的 mbm 下斷點(diǎn)(只能在 Net framework 下使用,Net Core 是不支持的)。

            3)、對泛型方法下斷點(diǎn)
                如果我們想對泛型類型的方法下斷點(diǎn),最首要的任務(wù)就是找到泛型類型的名稱和方法的名稱,找到之后,我們就可以下斷點(diǎn)了。找泛型類型的名稱和方法的名稱有兩種辦法,第一種是通過命令,第二種是我們可以使用 ILSpy 找到。


三、調(diào)試過程
    廢話不多說,這一節(jié)是具體的調(diào)試操作的過程,又可以說是眼見為實(shí)的過程,在開始之前,我還是要啰嗦兩句,這一節(jié)分為兩個部分,第一部分是測試的源碼部分,沒有代碼,當(dāng)然就談不上測試了,調(diào)試必須有載體。第二部分就是根據(jù)具體的代碼來證實(shí)我們學(xué)到的知識,是具體的眼見為實(shí)。

    1、測試源碼        
        1.1、Example_5_1_1
Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
 1 namespace Example_5_1_1
 2 {
 3     internal class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             var sum = Sum(10, 20);
 8 
 9             Debugger.Break();
10 
11             sum = Sum(100, 200);
12 
13             Console.WriteLine($"sum={sum}");
14         }
15 
16         private static int Sum(int a, int b)
17         {
18             var sum = a + b;
19 
20             return sum;
21         }
22     }
23 }
View Code
     
        1.2、Example_5_1_2
Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
 1 namespace Example_5_1_2
 2 {
 3     internal class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Console.WriteLine("請查看:未編譯形態(tài)的 Sum 方法");
 8             Debugger.Break();
 9 
10             var sum = Sum(10,20);
11             Console.WriteLine("請查看:已經(jīng)編譯形態(tài)的 Sum 方法");
12             Debugger.Break();
13 
14             sum = Sum(100, 200);
15 
16             Console.WriteLine($"sum={sum}");
17         }
18 
19         private static int Sum(int a, int b)
20         {
21             var sum = a + b;
22 
23             return sum;
24         }
25     }
26 }
View Code

        1.3、Example_5_1_3
Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
 1 namespace Example_5_1_3
 2 {
 3     internal class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Debugger.Break();
 8 
 9             var mylist = new MyList<int>();
10 
11             mylist.Add(10);
12 
13             Console.ReadLine();
14         }
15     }
16 
17     public class MyList<T>
18     {
19         public T[] arr = new T[10];
20 
21         public void Add(T t)
22         {
23             arr[0] = t;
24         }
25     }
26 }
View Code


    2、眼見為實(shí)
        
        2.1、在非托管函數(shù) Notepad 的 SaveFile 方法上下斷點(diǎn)。
            測試程序:Notepad
            操作流程:我們先要打開 notepad,然后再打開 windbg,點(diǎn)擊【文件】菜單,然后通過【attach to process】附加進(jìn)程,最后點(diǎn)擊【Attach】按鈕完成附加進(jìn)程的操作?,F(xiàn)在 notepad 是不能操作的,因?yàn)閿帱c(diǎn)斷住了,所以我們執(zhí)行【g】命令,運(yùn)行一下。然后我們點(diǎn)擊工具欄【break】按鈕,中斷,然后就可以調(diào)試了。
            我們使用【x】命令查找一下 notepad 的 SaveFile 方法。
1 0:002> x notepad!*SaveFile*
2 00007ff6`e46be780 notepad!SaveFile (bool __cdecl SaveFile(struct HWND__ *,class wil::unique_any_t<class wil::details::unique_storage<struct wil::details::resource_policy<unsigned short *,void (__cdecl*)(void *),&void __cdecl CoTaskMemFree(void *),struct wistd::integral_constant<unsigned __int64,0>,unsigned short *,unsigned short *,0,std::nullptr_t> > > &,bool,unsigned short const *))
3 00007ff6`e46d508c notepad!_imp_load_GetSaveFileNameW (__imp_load_GetSaveFileNameW)
4 00007ff6`e46e50b0 notepad!_imp_GetSaveFileNameW = <no type information>

            使用【bp】命令對?notepad!SaveFile 函數(shù)下斷點(diǎn)。下斷點(diǎn)后,繼續(xù)運(yùn)行,使用【g】命令。

1 0:002> bp notepad!SaveFile
2 0:002> g

            此時,我們可以操作 notepad,隨便輸入一些內(nèi)容,然后點(diǎn)擊【保存】,就可以被斷點(diǎn)斷住。

1 .......
2 Breakpoint 0 hit
3 notepad!SaveFile:
4 00007ff6`e46be780 488bc4          mov     rax,rsp

            我們可以使用【k】命令顯示調(diào)用棧也能說明問題。

 1 0:000> k
 2  # Child-SP          RetAddr               Call Site
 3 00 00000002`1a1dec58 00007ff6`e46b9336     notepad!SaveFile
 4 01 00000002`1a1dec60 00007ff6`e46badf4     notepad!NPCommand+0x2d2
 5 02 00000002`1a1df240 00007ff8`23e0e338     notepad!NPWndProc+0x844
 6 03 00000002`1a1df570 00007ff8`23e0dd79     USER32!UserCallWinProcCheckWow+0x2f8
 7 04 00000002`1a1df700 00007ff6`e46bb30c     USER32!DispatchMessageWorker+0x249
 8 05 00000002`1a1df780 00007ff6`e46d3b66     notepad!wWinMain+0x29c
 9 06 00000002`1a1df830 00007ff8`23b86fd4     notepad!__scrt_common_main_seh+0x106
10 07 00000002`1a1df870 00007ff8`25bbcec1     KERNEL32!BaseThreadInitThunk+0x14
11 08 00000002`1a1df8a0 00000000`00000000     ntdll!RtlUserThreadStart+0x21

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



        2.2、在已經(jīng)編譯的托管函數(shù)上下斷點(diǎn)。
            測試程序:Example_5_1_1
            我們使用 Windbg Preview 調(diào)試器,通過【launch executable】菜單加載【Example_5_1_1.exe】項(xiàng)目,通過【g】命令,運(yùn)行程序,調(diào)試器運(yùn)行代【Debugger.Break()】次會暫停執(zhí)行。當(dāng)然,我們可以使用【cls】命令清理一下調(diào)試器顯示的過多信息,自己來決定,我是會清理的。我們將在【sum = Sum(100, 200);】這行下斷點(diǎn)。
            當(dāng)調(diào)試器暫停的時候,說明有一部分代碼已經(jīng)執(zhí)行了?!緑ar sum = Sum(10, 20);】就是這行代碼已經(jīng)被執(zhí)行,也可以說是被 JIT 編譯了。我們?nèi)绾尾榭?Sum 方法被編譯的代碼呢?可以使用【!name2ee】命令。
1 0:000> !name2ee Example_5_1_1!Example_5_1_1.Program.Sum
2 Module:      00fc4044
3 Assembly:    Example_5_1_1.exe
4 Token:       06000002
5 MethodDesc:  00fc4d64
6 Name:        Example_5_1_1.Program.Sum(Int32, Int32)
7 JITTED Code Address: 01010908

            紅色標(biāo)注表示代碼已經(jīng)編譯,我們也可以使用【!u】命令查看這個代碼的匯編代碼,匯編代碼很多,所以折疊。

Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
 1 0:000> !u 01010908
 2 Normal JIT generated code
 3 Example_5_1_1.Program.Sum(Int32, Int32)
 4 Begin 01010908, size 3e
 5 
 6 E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_5_1_1\Program.cs @ 20:
 7 >>> 01010908 55              push    ebp
 8 01010909 8bec            mov     ebp,esp
 9 0101090b 83ec10          sub     esp,10h
10 0101090e 894dfc          mov     dword ptr [ebp-4],ecx
11 01010911 8955f8          mov     dword ptr [ebp-8],edx
12 01010914 833df042fc0000  cmp     dword ptr ds:[0FC42F0h],0
13 0101091b 7405            je      01010922
14 0101091d e85ef40670      call    clr!JIT_DbgIsJustMyCode (7107fd80)
15 01010922 33d2            xor     edx,edx
16 01010924 8955f0          mov     dword ptr [ebp-10h],edx
17 01010927 33d2            xor     edx,edx
18 01010929 8955f4          mov     dword ptr [ebp-0Ch],edx
19 0101092c 90              nop
20 
21 E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_5_1_1\Program.cs @ 21:
22 0101092d 8b45fc          mov     eax,dword ptr [ebp-4]
23 01010930 0345f8          add     eax,dword ptr [ebp-8]
24 01010933 8945f4          mov     dword ptr [ebp-0Ch],eax
25 
26 E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_5_1_1\Program.cs @ 23:
27 01010936 8b45f4          mov     eax,dword ptr [ebp-0Ch]
28 01010939 8945f0          mov     dword ptr [ebp-10h],eax
29 0101093c 90              nop
30 0101093d eb00            jmp     0101093f
31 
32 E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_5_1_1\Program.cs @ 24:
33 0101093f 8b45f0          mov     eax,dword ptr [ebp-10h]
34 01010942 8be5            mov     esp,ebp
35 01010944 5d              pop     ebp
36 01010945 c3              ret
View Code

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

            我們使用【bp】命令在地址【01010908】地址處下斷點(diǎn),【g】繼續(xù)運(yùn)行,就會在 Sum 方法的第一行斷住。

0:000> bp 01010908

            繼續(xù)運(yùn)行后,            

1 0:000> g
2 Breakpoint 0 hit
3 eax=00000000 ebx=00aff108 ecx=00000064 edx=000000c8 esi=02b524bc edi=00aff058
4 eip=01010908 esp=00aff03c ebp=00aff068 iopl=0         nv up ei pl zr na pe nc
5 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
6 Example_5_1_1!COM+_Entry_Point <PERF> (Example_5_1_1+0x920908):
7 01010908 55              push    ebp

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


            
        2.3、在未編譯的托管函數(shù)上下斷點(diǎn)。
            測試程序:Example_5_1_2
            我們使用 Windbg Preview 調(diào)試器,通過【launch executable】菜單加載【Example_5_1_2.exe】項(xiàng)目,通過【g】命令,運(yùn)行程序,調(diào)試器運(yùn)行代【Debugger.Break()】次會暫停執(zhí)行,此行代碼在12。當(dāng)然,我們可以使用【cls】命令清理一下調(diào)試器顯示的過多信息,自己來決定,我是會清理的。這次我們的任務(wù)依然是在 Sum 方法上下斷點(diǎn)。
            先來一個截圖吧,效果更明顯:
            Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
              我們還是先使用【!name2ee】命令查找一下 Sum 方法。
1 0:000> !name2ee Example_5_1_2!Example_5_1_2.Program.Sum
2 Module:      00f34044
3 Assembly:    Example_5_1_2.exe
4 Token:       06000002
5 MethodDesc:  00f34d64
6 Name:        Example_5_1_2.Program.Sum(Int32, Int32)
7 Not JITTED yet. Use !bpmd -md 00f34d64 to break on run.

              紅色標(biāo)注說明,我們的代碼還沒有被JIT編譯。我們聽從他的建議,使用【!bpmd -md】下斷點(diǎn)。

1 0:000> !bpmd -md 00f34d64
2 MethodDesc = 00f34d64
3 Adding pending breakpoints...

              我們可以使用【g】命令,繼續(xù)運(yùn)行,果然在斷點(diǎn)處暫停。我這里是可以的,但是視頻說是不可以的。

 1 0:000> g
 2 (bb0.3798): CLR notification exception - code e0444143 (first chance)
 3 JITTED Example_5_1_2!Example_5_1_2.Program.Sum(Int32, Int32)
 4 Setting breakpoint: bp 00F8094C [Example_5_1_2.Program.Sum(Int32, Int32)]
 5 Breakpoint: JIT notification received for method Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 0100da40.
 6 Breakpoint 0 hit
 7 eax=00f80928 ebx=009ef098 ecx=0000000a edx=00000000 esi=02c224bc edi=009eefe8
 8 eip=00f8094c esp=009eefb8 ebp=009eefc8 iopl=0         nv up ei pl zr na pe nc
 9 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
10 Example_5_1_2!COM+_Entry_Point <PERF> (Example_5_1_2+0x73094c):
11 00f8094c 90              nop

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


            1)、使用 !bpmd moduleName namespace.ClassName.MethodName
                這個實(shí)現(xiàn)的原理是借助 JIT 的編譯完成通知事件,在事件中判斷當(dāng)前編譯的是否是我們下斷點(diǎn)的方法,如果是就轉(zhuǎn)成 bp 命令下斷點(diǎn),從輸出的信息也可以看得出來。
                【!bpmd】命令格式一下兩種都對:!bpmd Example_5_1_2.exe Example_5_1_2.Program.Sum 或者 !bpmd Example_5_1_2 Example_5_1_2.Program.Sum
1 0:000> !bpmd Example_5_1_2 Example_5_1_2.Program.Sum
2 Found 1 methods in module 011a4044...
3 MethodDesc = 011a4d64
4 Adding pending breakpoints...

                斷點(diǎn)設(shè)置成功,【g】繼續(xù)運(yùn)行,成功在斷點(diǎn)處暫停。

 1 0:000> g
 2 (14c4.1b60): CLR notification exception - code e0444143 (first chance)(表示 JIT 已經(jīng)編譯好了,CLR 給 Windbg 發(fā)出一個異常通知)
 3 JITTED Example_5_1_2!Example_5_1_2.Program.Sum(Int32, Int32)
 4 Setting breakpoint: bp 02DD094C [Example_5_1_2.Program.Sum(Int32, Int32)](Windbg 拿到編譯后的機(jī)器碼地址,重新設(shè)置斷點(diǎn))
 5 Breakpoint: JIT notification received for method Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 011f0fe8.
 6 Breakpoint 0 hit
 7 eax=02dd0928 ebx=00efedd8 ecx=0000000a edx=00000000 esi=02f124bc edi=00efed28
 8 eip=02dd094c esp=00efecf8 ebp=00efed08 iopl=0         nv up ei pl zr na pe nc
 9 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
10 Example_5_1_2!COM+_Entry_Point <PERF> (Example_5_1_2+0x22d094c):
11 02dd094c 90              nop

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


            2)、使用 sosex 擴(kuò)展的 mbm 下斷點(diǎn)(只能在 Net framework 下使用,Net Core 是不支持的,必須使用.load命令加載 SOSEX.dll)。
                mbm 是非托管命令 bm 的托管版本,對方法名下斷點(diǎn),還支持模糊匹配。
                
1 0:000> !mbm Example_5_1_2!Example_5_1_2.Program.Sum

                設(shè)置斷點(diǎn)后,我們可以繼續(xù)運(yùn)行,執(zhí)行【g】命令。

1 0:000> g
2 Breakpoint: JIT notification received for method Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 00a61010.
3 Breakpoint set at Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 00a61010.
4 Breakpoint 5 hit
5 eax=00a20928 ebx=008ff050 ecx=0000000a edx=00000000 esi=029d24bc edi=008fef98
6 eip=00a2094c esp=008fef68 ebp=008fef78 iopl=0         nv up ei pl zr na pe nc
7 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
8 Example_5_1_2!COM+_Entry_Point <PERF> (Example_5_1_2+0x5a094c):
9 00a2094c 90              nop

                成功斷住,效果如圖:

                Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)
                【mbm】命令很強(qiáng)大,也可以支持模糊查找。這個操作是另外一個過程,需要重新運(yùn)行調(diào)試程序。
1 0:000> !mbm Example_5_1_2!*Sum

                成功在斷點(diǎn)出暫停。

1 0:000> g
2 Breakpoint: JIT notification received for method Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 01720fb8.
3 Breakpoint set at Example_5_1_2.Program.Sum(Int32, Int32) in AppDomain 01720fb8.
4 Breakpoint 1 hit
5 eax=031c0928 ebx=0137f378 ecx=0000000a edx=00000000 esi=033d24bc edi=0137f2c8
6 eip=031c094c esp=0137f298 ebp=0137f2a8 iopl=0         nv up ei pl zr na pe nc
7 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
8 Example_5_1_2!COM+_Entry_Point <PERF> (Example_5_1_2+0x21e094c):
9 031c094c 90              nop

              
        2.4、在泛型方法上下斷點(diǎn)。
            測試程序:Example_5_1_3
            我們使用 Windbg Preview 調(diào)試器,通過【launch executable】菜單加載【Example_5_1_3.exe】項(xiàng)目,通過【g】命令,運(yùn)行程序,調(diào)試器運(yùn)行代【Debugger.Break();】次會暫停執(zhí)行。當(dāng)然,我們可以使用【cls】命令清理一下調(diào)試器顯示的過多信息,自己來決定,我是會清理的。
            這次的任務(wù)是,我們要在泛型類型 MyList<T> 的 Add() 方法上下斷點(diǎn)。
            我們想要在泛型類型的方法上下斷點(diǎn),首要的任務(wù)是找到泛型類型的名稱和方法的名稱,這是關(guān)鍵。
            效果如圖:
            Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)

            a、我們通過 Windbg 和 SOS 的命令找到類型的名稱。
                編譯程序集后,泛型類型一定在這個程序集的模塊中。然后我們再在這個模塊中打印出所有的類型,就可以找到這個類型了。
                我們現(xiàn)在這個程序集中查找模塊信息,我們可以使用【!dumpdomain】命令。
 1 0:000> !dumpdomain
 2 --------------------------------------
 3 System Domain:      7141caf8
 4 ....
 5 --------------------------------------
 6 Shared Domain:      7141c7a8
 7 ......
 8 
 9 --------------------------------------
10 Domain 1:           00a2da30
11 ......
12 
13 Assembly:           00a87ea8 [E:\Visual Studio 2022\Source\Projects\......\Example_5_1_3\bin\Debug\Example_5_1_3.exe]
14 ClassLoader:        00a873a8
15 SecurityDescriptor: 00a872a0
16   Module Name
17 01004044(模塊地址)    E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_5_1_3\bin\Debug\Example_5_1_3.exe

              我們找到了模塊,就可以將模塊中所有的類型輸出出來,可以使用【!dumpmodule -mt 】命令。

 1 0:000> !dumpmodule -mt 01004044 
 2 Name:       E:\Visual Studio 2022\Source\Projects\...\Example_5_1_3\bin\Debug\Example_5_1_3.exe
 3 Attributes: PEFile 
 4 Assembly:   00a87ea8
 5 LoaderHeap:              00000000
 6 TypeDefToMethodTableMap: 01000038
 7 TypeRefToMethodTableMap: 01000048
 8 MethodDefToDescMap:      01000094
 9 FieldDefToDescMap:       010000a8
10 MemberRefToDescMap:      00000000
11 FileReferencesMap:       010000b8
12 AssemblyReferencesMap:   010000bc
13 MetaData start address:  006220a8 (1680 bytes)
14 
15 Types defined in this module
16 
17       MT  TypeDef Name
18 ------------------------------------------------------------------------------
19 01004d6c 0x02000002 Example_5_1_3.Program
20 01004de8 0x02000003 Example_5_1_3.MyList`1
21 
22 Types referenced in this module
23 
24       MT    TypeRef Name
25 ------------------------------------------------------------------------------
26 6f802734 0x02000010 System.Object
27 6f847540 0x02000011 System.Diagnostics.Debugger
28 6f808af0 0x02000012 System.Console

              紅色標(biāo)注的就是我們要查找泛型類型真實(shí)的名稱。有了類型,我們繼續(xù)可以使用【!dumpmt -md ...】命令,輸出它所有方法。

 1 0:000> !dumpmt -md 01004de8
 2 EEClass:         01001334
 3 Module:          01004044
 4 Name:            Example_5_1_3.MyList`1
 5 mdToken:         02000003
 6 File:            E:\Visual Studio 2022\Source\Projects\......\Example_5_1_3\bin\Debug\Example_5_1_3.exe
 7 BaseSize:        0xc
 8 ComponentSize:   0x0
 9 Slots in VTable: 6
10 Number of IFaces in IFaceMap: 0
11 --------------------------------------
12 MethodDesc Table
13    Entry MethodDe    JIT Name
14 6fbf97b8 6f7fc838 PreJIT System.Object.ToString()
15 6fbf96a0 6f938978 PreJIT System.Object.Equals(System.Object)
16 6fc021f0 6f938998 PreJIT System.Object.GetHashCode()
17 6fbb4f2c 6f9389a0 PreJIT System.Object.Finalize()
18 02840458 01004dd4   NONE Example_5_1_3.MyList`1..ctor()
19 02840450 01004dcc   NONE Example_5_1_3.MyList`1.Add(!0)

              紅色標(biāo)記就是我們要查找的 Add 方法,有了方法的地址,我們就可以使用【bpmd】命令為其下斷點(diǎn)了。

1 0:000> !bpmd Example_5_1_3 Example_5_1_3.MyList`1.Add
2 Found 1 methods in module 01004044...
3 MethodDesc = 01004dcc
4 Adding pending breakpoints...

              斷點(diǎn)設(shè)置成功后,我們使用【g】命令,程序繼續(xù)運(yùn)行,就可以在斷點(diǎn)處暫停。

 1 0:000> g
 2 (3ab4.2920): CLR notification exception - code e0444143 (first chance)
 3 JITTED Example_5_1_3!Example_5_1_3.MyList`1[[System.Int32, mscorlib]].Add(Int32)
 4 Setting breakpoint: bp 02840942 [Example_5_1_3.MyList`1[[System.Int32, mscorlib]].Add(Int32)]
 5 Breakpoint: JIT notification received for method Example_5_1_3.MyList`1[[System.Int32, mscorlib]].Add(Int32) in AppDomain 00a2da30.
 6 Breakpoint 0 hit
 7 eax=02840928 ebx=007bee20 ecx=029f26b0 edx=0000000a esi=00000000 edi=007bed90
 8 eip=02840942 esp=007bed58 ebp=007bed60 iopl=0         nv up ei pl zr na pe nc
 9 cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
10 Example_5_1_3!COM+_Entry_Point <PERF> (Example_5_1_3+0x2220942):
11 02840942 90              nop

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


            b、我們可以使用 ILSpy 來查找泛型類型的名稱和方法的名稱。
              效果如圖:
              Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)

                上面就是類型的名稱,我繼續(xù)查找方法的名稱,也很簡單。
              效果如圖:

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

              有了這些信息,我們就可以使用 Windbg 為程序設(shè)置斷點(diǎn)了,操作過程和 a 的過程一樣,就不多說了。文章來源地址http://www.zghlxwxcb.cn/news/detail-741808.html


四、總結(jié)
    終于寫完了,為什么說是終于,因?yàn)閷戇@一篇文章,不是一天完成的。寫文章,記錄操作過程,作圖例,所以時間就長了。今天介紹的是如何在方法上設(shè)置斷點(diǎn),有了斷點(diǎn),我們就可以使用上一篇講的動態(tài)調(diào)試命令,我們就可以更容易完成調(diào)試任務(wù),掌握這些調(diào)試技巧還是很有必要的。好了,不說了,不忘初心,繼續(xù)努力,希望老天不要辜負(fù)努力的人。

到了這里,關(guān)于Net 高級調(diào)試之五:如何在托管函數(shù)上設(shè)置斷點(diǎn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 如何洞察 .NET程序 非托管句柄泄露

    如何洞察 .NET程序 非托管句柄泄露

    很多朋友可能會有疑問,C# 是一門托管語言,怎么可能會有非托管句柄泄露呢? 其實(shí)一旦 C# 程序與 C++ 語言交互之后,往往就會被后者拖入非托管泥潭,讓我們這些調(diào)試者被迫探究 非托管領(lǐng)域問題 。 為了方便講述,我們上一個 Event 泄露的案例,使用 C# 調(diào)用 C++ ,然后讓

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

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

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

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

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

    前幾天有位朋友找到我,說他的機(jī)器內(nèi)存在不斷的上漲,但在任務(wù)管理器中查不出是哪個進(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è)計的內(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)常會有一些朋友問我什么是 工作集(內(nèi)存) ,什么是 提交大小 ,什么是 Virtual Size , 什么是 Working Set 。。。截圖如下: 既然有很多朋友問,這些用口頭也不怎么好描述,剛好上午有時間就系統(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)形式。有了這個基礎(chǔ),我們可以更好的了解我們的程序在運(yùn)行時的狀態(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è)計的內(nèi)容挺多的,比如:如何查看方法的匯編代碼,如何獲取方法的描述符,對象同步塊的轉(zhuǎn)儲,對象方法表的轉(zhuǎn)儲,托管堆和垃圾回收器信息的轉(zhuǎn)儲,CLR 的版本,GC 模式,等等,內(nèi)容挺多的。內(nèi)容雖然挺多,但是

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

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

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

    2024年02月05日
    瀏覽(23)
  • Net 高級調(diào)試之三:類型元數(shù)據(jù)介紹(同步塊表、類型句柄、方法描述符等)

    Net 高級調(diào)試之三:類型元數(shù)據(jù)介紹(同步塊表、類型句柄、方法描述符等)

    一、簡介 今天是《Net 高級調(diào)試》的第三篇文章,壓力還是不小的。上一篇文章,我們淺淺的談了談 CLR 和 Windows 加載器是如何加載 Net 程序集的,如何找到程序的入口點(diǎn)的,有了前面的基礎(chǔ),我們今天看一點(diǎn)更詳細(xì)的東西。既然 Windows 操作系統(tǒng)已經(jīng)加載了 CLR,初始化了應(yīng)用程

    2024年02月08日
    瀏覽(13)
  • Net 高級調(diào)試之六:對象檢查之值類型、引用類型、數(shù)組和異常的轉(zhuǎn)儲

    Net 高級調(diào)試之六:對象檢查之值類型、引用類型、數(shù)組和異常的轉(zhuǎn)儲

    一、簡介 今天是《Net 高級調(diào)試》的第六篇文章。記得我剛接觸 Net 框架的時候,還是挺有信心的,對所謂的值類型和引用類型也能說出自己的見解,畢竟,自己一直在努力。當(dāng)然這些見解都是書本上的,并沒有做到眼見為實(shí),所以總是有些東西說不清楚。今天,我們就好好的

    2024年02月05日
    瀏覽(15)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包