分类 调试 下的文章

.cordll (控制CLR调试)

简介

.cordell命令控制托管代码调试和Microsoft.NET公共语言运行库(CLR)。

使用形式

.cordll[Options]

参数

  • Options
    使用以下一个或多个以下选项:
    -l (小写的 L)

    加载 CLR 调试模块。

    -IModule (大写的 i)

    指定的名称或要进行调试的 CLR 模块的基址。

    -u

    卸载 CLR 调试模块。

    -e

    启用 CLR 调试。

    -d

    禁用 CLR 调试。

    -D

    禁用 CLR 调试和卸载 CLR 调试模块。

    -N

    重新加载 CLR 调试模块。

    -lpPath

    指定 CLR 调试模块的目录的路径。

    -se

    通过使用 CLR 调试模块的短名称,启用 mscordacwks.dll。

    -sd

    禁用使用CLR调试模块的短名称mscordacwks.dll。相反,调试器使用CLR调试模块的长名称mscordacwks_<spec>.dll。如果担心不匹配,禁用短名称使用可以避免使用本地CLR。

    -ve

    打开CLR模块加载的详细模式。

    -vd

    关闭CLR模块加载的详细模式。

支持环境

模式

用户模式下,内核模式

目标

实时、 崩溃转储

平台

全部

备注

要调试托管应用程序,调试器必须加载与应用程序加载的CLR相对应的数据访问组件(DAC)。但是,在某些情况下,应用程序加载多个CLR。在这种情况下,可以使用I参数指定调试器应加载哪个DAC。CLR的版本2名为Mscorwks.dll,而CLR的版本4名为CLR.dll。下面的示例演示如何指定调试器应加载版本2(mscorwks)的DAC。

.cordll -I mscorwks -lp c:\dacFolder

如果省略I参数,则调试器默认使用版本4。例如,以下两个命令是等效的。

.cordll -lp c:\dacFolder
.cordll -I clr -lp c:\dacFolder

Sos.dll是用于调试托管代码的组件。当前版本的Windows调试工具不包括任何版本的sos.dll。内核模式调试中支持.cordell命令。但是,除非调出必要的内存,否则此命令可能无法工作。

 

 

 

 

今天在分析一个dmp时,要看CLR栈,习惯性输入.cordll -ve -u -l指令来加载sos扩展,结果报如下错误:

CLR DLL status: No load attempts

核对sos.dll版本后,发现版本是对的。突然想起上次执行.loadby sos clrjit报错(参考The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos) failed, Win32 error 0n193 "%1 不是有效的 Win32 应用程序。"),心想是不是同样的原因呢,看下Windbg标题栏,果然是同样的原因,用的是64位Windbg

 

赶紧输入.loadby sos clrjit,看看是不是会报上次同样的错误,

看来一定要细心,要不然会浪费时间。

概要

本文分步介绍了如何使用 WinDbg 调试程序 (windbg.exe) 调试 Windows 服务。 要调试 Windows 服务,可以在服务启动后将 WinDbg 调试程序附加到托管该服务的进程,或者可以配置服务以在启动时附加 WinDbg 调试程序,以便解决与服务启动相关的问题。 本文将介绍这两种方法。

服务启动后将 WinDbg 调试程序附加到服务

此方法与你用于将调试程序附加到进程然后调试进程的方法类似。

使用托管要调试服务的进程的进程 ID

  1. 若要确定托管要调试服务的进程的进程 ID (PID),请使用以下任一方法。

    方法 1: 使用任务管理器


      1. 右键单击任务栏,然后单击
        “任务管理器”。 随即显示“Windows 任务管理器”对话框。
      2. 单击“Windows 任务管理器”对话框的
        “进程”选项卡。
      3. 在“映像名称”下,单击托管要调试服务的进程的映像名称。 请注意,此进程的进程 ID 是由
        相应的 PID 字段值指定的。

    方法 2: 使用任务列表实用工具 (tlist.exe)


      1. 单击“开始”,然后单击
        “运行”。 随即出现“运行”对话框。
      2. 在“打开”框中,键入
        cmd,然后单击“确定”。
      3. 在命令提示符处,更改目录路径以显示计算机上的 tlist.exe 文件位置。
        注意 tlist.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows
      4. 在命令提示符处,键入
        tlist 以列出计算机上当前运行的所有进程的映像名称以及进程 ID。
        注意 请记下托管要调试服务的进程的进程 ID。
  2. 在命令提示符处,更改目录路径以显示计算机上的 windbg.exe 文件位置。
    注意 如果命令提示符未打开,请按照方法 1 的步骤 a 和 b 操作。 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。
  3. 在命令提示符下,键入 windbg –p
    ProcessID /g 以将 WinDbg 调试程序附加到托管要调试服务的进程。
    注意 ProcessID 是托管要调试服务进程的进程 ID 的占位符。

