常用的 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 清除当前屏幕显示
  • ~0s 切换到 UI 线程
  • ~ 打印出当前问题进程的所有线程
  • bp 添加断点
  • bc 清除断点
  • bl 列出断点
  • ba 设置数据断点

也可以在 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,从中选择即将崩溃的进程

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

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

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

上面信息我们看到程序发生了 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 会自动跳转到源码对应的位置。

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

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

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

windbg 学习的更多相关文章

  1. windbg学习----.process

    .process 命令指定要用作进程上下文的进程(Set Process Context) .process显示当前进程的EPROCESS,这里显示当前进程为test.exe kd> .proc ...

  2. windbg学习进阶之——windbg环境变量配置

    接触性能调优以来一直想学下windbg分析dump,每次看老师几个命令就能找到很底层的问题原因那简直就是羡慕加崇拜啊~但是这接近一年了,愣是没啥进展呢,主要就是在今天整理的这部分卡住了...这理由找的 ...

  3. Windbg学习使用

    WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件. 1. WinDbg介绍:    Debuggin ...

  4. windbg学习进阶之——windbg字段名及其意义

    要使用windbg分析dump必须加载正确的符号,可以通过设置Symbols File Path为"D:/Symbols;SRV*D:/Symbols*http://msdl.microso ...

  5. windbg学习进阶之——dump分析常用命令收集

    #重要说明 (1) windbg命令分为标准命令,元命令和扩展命令. 标准命令提供最基本的调试功能,不区分大小写.如:bp  g  dt  dv  k等 元命令提供标准命令没有提供的功能,也内建在调试 ...

  6. Windbg学习笔记

    下载winsdksetup.exe ,双击,选择Debugging Tools for Windows安装. 64位系统抓64位进程dump,用64位windbg来分析.64位系统抓32位进程dump ...

  7. 很详细全部的WinDbg学习资料

    [ 分类 ]- windbg - hgy413的专栏(﹎゛Never Give Up Your Dream ..ヽ..) - CSDN博客 .

  8. windbg学习---.browse打开一个新的command 窗口

    .browse r eax .browse <command>将会显示新的命令浏览窗口和运行给出的命令

  9. windbg学习.formats--转换成各种进制

    .formats 命令在当前线程和进程上下文下对一个表达式或符号进行求值,并以多种数字格式显示出来. 0:002> .formats 000ad3a0 Evaluate expression: ...

  10. windbg学习---!thread和.thread

    !thread扩展显示目标系统中线程包括ETHREAD块在内的摘要信息.该命令只能在内核模式调试下使用 !thread [-p] [-t] [Address [Flags]] -p 显示拥有该线程的进 ...

随机推荐

  1. [转帖]为什么需要在脚本文件的开头加上#!/ bin / bash?

    本文翻译自:Why do you need to put #!/bin/bash at the beginning of a script file? I have made Bash scripts ...

  2. Oracle session的sid与serial的简单学习

    Oracle session的sid与serial的简单学习 ITPUB vage的说法 这样说吧,Oracle允许的会话数(或者说连接数)是固定的,比如是3000个.假设每个会话要占1K字节,哪一共 ...

  3. [转帖]tidb的分区表

    https://docs.pingcap.com/zh/tidb/v6.5/partitioned-table 分区类型 本节介绍 TiDB 中的分区类型.当前支持的类型包括 Range 分区.Ran ...

  4. 关于decimal非常浅显的学习与整理

    关于decimal非常浅显的学习与整理 背景知识 整数,小数,浮点,定点 整数(Integer)是没有小数部分的数值,可以是正数.负数或零.在计算机中,整数通常以二进制形式存储. 小数(Decimal ...

  5. [转帖]a.out、coff、elf三种文件格式

    补充:a.out早期并不是elf格式的,而是unix下另一种可执行格式,新的a.out是 本文讨论了 UNIX/LINUX 平台下三种主要的可执行文件格式:a.out(assembler and li ...

  6. Promise的异常穿透和中断Promise的链式请求

    1.Promise的异常穿透 1==>当你使用Promise的then,进行链式调用的时候,可以在最后指定失败的回调 2==>前面任何操作出现了异常,都会传递到最后失败的回调中进行处理: ...

  7. 【学到一个小技巧】context.WithValue 中的 key 可以是个空对象

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 从 netpoll 库看到这段代码: type connk ...

  8. 基于 hugging face 预训练模型的实体识别智能标注方案:生成doccano要求json格式

    强烈推荐:数据标注平台doccano----简介.安装.使用.踩坑记录_汀.的博客-CSDN博客_doccano huggingface官网 参考:数据标注平台doccano----简介.安装.使用. ...

  9. C++ CryptoPP使用AES加解密

    Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库.它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密.非对称加密.哈希函数.消息认证码 (MAC).数字签名等.C ...

  10. 爆了!Sealos 三天支持 1000 个帕鲁私服

    Sealos 的帕鲁私服模板从第一天发布之后就起了 100 多个私服,第二天直接上到 500 多个,第三天直接上千,还在加速增长中.来讲讲我们只用一个晚上怎么做到上线一个专属可用区的,还有一些帕鲁实践 ...