简介

调试应用程序时,调试器必须加载可执行模块的符号,以便能够显示有意义的调用堆栈、当前源代码行、变量值等。如果您曾经调试过在另一个系统上创建的小型转储,那么您已经知道除了符号之外,调试器还需要访问创建转储时由应用程序加载的相同版本的模块。如果调试器找不到与模块完全相同的版本(即匹配的模块),则无法加载模块的符号,从而严重限制了成功调试的可能性。在本文中,我们将讨论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. python递归函数和河内塔问题

    关于递归函数: 函数内部调用自身的函数. 以n阶乘为例: f(n) = n ! = 1 x 2 x 3 x 4 x...x(n-1)x(n) = n x (n-1) ! def factorial(n ...

  2. 「UER#2」信息的交换

    「UER#2」信息的交换 吉利题.. 不难发现,置换中的每一个循环是独立的,每一个循环分别对应一个独立的联通块. 根据题目的性质,每一个联通块做的事情等价于其按照编号从小到大遍历的的dfs生成树做的事 ...

  3. CF1109F Sasha and Algorithm of Silence's Sounds LCT、线段树

    传送门 构成一棵树可以分成两个限制:图不成环.图的点数-边数=1. 我们考虑枚举右端点\(r\)计算所有可能的左端点\(l\)的答案.我们先考虑第一个限制:图不成环.注意到当\(r\)确定的时候,满足 ...

  4. python鸭子类型

    “当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就能够被称为鸭子” python的鸭子类型的设计让python的诸多对象的分类和应用更加灵活,需要注意类型和对象的区别(pytho ...

  5. eclipse创建springboot项目的三种方法

    本文链接:https://blog.csdn.net/mousede/article/details/81285693 方法一 安装STS插件 安装插件导向窗口完成后,在eclipse右下角将会出现安 ...

  6. ComPtr的介绍以及使用

    ComPtr是为COM而设计的智能指针.它支持WindowsRT,也支持传统Win32.相比ATL里的CComPtr类,它有了一些提升. ComPtr包含在Windows 8.x SDK and Wi ...

  7. 2019 超级老板APPjava面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.超级老板等公司offer,岗位是Java后端开发,因为发展原因最终选择去了超级老板,入职一年时间了,也成为了面 ...

  8. kubernetes--配置文件

  9. 【面试突击】- Java面试总则

    Java基础 1.Map.Set.List集合差别及联系详解 2.HashSet类是如何实现添加元素保证不重复的 3.HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安 ...

  10. webpack-dev-server提示css模块解析失败,但已经装了css-loader

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/a117616/article/detai ...