简介

调试应用程序时,调试器必须加载可执行模块的符号,以便能够显示有意义的调用堆栈、当前源代码行、变量值等。如果您曾经调试过在另一个系统上创建的小型转储,那么您已经知道除了符号之外,调试器还需要访问创建转储时由应用程序加载的相同版本的模块。如果调试器找不到与模块完全相同的版本(即匹配的模块),则无法加载模块的符号,从而严重限制了成功调试的可能性。在本文中,我们将讨论VS.NET和WinDbg调试器用来识别和定位匹配模块的规则。我们将看到如何告诉调试器在哪里查找匹配的模块。我们还将讨论无法找到匹配模块的情况,并尝试找到解决方法。

模块匹配

调试器如何决定模块是否匹配?他们如何知道需要什么版本的模块?让我们看看Minidump里面。每个小型转储都包含转储进程加载的模块列表。此列表存储为小型转储模块结构的数组(如DbgHelp文档中所述)。此结构声明如下:

typedef struct _MINIDUMP_MODULE {
ULONG64 BaseOfImage;
ULONG32 SizeOfImage;
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
VS_FIXEDFILEINFO VersionInfo;
MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
ULONG64 Reserved0; // Reserved for future use.
ULONG64 Reserved1; // Reserved for future use.
} MINIDUMP_MODULE, *PMINIDUMP_MODULE;

下表描述了结构的成员:

Member Description
BaseOfImage Base address of the module in memory.
SizeOfImage Size of the module (in bytes) equal to the value stored in the module’s optional header (IMAGE_OPTIONAL_HEADER.SizeOfImage).
CheckSum Checksum of the module, equal to the value stored in the module’s optional header (IMAGE_OPTIONAL_HEADER.CheckSum). This value can be 0, unless the module was linked with /release option.
TimeDateStamp Time/date stamp of the module, equal to the value in the module’s file header (IMAGE_FILE_HEADER.TimeDateStamp).
ModuleNameRva This is a relative address (from the beginning of the minidump) of MINIDUMP_STRING structure that contains the file name (and path) of the module.
VersionInfo This structure contains the version information of the module (including file version and product version). More information about the contents of this structure can be found in Platform SDK documentation.
CvRecord This is a structure that contains the so-called debug record. You can find more information about its contents in this article (see CV_INFO_PDB20 and CV_INFO_PDB70 structures). This structure is present only if debug information for the module is stored in .PDB file.
MiscRecord This structure also contains the debug record, but in another format (IMAGE_DEBUG_MISC). This structure is present only if debug information for the module is stored in .DBG file.

如果要显示小型转储的模块信息,可以使用小型转储视图工具。例如,以下是kernel32.dll的模块信息:

Module:                C:\WINNT\system32\KERNEL32.DLL
Address: 7c4e0000
Size: 000b9000
CheckSum: 000bdbb3
TimeDateStamp: 3ef274dc
File version: 5.0.2195.6688
Product version: 5.0.2195.6688
MISC record: Available

如我们所见,小型转储允许非常精确地标识模块。我们可以确定模块的文件和产品版本,它在文件系统中的位置,并有足够的信息来加载匹配的调试信息文件。但是调试器真的使用所有这些信息来识别模块吗?结果是,它们没有。VS.NET调试器只使用以下数据来检查模块是否匹配:

  • File name (MINIDUMP_MODULE.ModuleNameRva)
  • Module size (MINIDUMP_MODULE.SizeOfImage)
  • Module timestamp (MINIDUMP_MODULE.TimeDateStamp)

WinDbg更精确一些,因为它还使用模块的校验和。以下是WinDbg用来检查模块是否匹配的数据列表:

  • File name (MINIDUMP_MODULE.ModuleNameRva)
  • Module size (MINIDUMP_MODULE.SizeOfImage)
  • Module timestamp (MINIDUMP_MODULE.TimeDateStamp)
  • Module checksum (MINIDUMP_MODULE.CheckSum)

有趣的是,模块的版本信息(MINIDUMP_module.VersionInfo)根本没有考虑在内。

模块搜索路径

VS.NET debugger

调试器在哪里寻找匹配的模块?它们搜索预定义的一组目录。这里记录了VS.NET调试器的模块搜索路径。值得注意的是,调试器检查了两个最重要的位置:

  • 存储小型转储的目录(及其一些子目录)
  • 在创建转储的系统上模块所在的目录

