windbg 学习

常用的 windbg 命令

  • .ecxr 用来切换到异常发生时的上下文,主要用在分析静态 dump 文件的时候。当我们使用 .reload 命令去强制加载库的 pdb 文件后,需要执行 .ecxr 命令,重新切换到异常上下文
  • kn/kv/kp 用来查看当前线程的函数调用堆栈。如果要查看当前进程的所有线程的函数调用堆栈,可以使用 ~*kn 命令
  • lm 用来查看库的信息,比如库的路径、时间戳、库的加载地址等。一般使用模糊匹配的模式,比如:lm vm codec*
  • .reload 用来加载pdb文件,一般用来强制加载某个 pdb 文件,比如:.reload  /f  kdcodec.dll。注意这个命令中的名称要使用完整的文件名称
  • !anallyze -v 输出当前异常的详细分析信息
  • g 在中断模式下,跳过中断,继续运行,主要用于实时调试的场景
  • bp/bl/bc 添加、查看、删除断点,主要用于实时调试的场景
  • ~ns 切换到 n 号线程中,在 GUI 应用程序中,UI 线程为 0 号线程,是 GUI 程序的主线程
  • .dump 创建一个用户模式或内核模式的转储文件,比如 .dump /ma C:1125.dmp
  • r 显示当前线程所有寄存器的值
  • .cls 清除当前屏幕显示

也可以在 windbg 的 help 选项卡下选择 index 查看命令


程序崩溃的情况有时是程序访问了 0x00000000 内存地址。

在 Windows 系统中小于 64 kb 的内存是禁止访问的。这块禁止访问的内存地址,是 Windows 系统故意预留的一块小地址内存区域,是为了方便程序员定位问题使用的。一旦访问到该内存区就会触发内存访问违例,

系统就会将进程强制结束掉。

在 Windows 核心编程一书中内存管理的章节,有专门的描述,

空指针赋值分区

这一分区是进程地址空间中从 0x00000000 到 0x0000FFFF 的闭区间,保留该分区的目的是为了帮助程序员捕获对空指针的赋值。如果进程中的线程试图读取或写入位于这一分区内的内存地址,就会引发访问违规。

C/C++ 程序中,错误检查经常执行的不够彻底。例如,下面的代码就没有执行错误检查:

int* pnSomeInteger = (int*)malloc(sizeof(int));
*pnSomeInteger = 5;

如果 malloc 无法分配足够的内存,那么它会返回 NULL。但是,前面的代码并没有检查这种可能性--------它想当然地认为分配一定会成功并访问位于地址 0x00000000 处的内存。因为地址空间中的这一分区是禁止访问的。

所以会引发内存访问违规并导致进程被终止。这一特性可以帮助开发人员发现应用程序中的缺陷。值得注意的是,没有任何办法可以让我们分配到位于这一地址区间的虚拟内存,即便是使用 win32 api 也不例外。


 调试步骤:

假设现在我们有一段崩溃代码,

// 添加的一段测试代码
SHELLEXECUTEINFO *pShExeInfo = NULL;
int nVal = pShExeInfo->cbSize; // 通过空指针访问结构体成员,导致崩溃

  

在编译后,运行 .exe 可执行文件,打开 windbg,在 File 选项卡中选择 Attach to a process,从中选择即将崩溃的进程

windbg 学习

 点 OK 后,完成 Attach 操作,windbg 会自动中断,这时在 windbg 的命令行输入 g,表示继续运行

windbg 学习

 我们让程序崩溃后,windbg 也会自动捕获到异常,这时输入 kn 查看崩溃时的函数调用堆栈。

对于非动态调试的,即加载 dmp 文件的,需要输入 .ecxr 定位到崩溃位置

windbg 学习

上面信息我们看到程序发生了 Access violation 内存访问违例的异常,并且可以看到崩溃时的 eax,ebx 等其他寄存器中的值,并能看到发生崩溃的那条汇编指令。

在执行 kn 之后,可以看到代码崩溃的所在行,对于看不见具体函数信息,我们需要手动加载 pdb 文件

输入 lm vm Test_windbg_one* 查看文件的编译时间,通过编译时间找到对应的 pdb 文件,找到之后在 File 选项卡中 Symbol File Path,里面输入 pdb 文件的绝对地址,再 reload,windbg 就会去自动加载 pdb 文件了,如果没有自动加载,可以在命令行输入 .reload /f Test_windbg_one.exe 来强制加载。

如果我们想要在 windbg 中查看代码崩溃为止,可以在 File 选项卡中选择 Source Search Path,在其中输入源代码所在的绝对路径,点击 ok 后,windbg 会自动跳转到源码对应的位置。

windbg 学习

 我们可以点击函数调用堆栈中每行最前面的数字超链接,就可以自动切换到对应的函数中,但是对于系统库中函数调用的堆栈模式是没有源码,所以我们一般只能看到应用程序模块的源码

有时我们在排查异常时,需要查看函数调用堆栈中某个函数中的变量值,可以点击函数调用堆栈中每一行前面的数字超链接

如果需要将 dmp 文件保存到本地,输入 .dump /ma D:Pathcrash.dmp 来保存到 crash.dmp 文件中

 

原文链接: https://www.cnblogs.com/strive-sun/p/16377822.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    windbg 学习

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/404495

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月25日 下午4:36
下一篇 2023年4月25日 下午4:36

相关推荐