使用托管要调试服务的进程的映像名称

 

只能在托管要运行服务的进程正好存在一个正在运行的实例时使用此方法。 为此,请按照下列步骤操作:

  1. 单击“开始”,然后单击
    “运行”。 随即出现“运行”对话框。
  2. 在“打开”框中,键入
    cmd,然后单击“确定”以打开命令提示符。
  3. 在命令提示符处,更改目录路径以显示计算机上的 windbg.exe 文件位置。

    注意 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。
  4. 在命令提示符下,键入 windbg –pn
    ImageName /g 以将 WinDbg 调试程序附加到托管要调试服务的进程。

    注意 ImageName 是托管要调试服务进程的映像名称的占位符。 “-pn”命令行选项指定
    ImageName 命令行参数是进程的映像名称。

启动 WinDbg 调试程序并附加到托管要调试服务的进程

  1. 启动 Windows 资源管理器。
  2. 找到计算机上的 windbg.exe 文件。

    注意 windbg.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows
  3. 同时运行 windbg.exe 文件和 /g 命令行开关以启动 WinDbg 调试程序。 设置断点后,/g 命令行开关允许跟踪的进程继续运行。
  4. 在“文件”菜单中,单击“附加到进程”以显示“附加到进程”对话框。
  5. 单击以选择托管要调试服务的进程相应节点,然后单击
    “确定”。
  6. 在出现的对话框中,单击“是”以保存工作区基本信息。 请注意,现在你可以调试服务的反汇编代码。

配置服务以在启动时附加 WinDbg 调试程序

如果要解决与服务启动相关的问题,可以使用此方法调试服务。

配置“映像文件执行”选项。 为此,请使用下列方法之一:

方法 1: 使用全局标志编辑器 (gflags.exe)
  1. 启动 Windows 资源管理器。

找到计算机上的 gflags.exe 文件。

注意 gflags.exe 文件通常位于以下目录中: C:\Program Files\Debugging Tools for Windows。

运行 gflags.exe 文件以启动全局标志编辑器。

在“映像文件名称”文本框中,键入托管要调试服务的进程的映像名称。 例如,如果要调试由映像名称为 MyService.exe 的进程托管的服务,请键入
MyService.exe。

在“目标”下,单击以选中“映像文件选项”选项。

在“映像调试程序选项”下,单击以选中“调试程序”复选框。

在“调试程序”文本框中,键入要使用的调试程序的完整路径。 例如,如果要使用 WinDbg 调试程序来调试服务,可以键入与以下路径相似的完整路径: C:\Program Files\Debugging Tools for Windows\windbg.exe。单击“应用”,然后单击,“确定”退出全局标志编辑器。

方法 2: 使用注册表编辑器

  1. 单击“开始”,然后单击
    “运行”。 随即出现“运行”对话框。
  2. 在“打开”框中,键入
    regedit,然后单击“确定”以启动注册表编辑器。
  3. 重要说明
    本部分(或称方法或任务)包含有关如何修改注册表的步骤。 但是,注册表修改不当可能会出现严重问题。 因此,请务必严格按照这些步骤操作。
    为了获得进一步的保护,请在修改注册表之前对其进行备份。 这样就可以在出现问题时还原注册表。
    有关如何备份与还原注册表的详细信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

    322756 如何在 Windows 中备份和还原注册表

类 std::tr2::sys::filesystem_error 定义文件系统库中函数的抛出版重载所抛出的异常对象。

cpp/error/exception cpp/error/runtime error cpp/error/system error





定义于头文件 <filesystem>