如果我们想指定其他目录在哪里搜索模块,我们可以这样做。有两种可能的方法-在注册表和项目设置中。以下注册表设置可用于指定系统范围内的目录:HKLM\Software\Microsoft\VisualStudio\xxx.xxx\NativeDE\Dumps GlobalModPath = REG_SZ。此设置可以包含用分号分隔的目录列表。类似的设置允许指定用户的模块搜索路径。

在“项目设置”中,我们必须将目录列表输入以下设置:Project properties | Configuration Properties | Debugging | Command Arguments。目录列表的前缀应为“MODPATH=”。例如:MODPATH=c:\modules\testapp;d:\bin\testapp。如下图

如果同时使用两种指定模块搜索路径的方法(注册表和项目设置),则生成的模块搜索路径是这两种方法的组合。首先检查项目设置中的目录。

WinDbg

WinDbg有更自然的方法来指定模块搜索路径-.exepath命令、-i命令行选项和_NT_EXECUTABLE_IMAGE_PATH环境变量。假如我不记得WinDbg默认使用什么路径,但可以通过以下命令轻松检查:

!sym noisy
.reload /f yourmodule.dl

如果我们没有匹配的模块,怎么办?

要确保自己构建的所有模块都存储在一个安全的位置,并且在需要调试崩溃转储时可以找到这些模块并不困难。但是系统dll呢?我们如何确保能够找到安装在客户系统上的相同版本的系统dll?尤其是考虑到热修复之类的东西?

最简单的方法是使用完整的内存内容来生成Minidumps, 如果使用MiniDumpWithFullMemory函数,使用MiniDumpWithFullMemory内存选项,使用NTSD调试器“.dump /ma”,或者检查Watson配置配置中的“崩溃转储类型”设置(这个设置只存在于WindowsXP之后,旧系统总是产生完全崩溃转储)。如果模块的完整内容存储在minidump中,那么理论上,调试器不必在其他地方查找匹配的模块。实际上,似乎只有WinDbg能够在小型转储中利用模块的内容.NET调试器有时只能从小型转储加载模块,但在大多数情况下,它拒绝这样做,并坚持从磁盘加载匹配的模块(如果找不到匹配的模块,则拒绝加载符号)。

当然,具有完整内存内容的小型转储有一个严重的缺点——它们是巨大的。如果我们负担不起自己从客户向开发人员传输许多兆字节的小型转储数据,我们就必须寻找更好的选择。幸运的是,Windows XP和Windows Server 2003操作系统存在一个简单的解决方案——它们的模块在符号服务器上可用,还有符号,调试器(带有符号服务器支持)可以下载它们。我们应该如何配置调试器从symbol服务器下载模块?如果符号服务器的路径是在_NT_SYMBOL_PATH环境变量中指定的,或使用.sympath/.symfix命令指定的,则WinDbg不需要任何其他步骤。VS.NET调试器无法使用_NT_SYMBOL_PATH或符号路径设置进行模块下载。相反,我们必须使用指定模块搜索路径的注册表或项目设置。尽管可以(而且工作正常)在命令参数| MODPATH设置中指定符号服务器的路径,但我发现使用系统范围的注册表设置更方便: HKLM\Software\Microsoft\VisualStudio\xxx.xxx\NativeDE\Dumps GlobalModPath = "srv*c:\symbols*http://msdl.microsoft.com/download/symbols"

建议再执行一个步骤,以确保VS.NET的模块下载可靠–升级symsrv.dll。这个负责符号服务器访问的小DLL的最新版本可以通过Windows的调试工具获得。我们应该将symsrv.dll从调试工具的安装目录复制到<VSInstallDir>\Common7\IDE目录中,覆盖旧版本的dll。

不幸的是,符号服务器上没有旧操作系统(Windows 2000和更早版本)的系统dll。看来调试器在这种情况下几乎无能为力。即使系统dll的符号在符号服务器上,调试器也无法下载它们,因为它们找不到匹配的模块。WinDbg通过在符号路径上查找任何不匹配的.DBG和.PDB文件提供了一点帮助,但无论如何都没有太大帮助。VS.NET调试器甚至不能做到这一点。

模块化

幸运的是,小型转储中的信息通常足以手动生成一个模块,该模块允许调试器从符号服务器下载符号,即使找不到真正匹配的模块。

