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

前言

我在 你需要知道的 N 种抓取 dump 的工具 的工具 这篇文章里,向大家介绍了几款可以抓取转储文件的工具及其简单用法。不知道大家是否还记得,以管理员权限运行 procdump -i 可以注册 procdump 为事后调试器。大家是否了解其实现原理?今天让我们一起揭开其神秘面纱。

约定

JIT DebuggerJust In Time DebuggerJIT 调试器Postmortem Debugger事后调试器,指的是同一个概念 —— 事后调试器。如果把 Debugger 换成 Debugging,表示事后调试。我有时候会说 JIT 调试器,有时候会说事后调试器,希望大家不要被我混乱的用词搞晕。

原理探究

运行 process monitor,开启监视。然后以管理员权限执行 procdump.exe -i,成功后,停止监视。为了方便大家,我特意录制了整个过程,感兴趣的小伙伴可以点开看看,不过我建议你亲自动手实战一番,毕竟 纸上来的终觉浅, 绝知此事要躬行

探究 procdump 安装为 JIT 调试器的过程

如果你没看视频,可以直接参考我过滤后的结果截图(保留ResultSuccess注册表 事件,排除非注册表相关事件):

我用黄色和红色高亮了 procdump 操作的注册表项。你能从图中得出什么结论呢?

  • procdump 会同时写 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebugHKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug 注册表项。

    相信有开发经验的小伙伴儿知道,在64 位系统下,部分注册表项有两套:一套是供 64 位进程使用的(黄色高亮部分),一套是供 32 位进程使用的(红色高亮部分,带 Wow6432Node)。

  • 如果 AeDebug下的 Auto 子项和 Debugger 子项有值,procdump 会先备份,再修改。(执行 procdump -u 的时候会恢复系统原有设置)

  • AutoDebugger 的数据类型都是 REG_SZ。(虽然我们看到 Auto 的值是 1

  • 我猜,32 位进程崩溃的时候,会使用带 Wow6432Node 的注册表项,64 位进程崩溃的时候,会使用不带 Wow6432Node 的注册表项。真的是这样吗?你知道怎么验证吗?相信聪明的你一定能想出验证办法。

其实,以上结论在 procdump -i 的输出结果中已经给出提示了(除了备份操作)。注意看下图中的黄色和红色高亮的部分。

procdump-i

温馨提示:

某些杀毒软件可能会对此注册表项有保护,如果设置失败,请检查是否是杀毒软件导致的。

至此,我们知道 procdump 是通过设置 AeDebug下的 AutoDebugger 子项实现的 JIT Debugging。那么这两项都有什么用呢?

AeDebug 探究

使用 google 搜索 AeDebug,搜到了微软的官方说明[1] ,有兴趣的小伙伴一定要读一读,有很多有价值的信息。

  • Auto 项:指定是否向用户显示错误提示框,如果值为 "0",则显示提示框。为 "1" 则不显示提示框,直接附加注册的事后调试器到目标进程中。

  • Debugger 项:指定事后调试器的路径,及传递给事后调试器的参数。我们发现 procdump -i 设置的参数是 -accepteula -j "E:\dumps" %ld %ld %p。其中:

    • -accepteula 表示接受用户协议。

    • -j 表示参数中有指向 JIT_DEBUG_INFO 的指针(父进程传递了 %p 对应的内容)。

    • "E:\dumps" 表示转储文件保存的路径(如果运行 procdump -i 的时候,没有指定转储文件的保存路径,默认会取当前路径 )。

    • 第一个 %ld 表示目标进程的进程 ID

    • 第二个 %ld 表示事件句柄。这个事件句柄是 WER 复制到事后调试器中的。如果事后调试器激活该事件(通过 SetEvent())后,WER 将继续目标进程的执行,而无需等待事后调试器终止。如果事后调试器在没有激活该事件的情况下终止,WER 将继续收集关于目标进程的信息。

    • %p 指向目标进程空间中的 JIT_DEBUG_INFO 结构指针。包含了异常的来源和与异常相关的上下文信息。

如果转储文件中保存了 JIT_DEBUG_INFO,使用 windbg 调试时,可以通过 .jdinfo address 来查看异常发生时的信息。例如,使用 windbg 打开 procdump 保存的转储文件的时候,应该可以看到如下提示。

procdump 在转储文件中添加的注释

我们可以根据提示,输入.jdinfo 0x1afd59e0000 来查看异常来源及上下文信息。

jdinfo 结果

说明:

在运行 procdump -i 的时候,如果没有指定转储选项,会默认使用 -mm 选项。该选项只包含 Process, Thread, Module, Handle and Address Space info. 信息,不会包含 %p 对应的内存数据。如果我们在调试 使用 -mm 选项保存的转储文件的时候执行 .jdinfo address,会得到如下错误:Unable to process JIT_DEBUG_INFO, Win32 error 0n30

我们可以简单的通过指定 -ma-mp来生成包含内存数据的转储文件,这样我们在调试器里执行 .jdinfo address的时候就不会报错了。

据我观察,对于 procdump 来说 -j%p 选项需要同时传递,缺一不可。

排除进程

如果我们真的不想让某些进程出现未处理异常的时候中断到 JIT 调试器中,有没有办法呢?从 vista 开始,我们可以显示排除某些进程,不让这些进程在出现未处理异常的时候中断到 JIT 调试器中。对应的注册表项如下:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\AutoExclusionList

下面是我机器上的该注册表项的值:

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\AutoExclusionList]
"DWM.exe"=dword:00000001
"demo.exe"=dword:00000001

