zoukankan      html  css  js  c++  java
  • 你生成的转储文件有问题吗?

    如果你还不清楚什么是转储文件,不知道什么时候需要转储文件,请参考转储文件系列文章的第一篇 —— 转储文件知多少

    前言

    细心的小伙伴可能注意到了,我在上一篇介绍抓取转储文件的工具的文章 —— 你需要知道的 N 种抓取 dump 的工具 中提到了:

    如果用 64 位的 windbg 附加到 32 位目标进程后,直接执行.dump 命令生成的转储文件会 “有问题”。

    经常抓 dump 的小伙伴很可能遇到过这个问题。具体是什么问题呢?我们一起看看吧。

    问题

    还记得 N 年前,我用任务管理器抓取 32 位进程的转储文件后,使用 windbg 分析时,傻眼了!全是wow64 相关的栈帧,一个我关心的栈帧都没有。大概就像下图这样。(配图是我新截的,第一次分析时没保存截图)

    有问题的调用栈
    有问题的调用栈

    我所指的 “有问题”,就是指的这个问题。你知道怎么解决吗?

    小知识

    x64 系统中,如果我们用系统自带的任务管理器为目标进程创建转储文件,不论目标进程是 32 位,还是 64 位,任务管理器将始终创建 64 位的转储文件。为 32 位进程创建的转储文件会包含 WoW64 子系统的信息,我们用 windbg 分析的时候,可能会遇到上文中提到的问题。下面是同一个 32 位进程的转储文件的调用栈截图。

    第一张截图是直接使用 k 命令得到的结果。可以看到很诡异。

    有问题的调用栈
    有问题的调用栈

    第二张截图是使用 .load 命令加载 wow64exts 扩展后,使用其 !sw 命令切换模式后,再使用 k 命令得到的结果。可以看到,结果很完美。

    正常的调用栈
    正常的调用栈

    对,wow64exts 是我们的解决之道。如果你像曾经的我一样,不知道使用 wow64exts!sw 命令切换模式进行调试的话,是不是就 “有问题” 了?每次都手动加载 wow64exts,然后用 !sw 命令切换模式岂不是很麻烦?我们可以在加载 wow64exts 模块后,直接使用 !wow64exts.k 查看调用栈,这里就不截图了。还有更省心的办法吗?如果用 k 命令能直接看到想看的调用栈岂不是更好?有,不过我们抓取转储文件的时候需要有讲究。

    {% note info%}

    2020-01-11 更新:

    群里大佬提醒,也可以使用 .effmach 命令来查看或切换调试器使用的处理器模式。我们可以使用 .effmach x86 来强制切换到 x86 模式下,然后再执行 k 命令。效果和 .load wow64exts; !sw; k 一样。 大家可以试一下。关于 .effmach 的帮助,请参考微软官方文档,或者直接参考下面的截图。

    截自微软官方文档
    截自微软官方文档

    {%endnote%}

    procdump

    x64 位系统下,procdump 默认对 32 进程创建 32 位的转储文件。这样做的好处是,生成的转储文件中不包含 WOW64 子系统的相关信息。我们用 windbg 分析转储文件时,可以直接使用 k 系列命令查看调用栈,不需要借助 wow64exts 的帮助了,这样调试起来更简单直接。

    为了更直观的感受 procdump 的好处,我专门录制了两段视频。第一段是使用 windbg 分析 procdump32 位进程生成的转储文件,第二段是使用 windbg 分析任务管理器为同一个 32 位进程生成的转储文件。

    调试 procdump 生成的 dump
    调试 procdump 生成的 dump

    调试任务管理生成的 dump
    调试任务管理生成的 dump

    相信大家可以直观的感受到,调试 procdump 生成的转储文件的时候,非常直接。调试任务管理器生成的转储文件的时候,需要借助 wow64exts 的帮助才可以看到正常的调用栈。

    {% note info%}

    说明:

    使用 procdump 默认选项生成的转储文件中不包含 WoW64 相关的信息。如果需要调试涉及 WoW64 子系统的故障,可以在运行 procdump 的时候加上 -64 选项,这样为 32 位进程生成的转储文件就包含 WoW64 子系统的信息了。我们绝大多数情况下不会调试 WoW64子系统相关的故障,所以就使用默认选项吧。

    {%endnote%}

    总结

    • windbg 中,使用 ! 来调用扩展中的命令。

    • 使用 procdump 默认选项为 32 位进程生成的转储文件不包含 WoW64 信息,绝大多数情况下更便于我们调试。

    • 如果需要,在使用 procdump 抓取转储文件时,我们可以使用 -64 选项为 32 位进程抓取包含 Wow64 相关信息的转储文件。

    • 调试包含 WoW64 信息的转储文件,可以使用 .load 命令加载 wow64exts模块,并调用其 !sw 命令切换模式,然后就可以正常调试了。

    • 直接使用 .effmach 命令可以显示当前的处理器模式,.effmach x86 | x64 可以显示切换模式。

    参考资料

  • 相关阅读:
    maven 配置报错 JAVA_HOME not found in your environment
    file控件change事件触发问题
    自己动手写easyui的checkbox
    json数组传递到后台controller
    yii2 添加模块过程
    YII框架中php入口文件隐藏
    YII框架路由和URL生成
    Node.js脚本杀掉占用端口的进程
    Java单例模式的6种写法
    HTTPS时代已来,你做好准备了吗?
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/12253558.html
Copyright © 2011-2022 走看看