WindbgはWindowsプラットフォーム用の非常に強力なデバッガーであることに気付き、時々新しいことを学びます。仲間のWindbgユーザーは彼らの狂ったスキルのいくつかを共有できますか?
ps:私は気の利いたコマンドを探していません。それらはドキュメントにあります。 windbgでできるとは想像もできなかった何かをするためのヒントを共有してみませんか?例えばプロセスがwindbgで実行されているときに、メモリ割り当てに関する統計を生成する方法。
私のお気に入りはコマンド.cmdtree <file>
(文書化されていませんが、以前のリリースノートで参照されています)。これは、別のウィンドウ(ドッキング可能なウィンドウ)を表示して、役立つコマンドまたは一般的に使用されるコマンドを表示するのに役立ちます。これにより、ユーザーはツールを使用して生産性を大幅に向上させることができます。
最初にここで話しましたが、<file>
パラメーター: http://blogs.msdn.com/debuggingtoolbox/archive/2008/09/17/special-command-execute-commands-from-a-customized-user-interface-with-cmdtree。 aspx
例: 代替テキストhttp://blogs.msdn.com/photos/debuggingtoolbox/images/8954736/original.aspx
クラッシュダンプでのメモリリークを調査するため(ライブプロセスには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
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
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
それは安っぽいですが、それは動作します:)
次のコマンドは、vtablesを使用してC++オブジェクトのスタックを調べる場合、特にリリースビルドを操作するときに、かなりの数の項目が最適化されていない場合に非常に便利です。
dpp esp 範囲
ダンプとして任意のPEファイルをロードできることは素晴らしいことです:
windbg -z mylib.dll
GetLastError()をクエリします。
!gle
これは、一般的なエラーコードのデコードに役立ちます。
!エラーerror_number
私が毎日使用するコマンドのほぼ60%。
dv /i /t
?? this
kM (kinda undocumented) generates links to frames
.frame x
!analyze -v
!lmi
~
説明
dv /i /t
[doc]dv
-現在のスコープ内のローカル変数の名前と値を表示します/i
-変数の種類を指定します:ローカル、グローバル、パラメーター、関数、または不明/t
-変数のデータ型を表示します?? this
[doc]??
-C++式を評価するthis
-C++このポインターkM
[doc]k
-スタックバックトレースを表示しますM
- DMLモード。フレーム番号は、特定のフレームへのハイパーリンクです。 kMの詳細については、 http://windbg.info/doc/1-common-cmds.html を参照してください。.frame x
[doc].frame x
、次にdv /i /t
を使用します。デフォルトでは、d
はトップフレームからの情報を表示します。!analyze -v
[doc1][doc2-!analyze拡張機能の使用]!analyze
--analyze
拡張子。現在の例外またはバグチェックに関する情報を表示します。拡張機能を実行するには、!
を前に付けることに注意してください。-v
-詳細な出力!lmi
[doc]!lmi
--lmi
拡張子。モジュールに関する詳細情報を表示します。~
[doc]~
-指定されたスレッドまたは現在のプロセスのすべてのスレッドのステータスを表示します。私が最も頻繁に使用する「ヒント」は、その厄介なマウスに頻繁に触れる必要がないようにするものです。 Alt + 1
Alt + 1 コマンドウィンドウにフォーカスを置き、実際にコマンドを入力できるようにし、上矢印が実際にコマンド履歴をスクロールできるようにします。ただし、フォーカスがすでにスクロール可能なコマンド履歴にある場合は機能しません。
ピーブ:フォーカスがソースウィンドウにあるときにキーを押すことが無視されるのはなぜですか? WinDbg内からソースコードを編集できるわけではありません。 Alt + 1 救助へ。
1つの単語(まあ、OK、3つ):[〜#〜] dml [〜#〜]、つまりデバッガーマークアップ言語。
これはWinDbgに最近追加されたものであり、ヘルプファイルには記載されていません。ただし、Windows用のDebuggingToolsのインストールディレクトリの「dml.doc」にいくつかのドキュメントがあります。
基本的に、これはHTMLのような構文であり、デバッガースクリプトに追加して、書式設定、さらに重要なことにリンクに使用できます。リンクを使用して、他のスクリプト、または同じスクリプトを呼び出すことができます。
私の日常業務には、C++ソフトウェアの大部分の汎用オブジェクトとオブジェクト間の関係を提供するメタモデラーのメンテナンスが含まれます。最初は、デバッグを容易にするために、これらのオブジェクトから関連情報を抽出する簡単なダンプスクリプトを作成しました。
これで、DMLを使用して、出力にリンクを追加できるようになりました。これにより、関連するオブジェクトで同じスクリプトを再度呼び出すことができます。これにより、モデルの探索がはるかに高速になります。
簡単な例を次に示します。イントロスペクション下のオブジェクトに、別のオブジェクトへの「参照」と呼ばれる関係があると仮定します。 r @ $ 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> " }
明らかに、これはかなり缶詰の例ですが、これは私にとって本当に貴重です。適切なデータメンバーのために非常に複雑なオブジェクトを探し回るのではなく(通常は1分程度かかり、さまざまなキャストと逆参照が必要でした)、すべてがワンクリックで自動化されます。
.prefer_dml 1
これにより、組み込みコマンドの多く(lm
など)が変更され、コマンドを実行する代わりにリンクをクリックできるDML出力が表示されます。かなり便利です...
.reload /f /o file.dll
(/o
は、あなたが持っているシンボルの現在のコピーを上書きします)
.enable_unicode 1
//すべてのWindowsコンポーネントは内部でUnicodeを使用するため、文字列のデバッガーをデフォルトの nicode に切り替えます。これは非常に便利です。
.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
別の答えはコマンドウィンドウと 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 + up/down コマンド出力ウィンドウの1行をスクロールするには、 Alt + PgDn/PgUp 1画面分スクロールします。
注:WinDbgのバージョンが異なると、ウィンドウとコントロールのクラス名が異なるため、AutoHotkeyが提供するウィンドウスパイツールを使用して、実際のクラス名を最初に見つけることができます。
ロードするスクリプト [〜#〜] sos [〜#〜] .NET Frameworkバージョン(v2.0/v4.0)に基づく:
!for_each_module .if(($sicmp( "@#ModuleName" , "mscorwks") = 0) )
{.loadby sos mscorwks} .elsif ($sicmp( "@#ModuleName" , "clr") = 0)
{.loadby sos clr}
ブレークポイントを使用して新しいワンショットブレークポイントを作成するなど、高度なブレークポイントコマンドを使用するのが好きです。
X86/x64で機能するマネージコードのプラットフォームに依存しないダンプ文字列:
j $ptrsize = 8 'aS !ds .printf "%mu \n", c+';'aS !ds .printf "%mu \n", 10+'
使用例は次のとおりです。
0:000> !ds 00000000023620b8
MaxConcurrentInstances
デバッガーが使用されるコマンドおよび単純な(静的または自動化可能な)ルーチンの場合、実行するすべてのデバッガーコマンドをテキストコマンドファイルに入れ、kd.exeまたはcdb.exeを介してそれを入力として実行できることは非常にクールです、バッチスクリプトなどから呼び出し可能.
WinDbgを起動して手動で行うことなく、これと同じ古いルーチンを実行する必要があるときはいつでもそれを実行します。何を探しているのかわからない場合や、一部のコマンドパラメータを検索/取得するために手動で分析する必要がある場合は、これはうまくいきません。
実行not WinDbgの.heap -stat
コマンドを使用します。それは時々あなたに不正確な出力を与えるでしょう。代わりに、DebugDiagsメモリレポートを使用してください。
正しい番号を取得したら、WinDbgの.heap -flt ...
コマンドを使用できます。