web-dev-qa-db-ja.com

あなたの好きなWindbgのヒント/トリックは何ですか?

WindbgはWindowsプラットフォーム用の非常に強力なデバッガーであることに気付き、時々新しいことを学びます。仲間のWindbgユーザーは彼らの狂ったスキルのいくつかを共有できますか?

ps:私は気の利いたコマンドを探していません。それらはドキュメントにあります。 windbgでできるとは想像もできなかった何かをするためのヒントを共有してみませんか?例えばプロセスがwindbgで実行されているときに、メモリ割り当てに関する統計を生成する方法。

45
user15071

私のお気に入りはコマンド.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

30
Kris Kumler

クラッシュダンプでのメモリリークを調査するため(ライブプロセスには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.2GB近くのメモリが必要であることを示す次のようなテーブルが表示されます。
   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 )
  • 次に、オブジェクトにvtableがある場合は、dpsコマンドを使用して、DumpHeapEntries.logで0x24バイトのヒープ割り当ての一部を探し、すべてのメモリを使用しているオブジェクトのタイプを確認します。
0:075> dps 3be7f7e8
3be7f7e8  00020006
3be7f7ec  090c01e7
3be7f7f0  0b40fe94 SomeDll!SomeType::`vftable'
3be7f7f4  00000000
3be7f7f8  00000000

それは安っぽいですが、それは動作します:)

27
jturcotte

次のコマンドは、vtablesを使用してC++オブジェクトのスタックを調べる場合、特にリリースビルドを操作するときに、かなりの数の項目が最適化されていない場合に非常に便利です。

dpp esp 範囲


ダンプとして任意のPEファイルをロードできることは素晴らしいことです:

windbg -z mylib.dll


GetLastError()をクエリします。

!gle


これは、一般的なエラーコードのデコードに役立ちます。

!エラーerror_number
20
deemok

私が毎日使用するコマンドのほぼ60%。

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

説明

  1. dv /i /t[doc]
    1. dv-現在のスコープ内のローカル変数の名前と値を表示します
    2. /i-変数の種類を指定します:ローカル、グローバル、パラメーター、関数、または不明
    3. /t-変数のデータ型を表示します
  2. ?? this[doc]
    1. ??-C++式を評価する
    2. this-C++このポインター
  3. kM[doc]
    1. k-スタックバックトレースを表示します
    2. M- DMLモード。フレーム番号は、特定のフレームへのハイパーリンクです。 kMの詳細については、 http://windbg.info/doc/1-common-cmds.html を参照してください。
  4. .frame x[doc]
    1. フレーム番号xに切り替えます。 0はスタックの一番上のフレーム、1は0番目のフレームの下のフレーム1、というように続きます。
    2. スタック上の別のフレームのローカル変数を表示するには、最初にそのフレームに切り替えます-.frame x、次にdv /i /tを使用します。デフォルトでは、dはトップフレームからの情報を表示します。
  5. !analyze -v[doc1][doc2-!analyze拡張機能の使用]
    1. !analyze --analyze拡張子。現在の例外またはバグチェックに関する情報を表示します。拡張機能を実行するには、!を前に付けることに注意してください。
    2. -v-詳細な出力
  6. !lmi[doc]
    1. !lmi --lmi拡張子。モジュールに関する詳細情報を表示します。
  7. ~[doc]
    1. ~-指定されたスレッドまたは現在のプロセスのすべてのスレッドのステータスを表示します。
17
user6105

私が最も頻繁に使用する「ヒント」は、その厄介なマウスに頻繁に触れる必要がないようにするものです。 Alt1

Alt1 コマンドウィンドウにフォーカスを置き、実際にコマンドを入力できるようにし、上矢印が実際にコマンド履歴をスクロールできるようにします。ただし、フォーカスがすでにスクロール可能なコマンド履歴にある場合は機能しません。

ピーブ:フォーカスがソースウィンドウにあるときにキーを押すことが無視されるのはなぜですか? WinDbg内からソースコードを編集できるわけではありません。 Alt1 救助へ。

10
JeffJ

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分程度かかり、さまざまなキャストと逆参照が必要でした)、すべてがワンクリックで自動化されます。

8
  • .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
7
JasonE

別の答えはコマンドウィンドウと Alt1 コマンド入力ウィンドウに焦点を合わせます。マウスを使わずにコマンド出力ウィンドウをスクロールするのが難しいと思う人はいますか?

さて、私は最近 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")

このスクリプトの実行後、次を使用できます Altup/down コマンド出力ウィンドウの1行をスクロールするには、 AltPgDn/PgUp 1画面分スクロールします。

注:WinDbgのバージョンが異なると、ウィンドウとコントロールのクラス名が異なるため、AutoHotkeyが提供するウィンドウスパイツールを使用して、実際のクラス名を最初に見つけることができます。

4
wangzq

ロードするスクリプト [〜#〜] 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}
4
Naveen

ブレークポイントを使用して新しいワンショットブレークポイントを作成するなど、高度なブレークポイントコマンドを使用するのが好きです。

3
Brian

X86/x64で機能するマネージコードのプラットフォームに依存しないダンプ文字列:

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

使用例は次のとおりです。

0:000> !ds 00000000023620b8

MaxConcurrentInstances
1
Naveen

デバッガーが使用されるコマンドおよび単純な(静的または自動化可能な)ルーチンの場合、実行するすべてのデバッガーコマンドをテキストコマンドファイルに入れ、kd.exeまたはcdb.exeを介してそれを入力として実行できることは非常にクールです、バッチスクリプトなどから呼び出し可能.

WinDbgを起動して手動で行うことなく、これと同じ古いルーチンを実行する必要があるときはいつでもそれを実行します。何を探しているのかわからない場合や、一部のコマンドパラメータを検索/取得するために手動で分析する必要がある場合は、これはうまくいきません。

1
David

実行not WinDbgの.heap -statコマンドを使用します。それは時々あなたに不正確な出力を与えるでしょう。代わりに、DebugDiagsメモリレポートを使用してください。

正しい番号を取得したら、WinDbgの.heap -flt ...コマンドを使用できます。

1
Tal