在windbg中,我正在寻找一种机制来获取命令的输出(特别是断点内的命令)并将其附加到文件中,不写入控制台。
目前我使用.logappend C:\path\to\log
设置流程,然后使用以下命令启用一些断点:
bp WIN32U!{function} ".echo '===WIN32K-START==='; k; .echo '===WIN32K-END==='; g"
这很好用,但写入控制台的输出量会导致严重的性能问题。我希望有一种方法可以将相同的输出提供给我的日志文件,而无需写入windbg控制台的开销。
答案 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"
来编写错误消息,该错误消息仍将发送到输出窗口,以便您可以了解过程中某些点发生的情况。