什么是你最喜欢的WinDBG的技巧/诀窍? [关闭](What is your favourit

2019-08-01 04:59发布

我已经认识到,WinDBG的是Windows平台的一个非常强大的调试器和我偶尔学点新东西了。 老乡WinDBG的用户可以分享一些他们疯狂的技能?

PS:我不想找一个漂亮的命令,那些可以在文档中找到。 如何共享做的东西,人们不能想象,否则可以使用WinDbg进行提示吗? 例如,当一个进程正在运行的WinDbg某种方式来生成有关内存分配的统计数据。

Answer 1:

我最喜欢的是命令.cmdtree <file> (无证,但在以前的版本说明中引用)。 这可以协助将另一个窗口(即可以停靠)以显示有用的或常用的命令。 这可以帮助用户更高效使用该工具。

最初谈到这里,用一个例子的<file>参数: http://blogs.msdn.com/debuggingtoolbox/archive/2008/09/17/special-command-execute-commands-from-a-customized-user -Interface与- cmdtree.aspx

例如: 替代文字http://blogs.msdn.com/photos/debuggingtoolbox/images/8954736/original.aspx



Answer 2:

为了研究在崩溃转储内存泄漏(因为我喜欢到目前为止UMDH现场处理)。 该策略是相同类型的对象都被分配了相同大小。

  • 饲料!heap -h 0命令WinDbg的命令行版本的Cdb.exe(更大的速度)来获取所有堆分配:
"C:\Program Files\Debugging Tools for Windows\cdb.exe" -c "!heap -h 0;q" -z [DumpPath] > DumpHeapEntries.log 
  • 使用Cygwin的到grep分配列表,由大小将它们分组:
 grep "busy ([[:alnum:]]\+)" DumpHeapEntries.log \ | gawk '{ str = $8; gsub(/\(|\)/, "", str); print "0x" str " 0x" $4 }' \ | sort \ | uniq -c \ | gawk '{ printf "%10.2f %10d %10d ( %s = %d )\n", $1*strtonum($3)/1024, $1, strtonum($3), $2, strtonum($2) }' \ | sort > DumpHeapEntriesStats.log 
  • 你得到一个表看起来像这样,例如,告诉我们的0X24字节25529270个分配需要将近1.2 GB的内存。
  8489.52 707 12296 ( 0x3000 = 12288 ) 11894.28 5924 2056 ( 0x800 = 2048 ) 13222.66 846250 16 ( 0x2 = 2 ) 14120.41 602471 24 ( 0x2 = 2 ) 31539.30 2018515 16 ( 0x1 = 1 ) 38902.01 1659819 24 ( 0x1 = 1 ) 40856.38 817 51208 ( 0xc800 = 51200 ) 1196684.53 25529270 48 ( 0x24 = 36 ) 
  • 那么,如果你的对象有虚函数表,只需要使用dps命令寻求一些DumpHeapEntries.log的0X24字节堆分配的知道,正在采取所有内存中的对象的类型。
 0:075> dps 3be7f7e8 3be7f7e8 00020006 3be7f7ec 090c01e7 3be7f7f0 0b40fe94 SomeDll!SomeType::`vftable' 3be7f7f4 00000000 3be7f7f8 00000000 

这是俗气,但它的工作原理:)



Answer 3:

堆栈的C ++虚函数表与对象,尤其是与发行工作时,在寻找时,下面的命令来非常方便,当不少东西得到优化的基础之上。

民进党ESP


能够为转储整齐加载任意PE文件:

WinDbg的-z中是指mylib.dll


查询GetLastError函数()有:

!GLE


这有助于解码常见的错误代码:

!错误ERROR_NUMBER


Answer 4:

近60%我日常使用的命令..

dv /i /t
?? this
kM (kinda undocumented) generates links to frames
.frame x
!analyze -v
!lmi
~


Answer 5:

“刀尖”我最经常使用的是一个,将节省您不必碰那个讨厌的老鼠经常键:Alt + 1

ALT + 1将会把重点放到命令窗口,这样你实际上可以键入命令,并让向上的箭头实际上是通过命令历史记录滚动。 但是,如果你的重点是已在滚动命令历史记录这是行不通的。

怨恨:为什么赫克被忽略按键,而重点是在源窗口? 它不象你可以从里面的WinDbg编辑源代码。 ALT + 1救援。



Answer 6:

一个字(好,OK,三):DML,调试程序标记语言

这是一个相当新的除了WinDbg的,并且它不是在帮助文件中。 然而,有在为Windows调试工具的安装目录下的“dml.doc”一些文档。

基本上,这是一个类似HTML语法,你可以添加到您的调试脚本格式,更重要的是,连接。 您可以使用链接来调用其他脚本,甚至是相同的脚本。

我每天的日常工作包括在元建模,提供对象之间的通用对象和关系的一大块C ++软件的维护。 起初,以便调试,我写了,它可以提取这些物体的相关信息的简单转储脚本。

现在,DML,我已经能够链接添加到输出,允许在同一个脚本来再次对相关对象进行调用。 这允许模型的更快的探索。

这里有一个简单的例子。 假设下内省有一个称为“参考”到另一个对象关系的对象。 R 7 $ T0 = $ $$的arg1 ARG1是一个对象的地址来检查

$$ dump some information from $t0

$$ allow the user to examine our reference
aS /x myref @@(&((<C++ type of the reference>*)@$t0)->reference )
.block { .printf /D "<link cmd=\"$$>a< <full path to this script> ${myref}\">dump Ref</link> " }

很显然,这是一个漂亮的罐装的例子,但这个东西是真的对我非常宝贵的。 相反,在非常复杂的对象狩猎周围正确的数据成员(通常占去了一分钟和各种铸造及提领弄虚作假)的,一切都是自动的点击!



Answer 7:

  • .prefer_dml 1

    这会修改许多内置的命令(例如, lm ),以显示DML输出,让你点击链接,而不是运行命令。 很方便...

  • .reload /f /o file.dll (中/o将覆盖有符号的当前副本)

  • .enable_unicode 1 //切换调试器默认的Unicode字符串,因为所有的Windows组件内部使用Unicode,这是非常方便的。

  • .ignore_missing_pages 1 //如果你做了很多内核转储的分析,你会看到很多关于内存不足的错误被调出。 此命令将告诉调试器停止引发此警告。

别名别名别名...

保存自己在调试一段时间。 下面是我的一些:

aS !p !process;
aS !t !thread;
aS .f .frame;
aS .p .process /p /r
aS .t .thread /p /r
aS dv dv /V /i /t //make dv do your favorite options by default
aS f !process 0 0 //f for find, e.g. f explorer.exe


Answer 8:

另一种答案提到的命令窗口和Alt + 1聚焦命令输入窗口上。 有没有人发现很难滚动命令输出窗口,不使用鼠标?

好吧,我最近使用的AutoHotkey滚动使用键盘和不留命令输入窗口中的命令输出窗口。

; WM_VSCROLL = 0x115 (277)
ScrollUp(control="")
{
    SendMessage, 277, 0, 0, %control%, A
}

ScrollDown(control="")
{
    SendMessage, 277, 1, 0, %control%, A
}

ScrollPageUp(control="")
{
    SendMessage, 277, 2, 0, %control%, A
}

ScrollPageDown(control="")
{
    SendMessage, 277, 3, 0, %control%, A
}

ScrollToTop(control="")
{
    SendMessage, 277, 6, 0, %control%, A
}

ScrollToBottom(control="")
{   
    SendMessage, 277, 7, 0, %control%, A
}

#IfWinActive, ahk_class WinDbgFrameClass
    ; For WinDbg, when the child window is attached to the main window
    !UP::ScrollUp("RichEdit50W1")
    ^k::ScrollUp("RichEdit50W1")
    !DOWN::ScrollDown("RichEdit50W1")
    ^j::ScrollDown("RichEdit50W1")
    !PGDN::ScrollPageDown("RichEdit50W1")
    !PGUP::ScrollPageUp("RichEdit50W1")
    !HOME::ScrollToTop("RichEdit50W1")
    !END::ScrollToBottom("RichEdit50W1")
#IfWinActive, ahk_class WinBaseClass
    ; Also for WinDbg, when the child window is a separate window
    !UP::ScrollUp("RichEdit50W1")
    !DOWN::ScrollDown("RichEdit50W1")
    !PGDN::ScrollPageDown("RichEdit50W1")
    !PGUP::ScrollPageUp("RichEdit50W1")
    !HOME::ScrollToTop("RichEdit50W1")
    !END::ScrollToBottom("RichEdit50W1")

这个脚本运行后,您可以使用Alt + 向上 / 向下滚动命令输出窗口的一行,Alt + PgDn键 / PgUp键滚动一个屏幕。

注:似乎不同版本的WinDbg将会对窗口和控制不同的类名,所以你可能希望使用AutoHotkey的提供的窗口间谍工具先找到实际的类名。



Answer 9:

脚本加载SOS基于.NET框架版本(V2.0 / V4.0):

!for_each_module .if(($sicmp( "@#ModuleName" , "mscorwks") = 0) ) 
{.loadby sos mscorwks} .elsif ($sicmp( "@#ModuleName" , "clr") = 0) 
{.loadby sos clr}


Answer 10:

我喜欢用先进的断点命令,如使用断点来创建新的一次性断点。



Answer 11:

不要使用WinDbg的.heap -stat命令。 它有时会为您提供不正确的输出。 相反,使用DebugDiags内存报告。

具有正确的数字,然后你可以使用WinDbg的.heap -flt ...命令。



Answer 12:

对于命令和其中使用的调试简单(静态或自动化)程序,这是非常酷的,能够把所有的调试器通过一个文本命令文件来运行,并通过kd.exe或运行的Cdb.exe作为输入命令经由批处理脚本调用等

运行,每当你需要做的这个相同的老套路,而不必火起来的WinDbg和手工做的事情。 太糟糕了,当你不知道你在找什么,或者一些命令参数需要人工分析发现/得到这个不起作用。



Answer 13:

独立于平台的转储字符串托管代码,这将适用于x86 / x64的工作:

j $ptrsize = 8 'aS !ds .printf "%mu \n", c+';'aS !ds .printf "%mu \n", 10+'

这里有一个简单的用法:

0:000> !ds 00000000023620b8

MaxConcurrentInstances


文章来源: What is your favourite Windbg tip/trick? [closed]