zoukankan      html  css  js  c++  java
  • 利用WinDbg 远程调试

    介绍
    在我的职业生涯中,我看到我们大多数都是使用Visual Studio来进行调试,而不是用其它许多免费的调试器。你可能有许多理由来使用这样的调试器,比如,在你家里的机器上没装开发环境,但是一个程序一次次的崩溃。其实根据堆栈的dump就可以判断出IE的崩溃是否是由于一个第三方的插件。

    对于WinDbg,我目前为止还没有发现很好的快速入门的教程。这篇文章结合实例讨论了WinDbg的使用。我首先假设你熟悉调试的基本概念:stepping in, stepping out,断点以及远程调试的基本概念。

    注意,这本来是座位一个入门的文档,你可以阅读并且开始使用WinDbg. 如果对于特定的命令有疑问,请查阅WinDbg的文档。你可以在任何微软提供的调试器中使用这篇文章中提到的命令,比如在VS的命令行窗口中。

    这篇文章是基于WinDbg 6.3.

    这仅仅是一系列关于调试技术的文章中的第一篇。在下一篇文章中,我会解释如何针对调试器编写扩展DLL.

    调试器一览
    下面大概介绍了你可以从微软网站上下载到的调试器:

    ·         KD-内核调试器。你可以用它来调试蓝屏一类的系统问题。如果是开发设备驱动程序是少不了它的。

    ·         CDB-命令行调试器。这是一个命令行程序

    ·         NTSD-NT调试器。这是一个用户模式调试器,可以用来调试用户模式应用程序。它实际上是一个CDB的windows UI增强。

    ·         WinDbg-用一个漂亮的UI包装了KD和NTSD。WinDbg即可以调试内核模式,也可以调试用户模式程序。

    ·         VS, VS.net-使用同KD和NTSD相同的调试引擎,并且相比于同样用于调试目的的WinDbg,提供了功能更丰富的界面。

    调试器之间的比较
    功能
     KD
     NTSD
     WinDbg
     Visual Studio .NET
     
    内核模式调试
     Y
     N
     Y
     N
     
    用户模式调试
     
     Y
     Y
     Y
     
    非托管调试
     Y
     Y
     Y
     Y
     
    托管调试
     
     Y
     Y
     Y
     
    远程调试
     Y
     Y
     Y
     Y
     
    附加到进程
     Y
     Y
     Y
     Y
     
    从进程分离
     Y
     Y
     Y
     Y
     
    SQL调试
     N
     N
     N
     Y
     

    WinDbg
    WinDbg实际上包装了NTSD和KD并且提供了一个更好用的用户界面。它也提供了命令行开关,比如最小化启动(-m),附加到一PID指定的进程(-p)以及自动打开崩溃文件(-z)。它支持三种类型的命令。

    ·         Regular commands(比如: k) 用来调试进程

    ·         Dot commands(比如:.sympath)用来控制调试器

    ·         Extension commands(比如: !handle)-这些命令属于可以用来添加到WinDbg的自定义命令;它们用扩展DLL的输出函数来实现。

    PDB文件
    PDB文件指的是链接器生成程序数据库文件(Program database files)。私有的PDB文件包括私有以及公有符号,源代码行号,类型,局部以及全局变量。公有的PDB文件不包含类型,局部变量以及源代码行号信息。

    调试场景
    远程调试
    使用WinDbg进行远程调试是很容易的,而且有很多种可行的方法。在下文中,’调试服务器’指的是运行在你所要调试的远程机器上的调试器。’调试客户端’指的是控制当前会话的调试器。

    ·         使用调试器:你需要CDB, NTSD或者WinDbg已经安装在远程机器上。WinDbg客户端可以连接到CDB, NTSD或者WinDbg中的任何一个作为服务器,反之亦然。在客户端和服务器直接可以选择TCP或者命名管道作为通讯协议。

    o   在服务器端的启动过程:

    §  WinDbg –server npipe:pipe=pipename(注:可以允许多个客户端连或

    §  从WinDbg内部: .server npipe:pipe=pipename(注,连接单个客户端)

    你可以用多种协议开启不同的服务会话。并且可用密码来保护一个会话。

    o   从客户端连接:

    §  WinDbg -remote npipe:server=Server, pipe=PipeName[,password=Password]

    §  从WinDbg内部: File->Connect to Remote Session: for connection string, enter npipe:server=Server, pipe=PipeName [,password=Password]

    ·         使用Remote.exe: Remote.exe使用命名管道作为通讯的方式。如果你使用的是一个命令行接口的程序,比如KD,CDB或者NTSD。你可以使用remote.exe来远程调试。注意:使用@q(不是q)来退出客户端,不用关掉服务端。

    o   要启动一个服务端:

    §  Remote.exe /s “cdp –p <pid>” test1

    o   从客户端连接:

    §  Remote.exe /c <machinename> test1

    上面的test1是我们所选择的命名管道的名字。

    服务端会显示那个客户端从那个服务器连接以及执行过的命令。你可以使用‘qq’命令来退出服务端;或者使用File->Exit来退出客户端。另外,如果要进行远程调试,你必须属于远程机器的”Debugger User”组并且服务器必须允许远程连接。

    即时调试
    在WinDbg的文档的”Enabling Postmorten Debugging”部分对此有很详细的讨论。简而言之,你可以把WinDbg设置成默认的即时调试器,命令就是:Windbg –I。这个命令实际上是把注册表中 HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug的键值设置成WinDbg。如果要把WinDbg设置成为默认的托管调试器,你需要显示设置如下的注册表键值:

    •HKLM\Software\Microsoft\.NETFramework\DbgJITDebugLaunchSetting 设置成 2
    •HKLM\Software\Microsoft\.NETFramework\DbgManagedDebugger 设置成Windbg.(注意其中的启动参数设置)
    通过JIT的设置,当一个应用程序在不是调试的状态下抛出了未处理的异常之时,WinDbg就会被启动。

    64位调试
    所有这些调试器均支持在AMD64和IA64上的64位调试环境。

    托管应用程序的调试
    WinDbg 6.3以后的版本支持在Widbey(VS2005和.net 2.0的内部开发代号) .net CLR托管调试。在文档中针对托管调试有很好的讨论。需要注意的是,对于托管程序来说,没有刚才所说的PDB(译注:托管代码实际上也是有PDB的,但是这个PDB实际上记录了C#代码和IL代码的对应关系以及相关的一些信息)的概念,因为所有的程序都是编译成为ILASM。调试器通过CLR来查询所需的附加信息。

    有几点需要注意:

    你只能在托段函数的代码被执行过至少一次之后才能设置断点。只有这样它才能被编译成汇编代码。记住以下的几点:

    ·         关于函数的地址的复杂化以及对应的断点设置:

    o   CLR有可能丢弃已经编译好的代码,所以函数的入口地址有可能改变。

    o   同样的代码有可能被多次编译,如果多个应用程序域没有共享这段代码的话。如果你设置了一个断点,它就会被设置在当前线程(译注:CLR的逻辑线程)所在的应用程序域内。

    o   泛型的特殊实例可能导致同一个函数有不同的地址。.

    ·         数据存储布局的复杂化以及对应的数据检查:

    •CLR可能会在运行的时候任意改变数据的存储布局,所以一个结构体成员的偏移量可能会被改变掉. (译注:实际上是在一个类型被加载的时候决定的数据布局,之后是不会改变的。)
    •一个类型的信息是在第一次使用的时候被加载,所以你可能不能够查看一个数据成员如果它还没有被使用过.
    ·         调试器命令的复杂化

    o   当跟踪托管代码的时候,你会需要穿越大段的CLR自己的代码比如JIT编译器的代码,原因可能是你第一次进入一个函数,或者是你在托管和非托管代码之间进行切换。

    调试Windows服务
    使用WinDbg,你可以像调试其它应用程序那样调试Windows服务程序。即可以通过附加进程的方法启动Windows服务,也可以把WinDbg当作一个即时调试器,并且在代码中调用DbgBreakPoint 或者 DebugBreak,或者在x86机器上加入一条int 3汇编指令。

    调试异常
    一个调试器会得到两次的异常通知-第一次在应用程序有机会处理异常之前(‘first chance exception’);如果应用程序没有处理这个异常,这时候调试器就会有机会来处理异常(‘second-chance exception’)。如果调试器没有处理二次机会的异常,应用程序就会退出。

    .lastevent或者,!analyze –v命令会给你显示异常的记录以及异常抛出所在函数的堆栈跟踪信息。

    你也可以使用 .exr, .cxr以及 .ecxr命令来显示异常和上下文记录。同时需要注意的是,你也可以改变first-chance的处理选项。对应的命令就是: sxe, sxd, sxn和sxi。

    reference:

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/iamoyjj/archive/2009/04/17/4088390.aspx

  • 相关阅读:
    C++11中静态局部变量初始化的线程安全性
    213. 打家劫舍 II
    cas解决aba相关问题
    socket[可读可写异常]3种条件的发生
    linux信号处理 (信号产生 信号阻塞 信号集)
    vim set paste解决粘贴乱序乱码问题
    174. 地下城游戏
    208. 实现 Trie (前缀树) 和 面试题 17.13. 恢复空格
    Centos安装和卸载docker
    Go语言轻量级框架-Gin与入门小案例MySQL增删查改
  • 原文地址:https://www.cnblogs.com/czjone/p/1862563.html
Copyright © 2011-2022 走看看