上面的 demo.exe 是我为了测试手动添加的,而 DWM.exe 是系统添加的。windows 为什么要默认把 DWM.exe 添加到排除列表呢?我也不太清楚,不过我在 Excluding an Application from Automatic Debugging[2] 看到这样一句话:

By default, the Desktop Window Manager (Dwm.exe) is excluded from automatic debugging because otherwise a system deadlock can occur if Dwm.exe stops responding (the user cannot see the interface displayed by the debugger because Dwm.exe isn't responding, and Dwm.exe cannot terminate because it is held by the debugger).

我想这就是 DWM.exe 会被排除的原因吧。

如果想通过代码的形式实现,除了直接操作注册表外,还可以通过 WerAddExcludedApplication() 来实现,对应的,可以通过 WerRemoveExcludedApplication() 来删除 。这两个函数的原型摘录如下:

HRESULT WerAddExcludedApplication(PCWSTR pwzExeName,BOOL   bAllUsers
);HRESULT WerRemoveExcludedApplication(PCWSTR pwzExeName,BOOL   bAllUsers
);

第一个参数 pwzExeName 表示要排除的程序,不要带路径,只传递程序名称即可。比如,demo.exe

第二个参数 bAllUsers 如果是 FALSE 的话,表示仅对当前用户有效,其它用户不受影响,修改的是 HKCUHKEY_CURRENT_USER)下对应的注册表项。如果为 TRUE 的话,表示对所有用户都生效,修改的是 HKLMHKEY_LOCAL_MACHINE)下对应的注册表项,为 TRUE 的时候,需要有管理员权限。

注意:

如果你手动调用代码操作注册表的话,务必注意 64 位系统下的注册表重定向问题。相信一定有小伙伴儿和我一样踩过这个坑。

JIT 调试的运作机制

整个运作机制,在张银奎张老师的《软件调试》(第一版)第 12 章:未处理异常和 JIT 调试 中做了非常非常详细的介绍。我就不摘录了,感兴趣的小伙伴一定要好好多读几遍。

AeDebug 中的 Ae 是什么意思?

AeDebug中的 Debug 很好理解,就是调试的意思。那 Ae 代表什么意义呢?有人说 AeDebugAuto Exception Debug 的缩写,听上去挺有道理的。偶然的机会,google 到了 Ramond Chen写的一篇文章 —— What does the “Ae” stand for in AeDebug?[3]。根据他的说法,Ae 表示 Application Error 的意思。我把原文截取如下,方便大家阅读。

Raymond-Chen-explain-AE

知道 AeDebug 是什么单词的缩写有助于帮助大家记忆,但没必要纠结。

