您的位置:首页 > 其它

使用VS调试时,被调试进程如何被断下来的。

2011-07-24 01:32 246 查看
不是什么新鲜的东西,很多书上写的非常详细了,不过有人问到,简要的扯下这个VS如何断下进程的。

++++++++++++++++++++++++++

当用VS的时候,按下F10后,为什么能够停在程序的入口处呢?

这个问题首先从windows API CreateProcess的Process Creation Flags说起。如果在创建进程的时候加了这个DEBUG_PROCESS这个flag. 那么进程环境块(Process environment block, 简称PEB)中的BeingDebugged设为1. 如果用Windbg的命令!peb来看的话
0:000> !peb

PEB at 7ffd8000

InheritedAddressSpace: No

ReadImageFileExecOptions: No

BeingDebugged: Yes <== 这个是yes.

下一步是LdrpInitializeProcess函数被调用来初始化进程的时候,这个函数会去检查BeingDebugged这个位,如果为1的话,就会调用函数ntdll!DbgBreakPoint这个函数。
比如说用windbg来开始调试notepad.exe的话,首先断下来的地方在ntdll!DbgBreakPoint函数里
0:000> kL

ChildEBP RetAddr

0007fb1c 7c940442 ntdll!DbgBreakPoint

0007fc94 7c9210af ntdll!LdrpInitializeProcess+0xffa

0007fd1c 7c90e457 ntdll!_LdrpInitialize+0x183

00000000 00000000 ntdll!KiUserApcDispatcher+0x7

这个函数非常简单,只有一个int 3指令。
ntdll!DbgBreakPoint:

7c90120e cc int 3

7c90120f c3 ret
这里是任何debuger第一次断下来进程的地方。无论是windbg还是VS.
在这个时候notepad.exe的binary已经被load到内存里面了,但是还没有开始执行。这个时候VS就可以加载符号文件,并且知道用户写的代码的入口在什么地方。于是在入口处设下一个断点,然后直接恢复进程的执行,而用户并不会察觉到其实VS debuger已经中断过进程一次了,而是直接发现程序停在了main处。

哪么调试器的attach功能,和break当前被调试的进程又是如何实现的呢?程序已经跑起来了,这个时候可能没有被设置任何一个断点。
这个是利用Windows API CreateRemoteThread来实现的。调试器会调用这个函数在目标进程中创建一个线程,这个线程执行的代码如下:
00adffc8 7c951e40 ntdll!DbgBreakPoint

00adfff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d
还是ntdll!DbgBreakPoint这个函数,由于这个函数里面有个int 3指令。CPU执行到了int 3指令的时候就会触发异常处理,最终debuger会处理这个异常,并且把进程中的所有线程挂起。
在windbg中可以看到notepad.exe被断下来以后有2个线程:
0:001> ~*

0 Id: 4b8c.3dd4 Suspend: 1 Teb: 7ffde000 Unfrozen

Start: notepad!WinMainCRTStartup (0100739d)

Priority: 0 Priority class: 32 Affinity: 3

. 1 Id: 4b8c.4c14 Suspend: 1 Teb: 7ffdd000 Unfrozen

Start: ntdll!DbgUiRemoteBreakin (7c951e13)

Priority: 0 Priority class: 32 Affinity: 3
线程0就是notepad本身的main thread.
线程1就是远程创建的线程。

当然在VS debuger里面不会看到ntdll!DbgBreakPoint这个函数,因为VS比较友好,会自动把当前处理了的线程切换到main thread上面。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: