Dump文件数据存储格式(六)
八、线程信息列表流(ThreadInfoListStream
)
ThreadInfoListStream
包含了线程状态信息,在ThreadListStream
的后面就是ThreadInfoListStream
了。
ThreadListStream
如下:
0x720+0n3796=0x15F4
而ThreadInfoListStream
如下:
所以ThreadInfoListStream
紧挨着ThreadListStream
,大小为5068字节。数据如下:
ThreadInfoListStream
的数据由两个结构组成,一个是MINIDUMP_THREAD_INFO_LIST,另一个是MINIDUMP_THREAD_INFO。
MINIDUMP_THREAD_INFO_LIST包含数据大小的信息,相当于头部结构,如下:
typedef struct_MINIDUMP_THREAD_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG NumberOfEntries;
} MINIDUMP_THREAD_INFO_LIST,*PMINIDUMP_THREAD_INFO_LIST;
为什么".loadby sos clrjit"在有的dmp文件执行成功,在另外的dmp文件执行不成功?
在日常分析dmp文件工作中,我发现用".loadby sos clrjit"指令来加载sos扩展库在有的dmp文件成功有的不成功,都是报如下错误:
0:036> .loadby sos clrjit
The call to LoadLibrary(sos.dll) failed, Win32 error 0n2
"系统找不到指定的文件。"
Please check your debugger configuration and/or network access.
今日有得闲,于是就仔细分析下这个问题。
首先,我们知道".loadby sos clrjit"是根据clrjit的路径去加载sos,出现这个问题自然而然有两个可能性:
- 一是dmp文件里没有包含clrjit模块信息
- 二是clrjit路径问题
我们先看看是不是第一种情况,执行lm列出dmp文件包含的模块信息
没有问题的dmp如下:
0:000> lm
start end module name
01250000 0126f000 clrcompression (deferred)
...
692b0000 6933a000 clrjit (deferred)
....
有问题的dmp如下:
0:036> lm
start end module name
00230000 0023e000 mxml1 (deferred)
0:036> lm
start end module name
00230000 0023e000 mxml1 (deferred)
....
50100000 5017d000 clrjit (deferred)
......
可以看到都有clrjit模块信息。也就证明不是第一种情况,那就是第二种情况了,为了求证,要查看模块的详细信息了
没有问题的dmp如下:
0:000> lmDvmclrjit
Browse full module list
start end module name
692b0000 6933a000 clrjit (deferred)
Image path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
Image name: clrjit.dll
Browse all global symbols functions data
Timestamp: Tue Jul 7 06:46:31 2020 (5F03A9C7)
CheckSum: 00095382
ImageSize: 0008A000
File version: 4.8.4220.0
Product version: 4.0.30319.0
File flags: 8 (Mask 3F) Private
File OS: 4 Unknown Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
Information from resource tables:
CompanyName: Microsoft Corporation
ProductName: Microsoft® .NET Framework
InternalName: clrjit.dll
OriginalFilename: clrjit.dll
ProductVersion: 4.8.4220.0
FileVersion: 4.8.4220.0 built by: NET48REL1LAST_C
PrivateBuild: DDBLD507
FileDescription: Microsoft .NET Runtime Just-In-Time Compiler
LegalCopyright: © Microsoft Corporation. All rights reserved.
Comments: Flavor=Retail
有问题的dmp如下:
0:036> lmDvmclrjit
Browse full module list
start end module name
50100000 5017d000 clrjit (deferred)
Image path: clrjit.dll
Image name: clrjit.dll
Browse all global symbols functions data
Timestamp: Sat Apr 12 09:19:13 2014 (53489491)
CheckSum: 0007D3A1
ImageSize: 0007D000
File version: 4.0.30319.34209
Product version: 4.0.30319.34209
File flags: 8 (Mask 3F) Private
File OS: 4 Unknown Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
Information from resource tables:
CompanyName: Microsoft Corporation
ProductName: Microsoft® .NET Framework
InternalName: clrjit.dll
OriginalFilename: clrjit.dll
ProductVersion: 4.0.30319.34209
FileVersion: 4.0.30319.34209 built by: FX452RTMGDR
PrivateBuild: DDBLD354
FileDescription: Microsoft .NET Runtime Just-In-Time Compiler
LegalCopyright: © Microsoft Corporation. All rights reserved.
Comments: Flavor=Retail
我相信大家都看出问题之所在了吧。对,能执行成功的模块是全路径,而另外一个只有文件名,那么当然会报"系统找不到指定的文件。"的错误了。看来两种dmp文件抓取的类型标志肯定不一样。
有问题dmp文件标志如下
果然去掉了模块路径信息。下面是这个标志的说明:
MiniDumpFilterModulePaths
过滤内存信息中的模块路径,只保留模块名称。此选项可以保护用户的隐私比如用户名、重要的目录等,但可能阻止系统定位Image文件,应当谨慎应用在特殊环境。
该选项要求DbgHelp 5.1以上版本。
Dump文件数据存储格式(七)
九、模块列表流(ModuleListStream
)
ModuleListStream
流包含进程已加载模块信息。它紧跟随在ThreadInfoListStream
后面。ThreadInfoListStream信息如下:
0x15f4+0n5068=0x29c0
而ModuleListStream如下
可知ModuleListStream的RVA 为0x29c0,所以
ModuleListStream
紧挨着ThreadInfoListStream
,大小为26680字节。数据如下:
这些数据按如下结构组织在一起:
typedef struct_MINIDUMP_MODULE_LIST {
ULONG32 NumberOfModules;
MINIDUMP_MODULE Modules[0];
} MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST;
Visual studio从符号服务器搜索中排除模块
符号服务器访问是对比调试器。能够自动下载与当前系统匹配的所有程序(或者最终用户系统,如果我们想调试崩溃转储)的符号是非常方便的。但是有一个小问题:有些模块的符号在公共符号服务器上没有。但是调试器并不知道,因此每次我们启动调试会话时,调试器都会连接符号服务器并尝试下载模块的符号,但没有成功。因此,调试会话的启动时间会显著增加,特别是对于使用大量第三方组件的应用程序,这些组件的符号无法定义在Microsoft symbol server上。
幸运的是,有一个解决方案-我们可以告诉调试器,一些模块应该从符号服务器搜索中排除。
以下是操作方法:
1、升级symsrv.dll.
这个小DLL负责符号服务器的访问。净我们应该将它升级到一个更新的版本,这个版本是随Windows调试工具提供的。在我们下载并安装调试工具之后,symsrv.dll应该从其安装目录复制到<VSInstallDir>\Common7\IDE目录。
2、在symsrv.ini文件中指定排除列表。
此文件应创建在<VSInstallDir>\Common7\IDE目录(其中symsrv.dll位置)。
此文件的[exclusions]部分应包含要从符号服务器搜索中排除的文件列表。支持通配符,我更喜欢用*通配符替换所有文件扩展名,以确保排除所有可能的调试信息文件格式。
这是一个样品symsrv.ini要求调试器排除msxml4.dll和shlwapi.dll从搜索服务器符号:
;start of symsrv.ini [exclusions] msxml4.* shlwapi.* ;end of symsrv.ini
我的内核调试器无法连接
在windbg中,可以使用Ctrl+Alt+D查看调试器的内部信息流。在KD中,使用Ctrl+D和ENTER来切换输出。启用这个输出,我可以看到调试器无法从调试端口读取数据,而且它正在超时。错误“SYNCTARGET:Timeout.”清楚地表明调试主机无法与调试目标通信,尤其是在“Send Break-in”消息之后出现此错误时。
因为我在Hyper-V虚拟机上使用命名管道,所以我知道我没有坏电缆,尽管这是导致内核调试失败的常见原因。我还知道虚拟机的配置是正确的,我可以将调试器用于这台服务器上的其他虚拟机。问题很可能是在虚拟机中运行的操作系统。
通过检查设备管理器,我能够确认在虚拟机中运行的操作系统的配置有问题。bcdedit设置被配置为使用COM1,这将使COM1在操作系统中不可用,但是,COM1出现在设备管理器中。由于某些原因,调试器在启动时没有像配置的那样捕获COM1。
检查此服务器的bcd配置时,我发现bcd配置不正确。在普通Windows 7或Windows Server 2008 R2操作系统的bcd存储中,bcdedit的Windows引导加载程序部分具有继承设置。您可以使用命令“bcdedit/enum all”从提升的命令提示符查看系统上的此信息。通常,Windows引导加载程序继承{bootloadersettings},{bootloadersettings}继承{globalsettings},{globalsettings}继承{dbgsettings}。如果没有继承设置,则引导加载程序将无法读取调试器配置。
下面是损坏的虚拟机的bcd设置。您可以看到所有正常继承的设置都丢失了。
C:\Windows\system32>bcdedit /enum all
Windows Boot Manager--------------------identifier {bootmgr}
device partition=C:
path \bootmgr
description Windows Boot Manager
locale en-US
default {current}
displayorder {current}
timeout30Windows Boot Loader-------------------identifier {current}
device partition=C:
path \Windows\system32\winload.exe
description Windows Server2008R2 Standard (recovered)
locale en-US
osdevice partition=C:
systemroot \Windows
resumeobject {2ec5363f-2a92-11e1-bbe4-806e6f6e6963}
usefirmwarepcisettings No
debug Yes
Resume from Hibernate---------------------identifier {2ec5363f-2a92-11e1-bbe4-806e6f6e6963}
device partition=C:
path \Windows\system32\winresume.exe
description Windows Server2008R2 Standard (recovered)
locale en-US
inherit {resumeloadersettings}
filedevice partition=C:
filepath \hiberfil.sys
debugoptionenabled Yes
Windows Memory Tester---------------------identifier {memdiag}
device partition=C:
path \boot\memtest.exe
description Windows Memory Diagnostic
locale en-US
Debugger Settings-----------------identifier {dbgsettings}
debugtype Serial
debugport1baudrate115200