总结

  • 一般情况下,修改 HKLM 下的注册表项需要管理员权限。

  • 注册为 JIT 调试器,需要管理员权限,因为需要写 HKLM 下的子键。

  • procdump 可以通过 -i 选项注册为事后调试器,另外 windbg也可以通过 -I 选项注册为事后调试器。

  • AeDebug 注册表项是 JIT 调试的关键,该注册项在 64 位系统下有对 32 位进程和 64 位进程分别有对应的注册表项。其中,带 Wow6432Node 的注册表项是给 32 位目标进程使用的。

  • 64位系统下,除了AeDebug有两套,还有很多其它注册表项也有两套。

  • 如果确实不希望自己的进程在出现未处理异常时中断到 JIT 调试器中,可以设置注册表进行排除(Vista 及之后的操作系统才支持)。

参考资料

  • 《windows sysinternals 实战指南》

  • 《软件调试》(第一版)

  • Microsoft Document : Enabling Postmortem Debugging[4]

  • Raymond-Chen : What does the “Ae” stand for in AeDebug?[5]

  • Configuring Automatic Debugging[6]

  • WerAddExcludedApplication[7]

  • WerRemoveExcludedApplication[8]

References:

[1]

微软的官方说明: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/enabling-postmortem-debugging

[2]

Excluding an Application from Automatic Debugging: https://docs.microsoft.com/en-us/windows/win32/debug/configuring-automatic-debugging#excluding-an-application-from-automatic-debugging

[3]

What does the “Ae” stand for in AeDebug?: https://devblogs.microsoft.com/oldnewthing/20181017-00/?p=99995

[4]

Microsoft Document : Enabling Postmortem Debugging: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/enabling-postmortem-debugging

[5]

Raymond-Chen : What does the “Ae” stand for in AeDebug?: https://devblogs.microsoft.com/oldnewthing/20181017-00/?p=99995

[6]

Configuring Automatic Debugging: https://docs.microsoft.com/en-us/windows/win32/debug/configuring-automatic-debugging#configuring-automatic-debugging-for-application-crashes

[7]

WerAddExcludedApplication: https://docs.microsoft.com/en-us/windows/win32/api/werapi/nf-werapi-weraddexcludedapplication

[8]

WerRemoveExcludedApplication: https://docs.microsoft.com/en-us/windows/win32/api/werapi/nf-werapi-werremoveexcludedapplication

猜你喜欢:

转储文件系列:

转储文件知多少

你需要知道的 N 种抓取 dump 的工具

你生成的转储文件有问题吗?

调试系列:

调试实战——你知道怎么使用DebugView查看调试信息吗?

调试实战——程序CPU占用率飙升,你知道如何快速定位吗?

调试实战——崩溃在ComFriendlyWaitMtaThreadProc

调试实战——使用windbg调试崩溃在ole32!CStdMarshal::DisconnectSrvIPIDs

调试实战——调试PInvoke导致的内存破坏

调试实战——调试excel启动时死锁

调试实战——调试DLL卸载时的死锁

调试实战——调试TerminateThread导致的死锁

排错系列:

排错实战——VS清空最近打开的工程记录

排错实战——拯救加载调试符号失败的IDA

排错实战——你知道拖动窗口时只显示虚框怎么设置吗?

排错实战——解决Tekla通过.tsep安装插件失败的问题

排错实战——使用process explorer替换任务管理器

排错实战——通过对比分析sysinternals事件修复程序功能异常

欢迎留言交流

