2023年1月

我每天都看很多转储文件。在这种情况下,我喜欢充分利用windbg可定制的外观和感觉。实际上,我在DMP文件和CMD文件之间有一个关联设置,每当我双击一个转储文件时,这个文件就会加载我自定义的颜色工作区。我喜欢有彩色源代码和调试命令窗口输出的黑色背景。
下面是我典型的调试会话的快照。

 

 

下面告诉你的设置方法。


  1. 创建以下CMD文件并将其放入您的路径中。在我的系统里叫D.CMD

    echooff
    Title kd.exe
    -z %1C:
    CD\debuggers
    start C:\Debuggers\windbg.exe
    -z %1 -W color

我想谈谈我们经常处理的一个常见问题。我们的任务通常是在用户模式进程/应用程序中查找哪些函数正在使用CPU。通常,用户会发现一个应用程序使用的CPU比他们预期的要多,这可能会影响整个系统的性能和响应能力。

对于这个练习,我编写了一些人为的示例代码,称为EATCPU。它包含在博客文章的底部。任务管理器的下图显示EATCPU消耗41%的CPU时间。客户或用户可能会告诉您,这种情况“通常”不会发生。问“正常”是什么总是好的。在这种情况下,我们认为正常值为~10%。

 

最好的情况是对运行在高CPU级别的进程进行实时调试。如果您有幸拥有一个客户/用户,该客户/用户允许您进行远程调试,并且问题在需要时重现,那么您可以采取以下操作。

您需要安装Windows调试工具,并设置符号路径。如果有可能,请获取正在调试的应用程序的符号。我们假设你是支持上述计划的专家。如果是内部编写的,从开发者那里获取符号。如果是来自第三方的,供应商可能愿意为您提供他们产品的符号。

下一件事是附用windbg.exe加进程。

在debuggers目录中,输入TLIST,这将列出您的进程。获取进程id,然后运行WinDBG.EXE –p PROCESSID,或者如果您调试的是eatcup之类的程序,则可以运行WINDBG C:\program\EATCPU.EXE.

附加调试器或在调试器中启动进程后,重现问题。

Microsoft (R) Windows Debugger Version 6.8.0001.0Copyright (c) Microsoft Corporation. All rights reserved.***** WARNING: Your debugger is probably out-of-date.***** Check http://dbg for updates.
CommandLine: eatcpu.exe

Symbol search path is: srv
*C:\symbols*\\symbols\symbols

Executable search path is:

ModLoad:
004000000041a000 eatcpu.exe

ModLoad: 779b0000 77b00000 ntdll.dll

ModLoad:
76780000 76890000C:\Windows\syswow64\kernel32.dll

ModLoad: 62bb0000 62cd1000 C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.
0.50727.762_none_24c8a196583ff03b\MSVCR80D.dll

ModLoad: 75cb0000 75d5a000 C:\Windows\syswow64\msvcrt.dll

(
1090.164): Break instruction exception - code 80000003(first chance)

eax
=00000000 ebx=00000000 ecx=712b0000 edx=00000000 esi=fffffffe edi=77a90094

eip
=779c0004 esp=0017faf8 ebp=0017fb28 iopl=0nv up ei pl zr na pe nc

cs
=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246ntdll!DbgBreakPoint:

779c0004
cc int 3 0:000>g

(
1090.11d4): Break instruction exception - code 80000003(first chance)

eax
=7efa3000 ebx=00000000 ecx=00000000 edx=77a1d894 esi=00000000 edi=00000000eip=779c0004 esp=0109ff74 ebp=0109ffa0 iopl=0nv up ei pl zr na pe nc

cs
=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246ntdll!DbgBreakPoint:

779c0004
cc int 3 0:007> .sympath SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols 0:007>g

(
1090.17d4): Break instruction exception - code 80000003(first chance)

