|
一、简介
今天是《Net 高级调试》的第五篇文章。今天这篇文章开始介绍如何在托管方法和非托管方法设置断点,我们要想调试程序,必须掌握调试的一些命令,动态调试的命令,我们在上一篇文章已经讲过了。光有命令也是不行的,要让这些调试命令有用,必须可以在方法上设置断点,然后,再使用调试命令,才能完成我们的调试任务。当然了,第一次看视频或者看书,是很迷糊的,不知道如何操作,还是那句老话,一遍不行,那就再来一遍,还不行,那就再来一遍,俗话说的好,书读千遍,其意自现,我这是第三遍。
如果在没有说明的情况下,所有代码的测试环境都是 Net Framewok 4.8,但是,有时候为了查看源码,可能需要使用 Net Core 的项目,我会在项目章节里进行说明。好了,废话不多说,开始我们今天的调试工作。
调试环境我需要进行说明,以防大家不清楚,具体情况我已经罗列出来。
操作系统:Windows Professional 10
调试工具:Windbg Preview(可以去Microsoft Store 去下载)
开发工具:Visual Studio 2022
Net 版本:Net Framework 4.8
CoreCLR源码:源码下载
二、基础知识
1、非托管函数下断点
其实对非托管函数下断点是十分方便的,因为C/C++函数在编译之后就成了【机器代码】了,函数名就进入了【符号表】,比如我们可以非常方便的 notepad 的 SaveFile 函数下断点。
操作步骤如下:
a、打开 notepad 。
b、使用 x notepad!SaveFile 下断点。
c、在 notepad 上保存一下文件,就会触发断点。
2、托管函数下断点
2.1、简介
托管函数下断点是很难的,因为你要下断点的方法的机器码在内存中可能还没有生成,也就是 JIT 从来就没有对该方法进行编译过,所以在还没有生成的代码上下断点就比较麻烦。虽然比较麻烦,并不代表不能实现,我们还是有三种方法可以对托管函数下断点的。
2.2、托管函数下断点的三种方式
1)、在编译后的函数上下断点
这是最简单的一种方式,既然方法已经编译完成,肯定就已经生成了机器代码,那在编译后的函数上下断点就容易很多了,和非托管的是一样的。
2)、在未编译的函数上下断点
a、使用 !bpmd assembly.exe(模块包含后缀名) namespace.ClassName.MethodName
b、使用 sosex 扩展的 mbm 下断点(只能在 Net framework 下使用,Net Core 是不支持的)。
3)、对泛型方法下断点
如果我们想对泛型类型的方法下断点,最首要的任务就是找到泛型类型的名称和方法的名称,找到之后,我们就可以下断点了。找泛型类型的名称和方法的名称有两种办法,第一种是通过命令,第二种是我们可以使用 ILSpy 找到。
三、调试过程
废话不多说,这一节是具体的调试操作的过程,又可以说是眼见为实的过程,在开始之前,我还是要啰嗦两句,这一节分为两个部分,第一部分是测试的源码部分,没有代码,当然就谈不上测试了,调试必须有载体。第二部分就是根据具体的代码来证实我们学到的知识,是具体的眼见为实。
1、测试源码
1.1、Example_5_1_1
- 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
- 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 }
复制代码 View Code
1.3、Example_5_1_3
- 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、眼见为实
2.1、在非托管函数 Notepad 的 SaveFile 方法上下断点。
测试程序:Notepad
操作流程:我们先要打开 notepad,然后再打开 windbg,点击【文件】菜单,然后通过【attach to process】附加进程,最后点击【Attach】按钮完成附加进程的操作。现在 notepad 是不能操作的,因为断点断住了,所以我们执行【g】命令,运行一下。然后我们点击工具栏【break】按钮,中断,然后就可以调试了。
我们使用【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 函数下断点。下断点后,继续运行,使用【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
复制代码 截图效果:
2.2、在已经编译的托管函数上下断点。
测试程序:Example_5_1_1
我们使用 Windbg Preview 调试器,通过【launch executable】菜单加载【Example_5_1_1.exe】项目,通过【g】命令,运行程序,调试器运行代【Debugger.Break()】次会暂停执行。当然,我们可以使用【cls】命令清理一下调试器显示的过多信息,自己来决定,我是会清理的。我们将在【sum = Sum(100, 200);】这行下断点。
当调试器暂停的时候,说明有一部分代码已经执行了。【var sum = Sum(10, 20);】就是这行代码已经被执行,也可以说是被 JIT 编译了。我们如何查看 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 <strong>JITTED Code Address: 01010908</strong>
复制代码 红色标注表示代码已经编译,我们也可以使用【!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
复制代码 View Code
我们使用【bp】命令在地址【01010908】地址处下断点,【g】继续运行,就会在 Sum 方法的第一行断住。 继续运行后, - 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
复制代码 效果截图:
2.3、在未编译的托管函数上下断点。
测试程序:Example_5_1_2
我们使用 Windbg Preview 调试器,通过【launch executable】菜单加载【Example_5_1_2.exe】项目,通过【g】命令,运行程序,调试器运行代【Debugger.Break()】次会暂停执行,此行代码在12。当然,我们可以使用【cls】命令清理一下调试器显示的过多信息,自己来决定,我是会清理的。这次我们的任务依然是在 Sum 方法上下断点。
先来一个截图吧,效果更明显:
我们还是先使用【!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<strong> Not JITTED yet. Use !bpmd -md 00f34d64 to break on run.</strong>
复制代码 红色标注说明,我们的代码还没有被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)、使用 !bpmd moduleName namespace.ClassName.MethodName
这个实现的原理是借助 JIT 的编译完成通知事件,在事件中判断当前编译的是否是我们下断点的方法,如果是就转成 bp 命令下断点,从输出的信息也可以看得出来。
【!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...
复制代码 断点设置成功,【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
复制代码 截图效果:
2)、使用 sosex 扩展的 mbm 下断点(只能在 Net framework 下使用,Net Core 是不支持的,必须使用.load命令加载 SOSEX.dll)。
mbm 是非托管命令 bm 的托管版本,对方法名下断点,还支持模糊匹配。
- 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
复制代码 成功断住,效果如图:
【mbm】命令很强大,也可以支持模糊查找。这个操作是另外一个过程,需要重新运行调试程序。- 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
复制代码
2.4、在泛型方法上下断点。
测试程序:Example_5_1_3
我们使用 Windbg Preview 调试器,通过【launch executable】菜单加载【Example_5_1_3.exe】项目,通过【g】命令,运行程序,调试器运行代【Debugger.Break();】次会暂停执行。当然,我们可以使用【cls】命令清理一下调试器显示的过多信息,自己来决定,我是会清理的。
这次的任务是,我们要在泛型类型 MyList 的 Add() 方法上下断点。
我们想要在泛型类型的方法上下断点,首要的任务是找到泛型类型的名称和方法的名称,这是关键。
效果如图:
a、我们通过 Windbg 和 SOS 的命令找到类型的名称。
编译程序集后,泛型类型一定在这个程序集的模块中。然后我们再在这个模块中打印出所有的类型,就可以找到这个类型了。
我们现在这个程序集中查找模块信息,我们可以使用【!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 <strong>01004044(模块地址)</strong> 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 <strong>01004de8</strong> <strong>0x02000003 Example_5_1_3.MyList`1</strong>
- 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 <strong>NONE Example_5_1_3.MyList`1.Add(!0)</strong>
复制代码 红色标记就是我们要查找的 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
复制代码 断点效果如图:
b、我们可以使用 ILSpy 来查找泛型类型的名称和方法的名称。
效果如图:
上面就是类型的名称,我继续查找方法的名称,也很简单。
效果如图:
有了这些信息,我们就可以使用 Windbg 为程序设置断点了,操作过程和 a 的过程一样,就不多说了。
四、总结
终于写完了,为什么说是终于,因为写这一篇文章,不是一天完成的。写文章,记录操作过程,作图例,所以时间就长了。今天介绍的是如何在方法上设置断点,有了断点,我们就可以使用上一篇讲的动态调试命令,我们就可以更容易完成调试任务,掌握这些调试技巧还是很有必要的。好了,不说了,不忘初心,继续努力,希望老天不要辜负努力的人。
来源:https://www.cnblogs.com/PatrickLiu/archive/2023/11/03/17804823.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|