简介

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

    1 可以创建多条路由规则,每条路由规则的那么属性不同 2路由规则是有顺序的.如果被前面的规则匹配了,那么后面的规则就没机会了 3 constraints 约束: 4namespaces 命名空间 5r ...

  2. golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

    micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.s ...

  3. Docker容器挂载文件(转载)

    一.Docker pull 安装 Nginx 1.查看docker仓库中的 nginx 命令 # 使用 docker search 命令搜索存放在 Docker Hub 中的镜像 docker sea ...

  4. java之mybatis之helloworld

    1. MyBatis 是一款一流的支持自定义SQL.存储过程和高级映射的持久化框架. MyBatis几乎消除了所有的 JDBC 代码,也基本不需要手工去设置参数和获取检索结果. MyBatis几乎能够 ...

  5. 微软企业库支持 MySql

    微软企业库支持 MySql   三步让企业库支持 mysql 数据库 1.创建 MySqlDatabaseData 类 using Microsoft.Practices.EnterpriseLibr ...

  6. Synchronized可重入锁分析

    可重入锁又称递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象必须是同一对象或者class), 不会因为之前已经获取过还没实方而发生阻塞.即同一线程可执行 ...

  7. 结对项目(java实现)

    一 .Github项目地址:https://github.com/734635746/MyApp 二.PSP表格 PSP2.1 Personal Software Process Stages 预估耗 ...

  8. linux下测试某网址或IP端口能否访问

    参考这篇 Linux系统下怎么测试端口的连通性 测试端口连通 nc -v -w 1 183.xx.oo.ee -z 82 1linux主机centos操作系统,项目里面需要访问一个URL路径的接口ht ...

  9. 超详细的纯净windows系统重装示例

    之前说过通过使用大白菜制作启动盘,再去系统之家下载系统.虽然系统能安装,但是有时安装的是ghost版本,安装方便,只要引导后面就是等待自动安装,驱动什么的都不用管.但是有时会带上很多软件,不好清理甚至 ...

  10. [LeetCode] 538. 把二叉搜索树转换为累加树 ☆(中序遍历变形)

    把二叉搜索树转换为累加树 描述 给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和. ...