eax
=7efa3000 ebx=00000000 ecx=00000000 edx=77a1d894 esi=00000000 edi=00000000eip=779c0004 esp=0109ff74 ebp=0109ffa0 iopl=0nv up ei pl zr na pe nc

cs
=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246ntdll!DbgBreakPoint:

779c0004
cc int 3

我最近注意到的一个趋势是,在尝试KB304101(PoolUsageMaximum)之后,MmSt标签的使用率仍然很高,这是一种趋势。内存管理器将这些池分配用于节对象原型pte。通常只有两种选择:1)升级到64位平台,或2)减小卷的大小。但我们可能想知道哪些映射文件正在使用这个内存。这是如何做到的。从!memusage开始。

5: kd> !memusage

loading PFN database

loading (
100%complete)

Compiling memory usage data (
99%Complete).

Zeroed:
19073 ( 76292kb)

Free:
0 ( 0kb)

Standby:
1468824 (5875296kb)

Modified:
368 ( 1472kb)

ModifiedNoWrite:
1927 ( 7708kb)

Active
/Valid: 605772 (2423088kb)

Transition:
0 ( 0kb)

Bad:
0 ( 0kb)

Unknown:
0 ( 0kb)

TOTAL:
2095964 (8383856kb)

Building kernel map

Finished building kernel map

Scanning PFN database
- (100% complete)

系统会遇到随机错误检查,内存损坏。有趣的是,腐败有一个非常特殊的模式——它看起来像是一个PFN地址,在这个过程中,标志被随机地放置在页面表页面的几个地方。内存管理器永远不会做这种事情,我怀疑驱动程序正在编辑用户页表页,这是不应该做的。

让我们看看堆栈:

kd>kb*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr Args to Child
f15b1308
80523096 c00862d8 10c5b000 00000000 nt!MiDeletePte+0x198f15b13d080519776 000001d8 10d20fff 00000000 nt!MiDeleteVirtualAddresses+0x164f15b13ec 805b1d74 10c20000 10d20fff f15b14a4 nt!MiDeleteFreeVm+0x20f15b148c 8054060c ffffffff 049c6aa8 049c6ab0 nt!NtFreeVirtualMemory+0x42ef15b148c 7c90eb94 ffffffff 049c6aa8 049c6ab0 nt!KiFastCallEntry+0xfc03e4a398 7c90da54 7c8209b3 ffffffff 049c6aa8 ntdll!KiFastSystemCallRet
03e4a39c 7c8209b3 ffffffff 049c6aa8 049c6ab0 ntdll
!NtFreeVirtualMemory+0xc

最近要求我在升级过程中跟踪一个问题。问题归结为在安装过程中捕获打开特定注册表服务项的Microsoft组件。像这样的问题经常需要实时调试来实时捕获注册表访问。我本可以在RegOpenKeyExW()上设置一个断点,并检查传递到函数中的每个请求的键,但是考虑到RegOpenKeyExW()是一个使用率很高的代码路径,所以这个方法非常耗时。此方法包括在函数上设置断点,等待插入,检查第二个参数(lpSubKey)是否与所需的注册表项(string)匹配,如果该项不匹配,则单击“g”。在找到包含我所需密钥的调用之前,我可以重复这些步骤100次。我想找个办法,只有在我的Key被碰过的时候才会设置“中断访问”。我们遇到了一个类似的问题,需要在可能有数百个文件正在使用时捕获文件系统函数处理特定文件。那么,如何实现这种类型的调试所需的自动化呢?答案是调试器脚本。

让我们来看看Windows的一个例子资源管理器使用这种方法。在这个场景中,我们将尝试捕捉资源管理器正在打开HKEY U LOCAL U MACHINE\SYSTEM\Setup键。Windows资源管理器每秒打开多个键,因此重点是在将此特定键传递给RegOpenKeyEx()时“插入”,而不必手动遍历传递给函数的数百个可能的键。

1、确定有问题的函数

根据MSDN,RegOpenKeyEx定义如下,我们对第二个参数感兴趣,因为它包含键的名称。