Windbg教程-调试非托管程序的基本命令上

简介:

Windbg是跟visual studio差不多的一个调试器,可以用来调试非托管程序(native application),也可以调试托管程序(managed application)。它比VS强的地方是你可以使用它来调试Windows操作系统,因此它也被叫做kernel mode debugger,同样为kernel mode debugger的调试器还有随着windbg一起安装的kd.exe(只不过这是一个命令行工具而已)。然而它在调试托管程序方面会比VS难用很多,当然如果你想看.NET程序的CLR内部结构,例如内存相关的信息的话,使用windbg还是可以的。

WindbgVS在调试方面最大的区别是,Windbg是采用命令驱动,而VS是采用良好的用户界面(UI)驱动。粗看起来,好像windbg是可以通过类似批处理的方式来实现一些调试步骤自动化(的确是这样的,会在后续的文章中讲到),可能你会感觉windbg功能会比VS强一些。实际上VS也提供了宏支持,你可以编写宏来控制VS的调试过程请参考我以前的文章Visual Studio调试之断点技巧篇

本篇文章里,以下面这个简单的程序为例,我介绍一些在windbg中,调试托管程序常用的命令:

Nativedebug.cpp

 

#include "stdafx.h"

#include <tchar.h>

 

void Usage()

{

#ifdef _UNICODE

                   wprintf(L"[Usage]: nativedebug.exe <digital numbers>\n");

#else

                   printf("[Usage]: nativedebug.exe <digital numbers>\n");

#endif

}

 

int _tmain(int argc, _TCHAR* argv[])

{

         int result = 0;

         if ( argc != 2 )

         {

                   Usage();

                   return -1;

         }

 

         result = _ttol(argv[1]);

#ifdef _UNICODE

         wprintf(L"%s * %s = %d\n", argv[1], argv[1], result * result);

         wprintf(L"Press any key to exit ...\n");

         _getwch();

#else

         printf("%s * %s = %d\n", result * result);

         printf("Press any key to exit ...\n");

         _getch();

#endif

 

         return 0;

}

 

编译好了以后,运行windbg.exe,点击菜单中的“File-Open Executable”,在弹出的对话框中选择nativedebug.exe。你应该可以看到类似下面的输出,我使用绿色的字符注释了各行输出的含义:

#

注意黄色高亮的字体,它说明这个调试器是32位的调试器,只能调试32位的程序,

如果你需要调试x64或者IA 64的程序,需要运行对应的调试器。

#

Microsoft (R) Windows Debugger Version 6.10.0003.233 X86

Copyright (c) Microsoft Corporation. All rights reserved.

#

这一行注明了被调试程序的命令行

#

CommandLine: E:\临时文档\Windbg教程\nativedebug\Debug\nativedebug.exe

#

下面这几行说明当前没有设置好符号文件搜索路径,符号文件在调试中比源文件

还重要,关于符号文件的说明和其重要性请参考我的另外一篇文章

#                     Visual Studio调试之符号文件

#

Symbol search path is: *** Invalid ***

****************************************************************************

* Symbol loading may be unreliable without a symbol search path.           *

* Use .symfix to have the debugger choose a symbol path.                   *

* After setting your symbol path, use .reload to refresh symbol locations. *

****************************************************************************

#

可执行文件搜索路径告诉了windbg在哪里搜索可执行文件(也就是.exe.dll文件)

大部分情况下,windbg知道怎样找到可执行文件--从程序的启动目录,从PATH环境

变量里面,从system32文件夹里面等等。因此大部分情况下,你不需要设置这个变量

然而在少数情况下,你需要使用.exepath设置它。请参看windbg帮助里面的.exepath

的说明来了解。一种少数情况基本上我们用不到是内核模式的调试,另外一种情况