Minidumps 和 modules匹配的更多相关文章

  1. 在vmware 6.5+ubuntu12.04上安装VMware tools出现问题的分析

    笔者已经写了一篇关于安装"VMware Tools",以实现文件共享的文章,那篇文章对于你实现共享操作是足够了, 所以,倘若你赶时间不如直接去在虚拟机的linux中利用VMware ...

  2. webpack配置别名alias出现的错误匹配

    @(webpack) webpack是一款功能强大的前端构建工具,不仅仅是针对js,它也可通过各种loader来构建相关的less,html,image等各种资源,将webpack配合流程制定工具gu ...

  3. TypeScript Modules(模块)

    本文概述了TypeScript中如何使用模块以各种方式来组织代码.我们将涵括内部和外部的模块,并且讨论他们在适合在何时使用和怎么使用.我们也会学习一些如何使用外部模块的高级技巧,并且解决一些当我们使用 ...

  4. Linux LSM(Linux Security Modules) Hook Technology

    目录 . 引言 . Linux Security Module Framework Introduction . LSM Sourcecode Analysis . LSMs Hook Engine: ...

  5. [转]使用 Minidumps 和 Visual Studio .NET 进行崩溃后调试

    本文关键字:Minidumps, Windows, SEH, VisualC, .NET 摘要 本文讲述了 minidumps 是怎样工作的.当你的程序崩溃的时候应该如何生成它们.以及如何在 Visu ...

  6. elasticsearch文档-modules

    elasticsearch文档-modules modules 模块 cluster 原文 基本概念 cluster: 集群,一个集群通常由很多节点(node)组成 node: 节点,比如集群中的每台 ...

  7. Vulkan Tutorial 11 Shader modules

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 与之前的图像API不同,Vulkan中的着色器代码必须以二进制字节码的格式使用,而不 ...

  8. ASP.NET MVC5写.php路由匹配时的问题 ASP.NET MVC 4 在 .NET 4.0 与.NET 4.5 的專案範本差異

    由于外包公司结束合作,所以考虑把其APP服务替换过来,因原后台是用php写的,在不影响员客户端使用的情况下在MVC下重写路由配置实现处理原php链接地址的请求,但实现时发现怎么也匹配不到自己写的路由, ...

  9. OpenCV特征点检测匹配图像-----添加包围盒

    最终效果: 其实这个小功能非常有用,甚至加上只有给人感觉好像人脸检测,目标检测直接成了demo了,主要代码如下: // localize the object std::vector<Point ...

随机推荐

  1. 2. Spark GraphX解析

    2.1 存储模式 2.1.1 图存储模式 巨型图的存储总体上有边分割和点分割两种存储方式 1)边分割(Edge-Cut):每个顶点都存储一次,但有的边会被打断分到两台机器上.这样做的好处是节省存储空间 ...

  2. HTML页面导出PDF——高清版

    需要做一个导出PDF的功能,网上找有很多,但是一般导出来的都是比较模糊的那种,下面这个是高清版的,导出的PDF都是几M,跟正常手动导出的差不多,很清晰. 首先用到的JS有: <script ty ...

  3. asp.net core 之中间件

    Http请求资源的过程可以看成一个管道:“Pipe”,并不是所有的请求都是合法的.安全的,其于功能.性能或安全方面的考虑,通常需要在这管道中装配一些处理程序来筛选和加工这些请求.这些处理程序就是中间件 ...

  4. MongoDB和Java(7):MongoDB用户管理

    最近花了一些时间学习了下MongoDB数据库,感觉还是比较全面系统的,涉及了软件安装.客户端操作.安全认证.副本集和分布式集群搭建,以及使用Spring Data连接MongoDB进行数据操作,收获很 ...

  5. Tensorflow在python3.7版本的运行

    安装tensorflow pip install tensorflow==1.13.1 -i https://pypi.tuna.tsinghua.edu.cn/simple 可以在命令行 或者在py ...

  6. CI隐藏入口文件index.php

    1.需要apache打开rewrite_module,然后修改httpd.conf的AllowOverride none 为AllowOverride All(里面,不同的环境目录不同) 2.在CI的 ...

  7. 精选SpringBoot八大开源项目:支付、秒杀、全文搜索等

    前言 曾在自己的博客中写下这样一段话:有一种力量无人能抵挡,它永不言败生来倔强.有一种理想照亮了迷茫,在那写满荣耀的地方. 如今,虽然没有大理想抱负,但是却有自己的小计划.下面是这一年来,自己利用闲暇 ...

  8. 1M大概多少个字

    <?php echo strlen("你"); 保存文件为gbk 输出2 保存文件为utf-8 输出3 说明不同编码占用字节不同 1M=1024kB 1KB = 1024B ...

  9. Web前端之【 iframe 】

    iframe基本用法 1.最基本的用法 iframe 标签指定 src <iframe src="demo_iframe_sandbox.htm"></ifram ...

  10. 【Tomcat】虚拟主机

    <Host name="localhost" appBase="webapps" unpackWARs="true" autoDepl ...