粗略察看一 下.pdb 文件,会发现在其起始位置存放的是这样一个字符串“Microsoft C/C++ program database 2.00”。可以看出 PDB 是 Program Database 的首字母缩写。在 MSDN 中或 Internet 上搜索一下有关 PDB 内部结构的信息,你会发现没有任何有用的信息,唯一例外的是,在 微软的基础知识文章中,微软申明此种格式是它有的(Microsoft Corporation, 2000d)。就连 Windows 的老大 Matt Pietrek 也承认:
“ PDB符 号 表 的 格 式 并 没 有 公 开 的 文 档 。( 就 连 我 也 不 知 道 其 确 切 的 格 式 , 唯 一 知 道 的 是,它会随着 Visual C++ 的 更 新 而 更 新 。)”( Pietrek 1997a )
或许,pdb 格式会随着 Visual C/C++一起更新,不过针对当前版本的 Windows 2000 我 可以确切的告诉你 PDB 符号文件的结构。这或许是首次公开的 PDB 格式文档。但首先,还 是让我们检查一下.dbg 和.pdb 文件是如何链接到一起的。
Windows 2000 的.dbg 文件的一个显著特性是:它们包含的数据很少,几乎可以忽略它 们的 CodeView子节。下面示例给出了 ntsokrnl.exe 的.dbg 文件所包含的整个 CodeView数据, 只有区区 32 字节。

Address | 00 01 02 03-04 05 06 07 : 08 09 0A 0B-0C 0D 0E 0F | 0123456789ABCDEF
---------|-------------------------:-------------------------|-----------------
00006590 | 4E 42 31 30-00 00 00 00 : 20 7D 23 38-54 00 00 00 | NB10.... }#8T...
000065A0 | 6E 74 6F 73-6B 72 6E 6C : 2E 70 64 62-00 00 00 00 | ntoskrnl.pdb...

通常,子节总是以一个 CV_HEADER 结构开始,该结构中包 含 CodeView 的版本标识。这一次,该版本标识是 NB10MSDN(Microsoft 2000a)没能告 诉我们有关这个特殊版本的更多信息: “ NB10 ,可执行文件的这一标识表示,其调试信息保存在独立的 PDB文件中。相应的格式还有NB09或NB11。”( MSDN Library—April 2000\Specifications\Technologies and Languages\Visual C++ 5.0 Symbolic Debug Information Specification\Debug Information Format )
我并不知道 NB11 格式的内部细节,不过 PDB 格式和前面讨论的 NB09 格式一样几乎 什么也没有。第一句话很明确的说明了为什么 NB10 数据块是如此的小。所有相关的信息都 被移到了独立的文件中了,因此这个 CodeView 子节的主要作用就是提供指向实际数据的链 接。如示例 1-8 所暗示的,在 ntoskrnl.pdb 文件中一定可以找到实际的符号信息。
CV_HEADER 结构是自解释的。其后的两个成员的偏移量分别为:0x8 和 0xC,它们的 名字分别为:dSignature 和 dAge,在.dbg 和.pdb 文件链接的过程中它们将扮演重要角色。 dSignature 是一个 32 位的 UNIX 风格的时间戳,它保存了调试信息构建的日期和时间(自 01-01-1970 以来逝去的秒数)。w2k_img.dll 提供了两个函数:imgTimeUnpack()和 imgTimePack()用来将 dSignature 和 Windows 风格的时间格式进行相互的转化。我还不是非 常清楚 dAge 成员的确切含义。目前知道的是:dAge 成员的初始值为 1,每次修改 PDB 数 据后其值就会增一。dSignature 和 dAge 共同构成一个 64 位的 ID,调试器可以使用它来验 证给定的 PDB 文件是否与它引用的.dbg 文件相匹配。PDB 文件在它的一个数据流中包含着 两个值的一个副本,因此调试器可以拒绝处理不相匹配的.dbg/.pdb 文件。
 
无论你何时遇到格式未知的数据结构,你应该做的第一件事就是使用十六进制 Dump 浏览器察看这些结构。本书附带的w2k_dump.exe可很好的完成这一工作。通过检查Windows 2000 PDB 文件,如 ntoskrnl.pdb 或 ntfs.pdb,你会发现这些文件拥有如下一些共同特性: 

  • 这些文件似乎都被划分为多个大小固定的块,一般情况下,每个块的大小为 0x400 字节。
  • 某些块包含一长串 1,但偶而会被一小段连续的 0 打断。
  • 文件中的信息并不必须是连续的。有时,数据会在块的边界处突然结束,但又会在 文件的其它地方继续开始。
  • 有些数据块会在文件中反复出现。

CodeView 的 NB10 子节 
typedef
struct _CV_NB10 //PDB reference{
CV_HEADER Header;
DWORD dSignature;
//seconds since 01-01-1970 DWORD dAge; //1++ BYTEabPdbName[];//zero-terminated} CV_NB10,*PCV_NB10, **PPCV_NB10;#define CV_NB10_ sizeof(CV_NB10)