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 }
1 namespace Example_5_1_2 2 { 3 internal class Program 4 { 5 static void Main(string[] args) 6 { 7 Console.WriteLine("請檢視:未編譯形態的 Sum 方法"); 8 Debugger.Break(); 9 10 var sum = Sum(10,20); 11 Console.WriteLine("請檢視:已經編譯形態的 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 }
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 }
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 函數下斷點。下斷點後,繼續執行,使用【g】命令。
1 0:002> bp notepad!SaveFile 2 0:002> g
此時,我們可以操作 notepad,隨便輸入一些內容,然後點選【儲存】,就可以被斷點斷住。
1 ....... 2 Breakpoint 0 hit 3 notepad!SaveFile: 4 00007ff6`e46be780 488bc4 mov rax,rsp
我們可以使用【k】命令顯示呼叫棧也能說明問題。
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
截圖效果:
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
紅色標註表示程式碼已經編譯,我們也可以使用【!u】命令檢視這個程式碼的組合程式碼,組合程式碼很多,所以摺疊。
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
我們使用【bp】命令在地址【01010908】地址處下斷點,【g】繼續執行,就會在 Sum 方法的第一行斷住。
0:000> bp 01010908
繼續執行後,
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
效果截圖:
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.
紅色標註說明,我們的程式碼還沒有被JIT編譯。我們聽從他的建議,使用【!bpmd -md】下斷點。
1 0:000> !bpmd -md 00f34d64 2 MethodDesc = 00f34d64 3 Adding pending breakpoints...
我們可以使用【g】命令,繼續執行,果然在斷點處暫停。我這裡是可以的,但是視訊說是不可以的。
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
截圖效果:
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...
斷點設定成功,【g】繼續執行,成功在斷點處暫停。
1 0:000> g 2 (14c4.1b60): CLR notification exception - code e0444143 (first chance)(表示 JIT 已經編譯好了,CLR 給 Windbg 發出一個異常通知) 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 拿到編譯後的機器碼地址,重新設定斷點) 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
截圖效果:
1 0:000> !mbm Example_5_1_2!Example_5_1_2.Program.Sum
設定斷點後,我們可以繼續執行,執行【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
成功斷住,效果如圖:
1 0:000> !mbm Example_5_1_2!*Sum
成功在斷點出暫停。
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
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
紅色標註的就是我們要查詢泛型型別真實的名稱。有了型別,我們繼續可以使用【!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)
紅色標記就是我們要查詢的 Add 方法,有了方法的地址,我們就可以使用【bpmd】命令為其下斷點了。
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...
斷點設定成功後,我們使用【g】命令,程式繼續執行,就可以在斷點處暫停。
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
斷點效果如圖:
上面就是型別的名稱,我繼續查詢方法的名稱,也很簡單。
效果如圖:
有了這些資訊,我們就可以使用 Windbg 為程式設定斷點了,操作過程和 a 的過程一樣,就不多說了。