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

摘要:
这不是什么新鲜事。许多书都写得很详细。然而,有些人问如何通过简单地拔下VS来断开进程。例如,使用windg开始调试记事本。在exe的情况下,首先要断开的是ntdll!如何实现调试器附加函数和正在中断的进程?调试器将调用此函数在目标进程中创建线程。此线程执行的代码如下:00adffc87c951e40ntdll!当CPU执行int3指令时,它将触发异常处理。最后,调试器将处理异常并挂起进程中的所有线程。

不是什么新鲜的东西,很多书上写的非常详细了,不过有人问到,简要的扯下这个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上面。

免责声明:文章转载自《使用VS调试时,被调试进程如何被断下来的。》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mtd-utilISurfaceOp 接口生成等高线(二)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C++面试

https://blog.csdn.net/weixin_44363885/article/details/99567746 这一行是个 贼鸡巴重要的链接!!!   很好的总结 我直接复制到下面了: 社招:社招的同学,无论是1-3年经验,还是中途转行,都可参考。写简历必须有针对性,以后台开发为例,请去拉勾网 / 猎聘 / 智联招聘等网站,多看看后台开发的J...

线程中断总结

1、线程中断 每个线程都有一个与之相关联的 Boolean 属性,用于表示线程的中断状态(interrupted status)。中断状态初始时为 false;当另一个线程通过调用Thread.interrupt()中断一个线程时,会出现以下两种情况之一。如果那个线程在执行一个低级可中断阻塞方法,例如Thread.sleep()、Thread.join()...

Java线程并发中常见的锁--自旋锁 偏向锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题。本文着重介绍了在java并发中常见的几种锁机制。 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制。其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作...

GDB常用调试命令以及多进程多线程调试

http://blog.csdn.net/freeelinux/article/details/53700266 一:普通命令   1.list命令 list  linenum      显示程序第linenum行周围的程序 list  function      显示函数名为function的函数的源程序 list                  ...

android 在子线程中使用handler更新界面

1. 在子线程中创建一个handler对象,让这个handler对象获取主线程的looper,这样才能把这个handler中的消息发送到ui线程的消息队列中 下面这个界面当点击updateui按钮就会创建一个对象然后调用它的更新图片和文字的方法,这两个设置方法在子线程中执行。 在更新界面的对象的类中创建一个handler对象,在初始化的时候给他赋值为Lo...

WinForm 子线程修改主线程(UI线程)

原文http://www.cnblogs.com/SkySoot/archive/2012/03/14/2396552.html 我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: 1 public partial class TestThread : Form 2 { 3 public Test...