Dump文件数据存储格式(四)
六、异常信息流(ExceptionStream
)
异常信息流包含异常信息。包括发生异常的线程、异常记录信息、线程上下文等信息。它紧挨着杂项信息流(MiscInfoStream
)后面。
MiscInfoStream
信息如下:
0x124+0n1365=0x678
我们看看ExceptionStream
信息
可知ExceptionStream的RVA为678h=0x124+0n1365。所以,
MiscInfoStream
后面就是ExceptionStream
。大小168字节,ExceptionStream
数据如下:
ExceptionStream
的数据结构如下:
typedef structMINIDUMP_EXCEPTION_STREAM {
ULONG32 ThreadId;
ULONG32 __alignment;
MINIDUMP_EXCEPTION ExceptionRecord;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
} MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM;
Windbg Register(寄存器)窗口的使用
寄存器是位于在 CPU 的小易失性内存单位。 许多寄存器专用于特定用途,并可用于用户模式应用程序使用的其他寄存器。 基于 x86 和基于 x64 的处理器在有可用的寄存器的不同集合。
如何打开寄存器窗口
- 通过菜单View--->Registers
- 通过快捷键Alt+4
- 通过工具栏
寄存器窗口
通过上面方式打开的窗口如下:
寄存器窗口包含两个列。 Reg列列出了所有目标处理器的寄存器。 Value列显示每个注册的当前值。 此窗口还包含自定义按钮在工具栏上,打开自定义注册列表对话框:
在寄存器窗口中,可以执行以下操作:
Value列显示每个注册的当前值。 以红色文本显示的最近更改的寄存器的值。
- 若要输入新值,请双击值单元格,然后键入新值或编辑旧值。 (剪切、 复制和粘贴命令是可用来进行编辑。)
- 若要保存新值,请按 ENTER。
- 若要放弃的新值,请按 ESC。
- 如果键入无效的值,按 ENTER 键时,将重新出现的旧值。
寄存器值显示在当前的基数,并且必须在相同的基数中键入新值。 若要更改当前的基数,请使用n (设置数量 Base)命令在调试器命令窗口中。
在用户模式下,寄存器窗口显示与当前线程相关联的寄存器。
在内核模式下,寄存器窗口显示与当前相关联的寄存器注册上下文。 可以设置寄存器上下文以匹配特定线程、 上下文记录或捕获帧。 实际显示仅指定的寄存器上下文的最重要寄存器;不能更改它们的值。
寄存器窗口已包含一个工具栏自定义按钮和具有带其他命令的快捷菜单。 若要访问菜单,请右键单击标题栏或单击窗口右上角附近的图标 ()。 工具栏和菜单包含以下按钮和命令:
(工具栏和菜单)自定义会打开自定义寄存器列表对话框中,在本主题中的以下部分中所述。
(仅限菜单)工具栏工具栏,开启和关闭。
(仅限菜单)停靠或取消停靠将使窗口进入或离开停靠的状态。
(仅限菜单)移到新停靠寄存器窗口将关闭,并将其打开新的平台中。
(仅限菜单)设置为选项卡形式停靠为窗口中,键入目标不可用于寄存器窗口。 此选项才可用的源或内存窗口。
(仅限菜单)始终浮点将使窗口停靠,即使仍拖到停靠位置。
(仅限菜单)移动与帧将使窗口移动时移动的 WinDbg 帧,即使在窗口已解除固定。
(仅限菜单)帮助有关 Windows 调试工具文档中打开此主题。
(仅限菜单)关闭关闭此窗口。
自定义寄存器列表对话框
若要更改显示的寄存器的列表,请单击自定义按钮。 自定义寄存器列表对话框将出现。在此对话框中,可以编辑的寄存器,若要更改的寄存器的显示的顺序的列表。 (不能实际从列表中删除寄存器; 如果这样做,它将结束时重新出现。)寄存器名称之间必须留一个空格。如果选择修改显示首次寄存器值复选框,其值已更改的寄存器最近显示在顶部。如果选择不会显示 subregisters复选框,subregisters 不会显示。 例如, eax将显示,但不是ax, ah,或者al。单击确定以保存所做的更改或取消放弃所做的更改。如果你正在调试多个类型的处理器的多处理器计算机,WinDbg 将单独存储每个处理器类型的自定义设置。 这种分离使您可以同时自定义的每个处理器的寄存器的显示。
使用进程内存转储轻松解决事件查看器错误
今天我将写一篇关于我如何使用SOS.Net框架调试扩展(和!analyze-v)以轻松解决.NETFramework异常。此异常阻止事件查看器正确显示。事件查看器返回了一个错误,该错误提供了有关导致该问题的实际原因的很少信息。在本例中,我将演示如何使用windbg来获取有关出错的信息。我不必对此问题执行实时调试。相反,我使用进程转储来获取与根本原因相关的非常精确的信息,这些信息由调试器返回。然后我可以使用进程监视器来识别需要检查的文件。这些行动使我找到了问题的根源,很容易就得到了纠正。
报告的问题:打开时遇到以下错误事件vwr.msc(事件查看器)在Windows 2008 Server系统上:
"MMC could not create the snap-in."MMC could not create the snap-in.
The snap-inmight not have been installed correctly
Name: Event Viewer
CLSID: FX:{b05566ad-fe9c-4363-be05-7a4cbb7cb510}
Windbg Locals(局部变量)窗口的使用
在WinDbg中,可以通过输入命令、使用“局部变量”窗口或使用“监视”窗口查看局部变量。局部变量窗口显示当前作用域中的本地变量的所有信息。
如何打开Locals窗口
- 通过菜单View--->Locals
- 通过快捷键Al+3
- 通过工具栏
局部变量窗口
通过上面的方式打开的窗口如下:
使用Microsoft Windows调试工具连接到远程存根(Remote Stub)的远程调试
Microsoft调试工具for Windows提供了两种创建远程调试连接的方法,包括“连接到远程会话”和“连接到远程存根”。连接到远程会话是这两个会话中最常用的,也是您通常需要的全部内容,但是它不允许客户端访问远程上缺少的调试符号。
通常,远程调试会话将在所有用户都可以访问符号信息的公司网络中完成,但是如果我们在无法自由共享符号的安全环境之外进行调试,调试将变得更加困难。
Microsoft调试工具包有两个服务器端命令行应用程序,可通过连接到远程存根来帮助我们完成此操作:Dbgsrv.exe文件用于用户模式调试和Kdsrv.exe文件用于内核模式调试。它们为调试器提供了一个精简的服务器层,以充分利用本地符号和源代码进行附加。
让我们通过展示连接到远程会话时遇到的问题来说明使用远程存根的好处。
此图显示了传统的远程调试会话。调试主机和目标都在运行windbg,不过我们可以使用KD或CDB。目标是调试一个有缺陷的应用程序Getif.exe它在调试目标上运行。我们在调试主机上有应用程序的符号,但是出于安全原因,调试目标没有符号访问权限Getif.exe. 在这两台计算机上,我们都从http://msdl.microsoft.com/download/symbols取符号。
以下是调试目标计算机上的符号路径。因为此系统不在我们的安全环境之外,所以它没有Getif.exe应用程序。这对于调试是有问题的。
这是调试主机上的符号路径,其中包括指向应用程序符号的路径,因为它位于安全位置内
要在目标计算机上创建远程调试服务器,请使用.server命令指定用于连接的本地端口:.server tcp:port=<localport>
接下来,我在调试主机上选择“connect to remotesession”。
然后输入端口和服务器名称:
这就是我们头疼的地方!因为我们没有Getif.exe符号访问位于安全环境外部的计算机上,堆栈getif.exe不显示符号信息。这使得调试应用程序变得很困难,因为我们无法转储数据类型或查看其他符号信息。
如果我们想调试Getif.exe对于符号,我们需要将符号文件复制到调试目标计算机,并将位置添加到目标的符号路径中。在我们的场景中,这可能是不可能的,因为符号通常仅限于内部使用,不允许自由复制。
通过在调试目标计算机上激活Dbgsrv,调试主机上的调试器将通过对目标计算机上用户模式进程的完全符号访问进行连接。上图说明了这个过程。
让我们在调试目标上运行一个使用dbgsrv的示例。在调试目标上输入:<path to debugging tools>\dbgsrv -t tcp:port=<localport>
Dbgsrv返回命令提示符,命令窗口中没有输出,调试端口可以是系统上任何打开的端口。最好用netstat确认我们正在监听我们选择的端口。下面是一个例子
现在让我们把焦点转移到调试主机上。我们没有选择典型的“连接远程会话”,而是使用“文件”菜单中的“连接到远程存根”选项。
接下来输入端口和服务器名称。
选择OK之后,我们将返回到空的命令窗口。在连接到目标进程之前,我们不会看到任何文本:
下一步选择“文件附加到进程”选项
请注意,“附加到进程”对话框显示调试目标计算机上运行的进程列表。
现在让我们来看看这个过程。标题栏确认我们已连接到kdsrv目标上的进程:
在这里您可以看到与远程存根连接的好处。符号getif.exe正在为运行在安全环境之外的计算机上的应用程序工作。
但是如果我需要内核调试呢?您可以使用Kdsrv对内核调试执行相同的操作。
如果需要的话,我们可以使用内核调试器srkdv。与前面的示例非常相似,我们输入命令:kdsrv -t tcp:port=<localport>
我们可以看到我们正在监听我们选择的本地端口:
现在,我们必须在调试主机上启动调试器,命令行包含连接到KdSrv主机所需的信息。从Windbg 6.10.3.233开始,我们无法从Windbg图形界面连接到kdsrv远程存根,然后再将内核连接到调试目标。
我在上面的图中用的是字符串-windbg -k kdsrv:server=@{tcp:server=rodolpho,port=5004},trans=@{com:pipe,port=\\mimi\pipe\2008target}
请注意,我们正在调试运行在Microsoft Hyper-V下的内核调试目标上的命名管道!这是一个很好的调试方法,无需设置第二台计算机和连接空调制解调器电缆。如果我们想用空调制解调器电缆连接到COM1,我们将使用:windbg -k kdsrv:server=@{tcp:server=rodolpho,port=5004},trans=@{com:port=com1,baud=11500}
Windbg启动后,命令窗口看起来就像我们附加了一个本地调试器一样。标题栏将确认我们正在通过调试服务器附加:
我们还可以将上下文更改为Getif.exe连接到远程存根后处理。当我们查看应用程序堆栈时,我们有应用程序的符号:
在我们有了远程存根连接之后,我们就可以作为远程会话共享我们的客户机,但是我们将始终处理远程存根客户机上的符号。一旦你设置了一个远程存根几次,它就像设置一个远程会话一样简单,并且可以使远程调试更加顺利。
安全说明:这些示例使用TCP/IP或命名管道,不受密码保护。如果您需要更高的安全性,调试器远程将允许SSL和安全管道连接以及密码和证书身份验证。