wenmo8 发布的文章

简介

我最近研究了一个问题,Winlogon中两个线程的交互导致错误检查。一个线程是初始化GDI的Winlogon线程。这个场景的有趣之处在于另一个线程是如何在这个进程中结束的。

线程在干什么?

下面是线程堆栈的用户一半。线程试图加载DLL

ChildEBP RetAddr Args to Child

0058eaec 773901ad 773901d9 0058eafc
00240022 ntdll!KiFastSystemCallRet

0058eb0c 775d96f3 775d1808
00000000 77e6f032 USER32!NtUserRegisterWindowMessage+0xc0058ed24 775e475500000000 00000001 7c837512 comctl32!InitGlobalMetrics+0x440058ed3c 775e426a00000031 0058ed68 7763490c comctl32!_ProcessAttach+0x980058ed48 7763490c 775d000000000001 00000000 comctl32!DllMain+0x210058ed68 7c81a352 775d000000000001 00000000 comctl32!_DllMainCRTStartup+0x520058ed88 7c833465 776348ba 775d000000000001 ntdll!LdrpCallInitRoutine+0x140058ee90 7c83431100000000 00000000 7c8e2e58 ntdll!LdrpRunInitializeRoutines+0x3670058f124 7c83406500000000 00080e98 0058f3ec ntdll!LdrpLoadDll+0x3cd0058f3a0 77e41bf3 00080e98 0058f3ec 0058f3cc ntdll!LdrLoadDll+0x1980058f408 77e5c70b 7c8e2e5800000000 00000000 kernel32!LoadLibraryExW+0x1b20058f41c 7c92a6a1 7c8e2e5800000000 7c8e2e58 kernel32!LoadLibraryW+0x110058f454 7c92a65f 7c8e2e58 7c8d0000 7c9297b6 SHELL32!SHFusionLoadLibrary+0x2a0058f460 7c9297b600000020 00000008 0058f6a8 SHELL32!DelayLoadCC+0x150058f694 7c929728 0058f6a8 0000007c00000001 SHELL32!SHFusionInitializeIDCC+0x920058f8b4 7c92966f 7c8d0000 0000007c00000001 SHELL32!SHFusionInitializeFromModuleID+0x3a0058f8c8 7c92962c 7c8d000000000001 0058f8f8 SHELL32!_ProcessAttach+0x340058f8d8 7c92bb63 7c8d000000000001 00000000 SHELL32!DllMain+0x270058f8f8 7c81a352 7c8d000000000001 00000000 SHELL32!_DllMainCRTStartup+0x520058f918 7c833465 7c92bb1b 7c8d000000000001 ntdll!LdrpCallInitRoutine+0x140058fa20 7c83431100000000 00000000 00000004 ntdll!LdrpRunInitializeRoutines+0x367

我最近处理的一个棘手的死锁问题开始。让我先解释一下表面症状,然后我们就可以找到好东西了。当运行Vista的用户尝试启动internetexplorer时,任何事情都不会发生。所以他们再次双击图标,还是什么也没发生。所以用户会重新启动并返回他们的网络活动。
经过一些基本的故障排除后发现Iexplore.exe正在运行多次,每次尝试打开浏览器都会导致另一个Iexplore.exe实例。因为没有用户界面,所以我继续收集了一些Iexplore.exe进程转储以及完整的系统转储。
进程转储没有被证明是非常有用的,所以我决定转到完整的内存转储。
因为我知道我们有多个IExplore.exe运行的进程,我想先调查一下。

0: kd>!process 0 0

<snip>PROCESS 87289d90 SessionId:5 Cid: 0fdc Peb: 7ffdc000 ParentCid: 0968DirBase: 7d66c520 ObjectTable: a203a178 HandleCount:205.

Image: iexplore.exe

PROCESS 861a9d90 SessionId:
5Cid: 0d34 Peb: 7ffd9000 ParentCid: 0fdc

DirBase: 7d66c7a0 ObjectTable: a5651a98 HandleCount:
170.

Image: ieuser.exe

PROCESS 86c175b0 SessionId:
5 Cid: 1250 Peb: 7ffd9000 ParentCid: 0968DirBase: 7d66c940 ObjectTable: a0853f10 HandleCount:91.

Image: iexplore.exe

PROCESS 861ac7a8 SessionId:
5 Cid: 1024 Peb: 7ffde000 ParentCid: 0968DirBase: 7d66c620 ObjectTable: a83f7898 HandleCount:91.

Image: iexplore.exe
</snip>

