将windbg命令输出写入文件,但不是控制台

时间:2017-09-12 17:32:22

标签: windows windbg

在windbg中,我正在寻找一种机制来获取命令的输出(特别是断点内的命令)并将其附加到文件中,写入控制台。

目前我使用.logappend C:\path\to\log设置流程,然后使用以下命令启用一些断点:

bp WIN32U!{function} ".echo '===WIN32K-START==='; k; .echo '===WIN32K-END==='; g"

这很好用,但写入控制台的输出量会导致严重的性能问题。我希望有一种方法可以将相同的输出提供给我的日志文件,而无需写入windbg控制台的开销。

2 个答案:

答案 0 :(得分:1)

您可以修补 dbgeng!g_OutputControl 全局以禁用写入控制台并仅写入日志文件

但我不知道你是否会有性能提升

寻找txt文件

C:\>dir /b *.txt
File Not Found

打开调试会话

C:\>cdb calc


Microsoft (R) Windows Debugger Version 10.0.15063.400 X86

ntdll!LdrpDoDebuggerBreak+0x2c:
774005a6 cc              int     3

在打开的调试会话中 产生父调试器以调试运行调试对象的windbg

0:000> .dbgdbg
Debugger spawned, connect with
    "-remote npipe:icfenable,pipe=cdb_pipe,server=xxxx"

在生成的父补丁中进行全局和分离

ed dbgeng!g_OutputControl 0
.detach
q

在调试会话中打开日志文件

0:000> .logappend c:\foo.txt
Opened log file 'c:\foo.txt'

设置条件断点并启动会话

0:000> bp ntdll!RtlEnterCriticalSection "kb;gc"
0:000> bl
 0 e 773a7790     0001 (0001)  0:**** ntdll!RtlEnterCriticalSection "kb;gc"
0:000> g

此处没有控制台输出

执行ctrl + c停止会话并退出会话

eax=7ffde000 ebx=00000000 ecx=00000000 edx=773ff1d3 esi=00000000 edi=00000000
eip=77394108 esp=016ef8a8 ebp=016ef8d4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77394108 cc              int     3
0:001> q
quit:

检查日志文件并确认是否有大量数据写入其中 RtlEnterCriticalSection Api是一个非常热门的Api

C:\>dir /b *.txt
foo.txt

C:\>ls -l foo.txt
-rw-rw-rw-  1  0 **1754920** 2017-09-15 00:27 foo.txt

C:> head foo.txt

Opened log file 'c:\foo.txt'
0:000> bp ntdll!RtlEnterCriticalSection "kb;gc"
0:000> bl
 0 e 773a7790     0001 (0001)  0:**** ntdll!RtlEnterCriticalSection "kb;gc"
0:000> g
ChildEBP RetAddr  Args to Child
000cf114 77425f4b 000d0138 7724d80b 00000000 ntdll!RtlEnterCriticalSection
000cf158 773ea40a 000d0000 50180162 00000044 ntdll!RtlDebugAllocateHeap+0x9d
000cf23c 773b5ae0 00000044 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4
000cf2c0 77384726 000d0000 40180060 00000044 ntdll!RtlAllocateHeap+0x23a

还有更多的22k行写入此文件

C:\>wc -l foo.txt
22543 foo.txt

C:> tail foo.txt

000cf838 773c37be 00462d6c 7ffdb000 00000000 ntdll!__RtlUserThreadStart+0x70
000cf850 00000000 00462d6c 7ffdb000 00000000 ntdll!_RtlUserThreadStart+0x1b
(c80.8ec): Break instruction exception - code 80000003 (first chance)
eax=7ffde000 ebx=00000000 ecx=00000000 edx=773ff1d3 esi=00000000 edi=00000000
eip=77394108 esp=016ef8a8 ebp=016ef8d4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77394108 cc              int     3
0:001> q
quit:

C:\>

答案 1 :(得分:1)

您需要.outmask元命令:https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-outmask--control-output-mask-

.outmask允许您控制将哪些消息类型发送到输出窗口和日志文件。 /l开关可以允许您仅更改到达输出窗口的类型,而不会影响哪些类型将到达日志文件。

例如,此命令将关闭所有输出到输出窗口,同时仍将正常消息发送到日志文件:

.outmask- /l 0xffff

虽然可能只需要.outmask- /l 1,但这会关闭正常的消息输出,但错误和警告仍将显示在输出窗口中。完成后,使用.outmask /d将输出设置重置为默认值。

结合.printf输出不同消息类型的能力,你可以做到这一点,这样你仍然可以知道发生了什么。使用.outmask- /l 1关闭正常消息输出到窗口。现在,您可以在某个地方的断点命令中使用.printf /oe "message"来编写错误消息,该错误消息仍将发送到输出窗口,以便您可以了解过程中某些点发生的情况。