是在调试用户模式(user modemini dump文件的时候需要指明。

#

Executable search path is:

#

# ModLoad: 指明了当前程序加载的其所依赖的 dll文件,以及它们加载的地址。顺便

说一句,windbg有的时候会使用这些信息来将堆栈转换到对应的函数上去。

#

ModLoad: 00950000 0096b000   nativedebug.exe

ModLoad: 77d80000 77f00000   ntdll.dll

ModLoad: 76070000 76170000   C:\Windows\syswow64\kernel32.dll

ModLoad: 77670000 776b4000   C:\Windows\syswow64\KERNELBASE.dll

ModLoad: 6ed80000 6eea4000  C:\Windows\WinSxS\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_2a4cbfc25558bcd3\MSVCR90D.dll

#

下面这一行说明了当前是什么异常导致程序中断执行,是的 ,虽然我们刚刚启动被

调试的程序,的确是一个异常断点异常导致程序中断执行。至于原因请参看我的

另外一篇文章:

#                 Visual Studio调试之断点基础篇

另外,下面一行中,第一个括号里面的是当前的线程ID,第二个括号指明了当前的异常

是第一次机会处理,还是第二次机会处理。First chance的含义请参看我的这篇文章:

#                  Visual Studio调试之避免单步跟踪调试模式

(ec4.d7c): Break instruction exception - code 80000003 (first chance)

#

当前CPU中各个寄存器的值

#

eax=00000000 ebx=00000000 ecx=f2260000 edx=0016ddd8 esi=fffffffe edi=77da3bdc

eip=77e207ff esp=002df598 ebp=002df5c4 iopl=0         nv up ei pl zr na pe nc

cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b            efl=00000246

#

没有symbol,所以在调试的时候比较麻烦,另外export symbol的含义在后一篇文章

中讲

#

*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -

#

当前中断时,程序正在执行的函数,以及其位置。

#

ntdll!LdrVerifyImageMatchesChecksum+0x6ce:

#

当前执行的指令(或者是下一条要执行的指令)。

#

77e207ff cc              int     3

 

WindbgVS不同的地方是,windbg在启动程序后,执行main函数之前,就中断了,而VS却是直接执行,原因是VS是一个整合的平台,你可以先在源代码里面设置好断点,然后VS从源代码编译完程序后,启动程序之前自动就可以把断点设置好。而windbg只是一个调试器,所以它需要给程序员设置断点的机会,实际上所有的调试器的使用模式都是类似的。

 因为没有符号文件,不好调试,所以需要先加载符号文件。Windbg知道几个符号文件搜索路径(symbol path)――就是微软的公开符号文件服务器,如果你想查看你的程序在运行过程中使用了哪些windowsAPI和函数的话,可以使用它。执行下面的命令来使用这个文件服务器(不要忽略了前面的点号):

.symfix

上面的命令自动将symbol path设置为微软的公开符号文件服务器地址,如果你在微软内部混过,你会发现这个命令设置的路径有点不同,嘘……。

Sympath可以设置和查看symbol的路径,执行下面这个命令来查看最新的符号文件搜索路径:

.sympath

#

输出结果

#

Symbol search path is: SRV**http://msdl.microsoft.com/download/symbols

 

设置好符号文件搜索路径以后,接下来每次加载新的可执行(.exe或者.dll)文件,windbg都会先在这些路径里面搜索它的符号文件,但是对于已经加载了的可执行文件,例如ntdll.dllkernel32.dll,我们需要手动重新加载,使用下面的命令来加载:

.reload

#

输出结果

#

Reloading current modules

.....

 

这个时候,点击windbg菜单里面的“View”-“Call Stack”,就可以看到堆栈了。因为我们还用到了MS CRT里面的函数,即atoi,所以我们还需要VCRT的符号文件。幸运的是,VS自带了VCRT的私有符号文件,这样我们用下面的命令将这个符号文件的文件夹路径添加到windbg的符号文件搜索路径列表里面来,注意后面的加号,如果不写加号,就说明将搜索路径完全替换成新的:

.sympath+ C:\Windows\symbols\dll

#

输出结果

#

Symbol search path is: SRV**http://msdl.microsoft.com/download/symbols;C:\Windows\symbols\dll

执行下面的命令看一下加载的结果(注意前面没有点号):

lm

#

输出结果

#

start    end        module name

00b60000 00b7b000   nativedebug   (deferred)            

6fef0000 70014000   MSVCR90D   (private pdb symbols) D:\Debuggers\sym\msvcr90d.i386.pdb\EBEA784C96244F1E8F8D35E0391C898D1\msvcr90d.i386.pdb

76070000 76170000   kernel32   (deferred)            

77670000 776b4000   KERNELBASE   (deferred)            

77d80000 77f00000   ntdll      (pdb symbols)          D:\Debuggers\sym\wntdll.pdb\E06BEA155E9748BEA818E2D0DD2FED952\wntdll.pdb

上面的输出结果会在后文讲到,至于如何设置断点,以及在命令行里面查看堆栈,在后面讲――写文章还是蛮辛苦的。


本文转自 donjuan 博客园博客,原文链接: http://www.cnblogs.com/killmyday/archive/2010/02/22/1671511.html  ,如需转载请自行联系原作者

相关文章
|
机器学习/深度学习 数据可视化 数据处理
OpenAI Gym 高级教程——可解释性和可视化
OpenAI Gym 高级教程——可解释性和可视化
717 1
|
开发框架 小程序 JavaScript
UniApp框架适合哪些应用场景?
UniApp作为一款跨平台的移动应用开发框架,因其高效、灵活和强大的特性,适用于多种应用场景。
727 3
|
Cloud Native 持续交付 云计算
云原生技术的崛起与未来展望
本文探讨了云原生技术的核心概念、发展历程及其在现代IT架构中的关键作用。随着云计算的普及,云原生作为一种优化云应用构建和部署的方法,正逐渐成为企业数字化转型的重要推力。文章分析了容器化、微服务、持续集成/持续部署(CI/CD)等关键技术如何支撑起灵活、高效、可扩展的云原生架构,并讨论了面临的挑战与未来的发展趋势。
514 12
|
11月前
|
Web App开发 缓存 JavaScript
Android网络小说阅读器的实现
小说阅读Demo,。此Demo使用Jsoup解析HTML,实现小说数据抓取(数据源自网络),并包含自定义View、六章小说缓存等功能,但未实现下载。项目还包括屏幕适配、字体设置等,借助第三方框架完成优化。以下是主页、详情页、阅读页等界面展示。
328 0
|
存储 安全 Linux
句柄是什么?一文带你了解!
今天又学习了一个装X概念——句柄,看字面意思,感觉跟某种器具有关,但实际上,这个词可不是用来打造家居用品的。
2755 0
|
消息中间件 安全 Dubbo
java 的Remote 的使用
在Java中,"Remote" 的概念通常与Java RMI(Remote Method Invocation,远程方法调用)技术相关,它允许一个Java虚拟机(JVM)上的对象调用另一个JVM上对象的方法,就像调用本地对象一样。但是,值得注意的是,从Java 9开始,RMI已经被标记为不推荐使用(deprecated),并且在新版本的Java中可能不再得到支持和更新。尽管如此,了解RMI的基本概念仍然对理解分布式Java应用程序的设计和开发有所帮助。 ### RMI的基本步骤 1. **定义远程接口**: 远程接口是扩展了 `java.rmi.Remote` 接口的Java接口。它
1047 13
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
1216 3
|
Android开发
Android中SurfaceView的双缓冲机制和普通View叠加问题解决办法
本文介绍了 Android 平台上的 SurfaceView,这是一种高效的图形渲染控件,尤其适用于视频播放、游戏和图形动画等场景。文章详细解释了其双缓冲机制,该机制通过前后缓冲区交换来减少图像闪烁,提升视觉体验。然而,SurfaceView 与普通 View 叠加时可能存在 Z-Order 不一致、同步问题及混合渲染难题。文中提供了使用 TextureView、调整 Z-Order 和创建自定义组合控件等多种解决方案。
740 9
|
机器学习/深度学习 算法 数据处理
机器学习归一化特征编码(一)
特征缩放是机器学习预处理的关键步骤,它包括归一化和标准化。归一化通过最大最小值缩放,将数据转换到[0,1]区间,有助于梯度下降算法更快收敛,减少数值较大特征的影响。标准化则通过减去均值并除以标准差,确保数据具有零均值和单位方差,适用于关注数据分布情况的算法。例如,欧氏距离计算时,未归一化的特征可能导致模型偏向数值较大的特征。归一化能提升模型精度,尤其是当距离度量如欧式距离时。常见的实现方法有`MinMaxScaler`,它将每个特征值缩放到用户指定的范围,如[0,1]。而`StandardScaler`执行Z-Score标准化,数据分布符合标准正态分布。
|
存储 项目管理 开发工具