在某些情况下,您可能希望使用用户模式调试器从内核调试器中调试进程。它可能是你有一个加载内核模式驱动程序的应用程序,并且你希望能够调试应用程序的用户模式方面,然后进入内核以跟踪对内核的调用。

这是你需要做的!

通过串行电缆(调制解调器电缆)、USB电缆或FireWire电缆连接内核调试器,并将您的计算机配置为内核调试。要在Vista或Windows 2008上启用调试选项,必须使用bcdedit.exe文件因为那些操作系统不再使用启动.ini文件。下面是一个例子:

bcdedit /debug {<guid>} <ON | OFF>bcdedit/dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200

在某些情况下,我们会执行实时调试以确定服务器故障的根本原因。在内存转储的情况下,文件通常非常大,因此通过网络复制文件,即使是在最快的广域网连接上,也可能需要很长时间。解决方案是远程调试。

你应该怎么做?

首先,需要两个人:一个是远程人员,另一个是通过使用安装在他们机器上的调试器调试进程来帮助远程用户的专家。
假设你是帮助远程人的专家。流程如下:
1、远程用户使用windbg打开转储文件、调试进程或内核调试远程位置的计算机。
2、远方的人决定,“我需要帮助!”
3、远程用户只在windbg提示符下需输入..server tcp:port=9999。

 

注意下面的输出。
服务器已启动。客户机可以使用这些命令行中的任何一个进行连接

0: <debugger> -remote tcp:Port=9999,Server=MyServerName

今天分析一个dmp文件时,想看下内存的使用情况,于是执行!address -summary,结果却有如下输出:

0:000> !address -summary
The current target does not provide full memory information. No meaningful summary available.
Use !address with no arguments to display the available virtual memory map of the target.

之前收集到的dmp文件没有这样问题,于是问了下支持的同事,这个dmp文件的获取方法是怎样的。支持的同事反应不是自己抓的,是我们的程序自动产生的。看来程序在生成dmp时,Minidump的的选项设置有问题。

用工具打开dmp看看

 

赶紧查看一下代码

 

果然设置选项不够,赶紧加上MiniDumpWithFullMemoryInfo选项,制造一个异常,在看看

 

 

用Windbg加载,并执行!address -summary

0:000> !address -summary

                                     
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    123          75782000 (   1.835 GB)           91.78%
<unknown>                               124           5954000 (  89.328 MB)  53.04%    4.36%
Image                                   306           3c17000 (  60.090 MB)  35.68%    2.93%
Heap                                     42            c96000 (  12.586 MB)   7.47%    0.61%
Stack                                    18            600000 (   6.000 MB)   3.56%    0.29%
Other                                     8             5c000 ( 368.000 kB)   0.21%    0.02%
TEB                                       6              e000 (  56.000 kB)   0.03%    0.00%
PEB                                       1              3000 (  12.000 kB)   0.01%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED                               57           5497000 (  84.590 MB)  50.22%    4.13%
MEM_IMAGE                               327           3c83000 (  60.512 MB)  35.93%    2.95%
MEM_PRIVATE                             121           1754000 (  23.328 MB)  13.85%    1.14%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                123          75782000 (   1.835 GB)           91.78%
MEM_COMMIT                              447           8197000 ( 129.590 MB)  76.94%    6.33%
MEM_RESERVE                              58           26d7000 (  38.840 MB)  23.06%    1.90%

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READONLY                           188           3f7c000 (  63.484 MB)  37.69%    3.10%
PAGE_EXECUTE_READ                        68           2f22000 (  47.133 MB)  27.98%    2.30%
PAGE_READWRITE                          144           11be000 (  17.742 MB)  10.53%    0.87%
PAGE_WRITECOPY                           29            666666000 (   1.066 MB)   0.63%    0.05%
PAGE_READWRITE|PAGE_GUARD                12             1e000 ( 120.000 kB)   0.07%    0.01%
PAGE_EXECUTE_READWRITE                    4              a000 (  40.000 kB)   0.02%    0.00%
PAGE_NOACCESS                             2              2000 (   8.000 kB)   0.00%    0.00%

--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Free                                         7eb0000          56d90000 (   1.357 GB)
<unknown>                                    4e00000           2000000 (  32.000 MB)
Image                                       75231000            54d000 (   5.301 MB)
Heap                                         7a79000            376000 (   3.461 MB)
Stack                                        37e0000             fd000 (1012.000 kB)
Other                                       7fcc0000             33000 ( 204.000 kB)
TEB                                           e19000              3000 (  12.000 kB)
PEB                                           e16000              3000 (  12.000 kB)

看到了内存的摘要信息了。

虽然我们希望dmp文件尽量小,但一些必要的信息还是需要的。