你需要了解的 JIT Debugging相关推荐

  1. To handle Unhandled Exception

    为了捕捉那些我们没有try{-}catch{-}到的异常(Unhandled Exception),且有一个UI给用户予以友好的提示,我们需要一个机制去处理这些异常.而且,如果我们在任何可能发生异常的 ...

  2. [译] Cilium:BPF 和 XDP 参考指南(2021)

    Cilium:BPF和XDP参考指南_RToax-CSDN博客Table of ContentsBPF体系结构指令系统辅助功能地图对象固定尾叫BPF到BPF呼叫准时制硬化减负工具链开发环境虚拟机本文档 ...

  3. 【Bash百宝箱】gdb命令

    gdb即The GNU Debugger,是一种调试工具,使用gdb可以查看一个程序在运行时或crash时的内部信息,主要有以下四种功能. a 启动程序,按自定义的方式运行程序. b 在特定条件下(即 ...

  4. asp.net确认对话框_在ASP.NET或Trace.Fail中防止服务器端对话框被认为有害

    asp.net确认对话框 Dialogs on the server-side? What is this nonsense of which you speak? Are you insane? S ...

  5. Linux bpf 3.2、BPF and XDP Reference Guide

    开源软件Cilium深度的使用了BPF来做网络安全,它的文档中使用了一个章节专门的来介绍BPF的原理和使用. 参考原文:BPF and XDP Reference Guide 注意:本文档部分针对的是 ...

  6. pytorch JIT浅解析

    概要   Torch Script中的核心数据结构是ScriptModule. 它是Torch的nn.Module的类似物,代表整个模型作为子模块树. 与普通模块一样,ScriptModule中的每个 ...

  7. JVM实用参数(二)参数分类和即时(JIT)编译器诊断

    作者: PATRICK PESCHLOW     原文地址    译者:赵峰 校对:许巧辉 在这个系列的第二部分,我来介绍一下HotSpot JVM提供的不同类别的参数.我同样会讨论一些关于JIT编译 ...

  8. 在 .NET Core 3.0 中实现 JIT 编译的 JSON 序列化,及一些心得与随想

    源码:https://github.com/Martin1994/JsonJitSerializer NuGet:https://www.nuget.org/packages/MartinCl2.Te ...

  9. JIT Code Generation代码生成

    JIT Code Generation代码生成 一.表达式编译 代码生成(Code Generation)技术广泛应用于现代的数据系统中.代码生成是将用户输入的表达式.查询.存储过程等现场编译成二进制 ...

最新文章

  1. JavaScript History对象
  2. Weblogic 集群部署说明 --转
  3. a eraser eraser还是an_eraser前面用a还是an
  4. SpringMvc的服务器端跳转和客户端跳转
  5. 超硬核!我统计了BAT笔试面试出现频率最高的五道题,学会了总能碰到一道
  6. 图像处理基础系列-01
  7. azure夜校培训第5场 3月15日18:00---存储
  8. Codeforces Round #666 (Div. 2)C - Multiples of Length(错位相减)
  9. codesys编程_CODESYS楼宇自动化应用案例:化学系教学楼智能排气系统
  10. 51Nod-1640-天气晴朗的魔法(最小生成树)
  11. python 做界面时如何使图片保持透明背景_Python利用matplotlib生成图片背景及图例透明的效果...
  12. STM32+L298N+PWM可调速小车(四驱)
  13. Word 2003 出现 向程序发送命令时出现问题 的 解决方案
  14. jquery获取元素索引值index()
  15. 国科大首期“一生一芯”计划初见成效——本科生带着自己设计的处理器芯片毕业
  16. android全景图
  17. /var/ha/soc/hagsdsocket./cdrom/rootpre.sh[338]: /usr/lpp/ssp/bin/spget_syspar
  18. windows installer正准备安装
  19. Bybit USDT永续合约交易测评 | TokenInsight
  20. ESP32-S2 SGM58031-热敏电阻电压转温度

热门文章

  1. andriod之应用内置浏览器 webview
  2. 告别 ROR windows 部署的噩梦-在 windows 上面 使用 Apache 部署 Ruby On Rails
  3. html广告条效果,css3炫酷网站banner广告动画特效
  4. Kinect开发笔记之五使用PowerShell控制Kinect
  5. YouTube键盘快捷键:速查表
  6. oracle的本地安装和PUTTY+XMING远程连接安装和oracle翻页功能
  7. JavaScript对象、JSON对象、JSON字符串的区别
  8. 二维数组foreach嵌套遍历,判断连续3天以上的算有效数据
  9. 让未备案的网站先飙起来
  10. [IOS地图开发系类]2、位置解码CLGeocoder