-
Notifications
You must be signed in to change notification settings - Fork 0
MS_WinDbg
-
TOP > トラブルシュート > 障害対応に使用するツールの一覧
- WinDbg
- UMDH
- ダンプの概要(種類と取得)
- ダンプ解析やライブデバッグなどができます。
- ダンプ解析は高度な技術を要しますが、クラッシュダンプに以下のコマンドを実行することで
スタックトレースを取得しプロセスをクラッシュさせたプログラムの特定などができます。
クラッシュ・ダンプを WinDbg の k コマンドで確認した所、
以下の様にスタックトレースが出力された。
ChildEBP RetAddr
1c2fd0b8 774a5620 ntdll!KiFastSystemCallRet
1c2fd0bc 774d3c62 ntdll!NtWaitForSingleObject+0xc
1c2fd140 774d3d4b ntdll!RtlReportExceptionEx+0x14b
...
1c2fd668 774afc25 ntdll!RtlpLogHeapFailure+0xa1
1c2fd694 763b9a26 ntdll!RtlFreeHeap+0x60
1c2fd6a8 76079c03 kernel32!HeapFree+0x14
Unable to load image C:\YYYYY\XXXXX.dll, Win32 error 0n2
*** WARNING: Unable to verify timestamp for XXXXX.dll
*** ERROR: Module load completed but symbols could not be loaded for XXXXX.dll
※ これにより、C:\YYYYY\XXXXX.dll がプロセスをクラッシュさせていることが解る。
※ このスタックは RtlFreeHeap → RtlpLogHeapFailure の並びなので、
ヒープの破壊(二重解放やバッファ オーバーラン)を疑う典型パターン。
再現時はグローバルフラグでページ ヒープを有効にすると特定しやすい。
-
WinDbg(新版):Microsoft Store または
winget install Microsoft.WinDbgで入手する。 -
Windows SDK 同梱版:Windows SDK のインストール時に
「Debugging Tools for Windows」を選択する。
Visual Studio のインストールでは WinDbg は入らないため、別途インストールが必要。
補足(最新化): 原文の「WinDbg Preview」は preview が外れ、 WinDbg(旧 WinDbg Preview)が正式版となっている。 旧来の
windbg.exe(Debugging Tools for Windows 同梱)は WinDbg Classic として残るが、新規は新版を使えばよい。
- ダンプ解析は同一CPUアーキテクチャのPCを利用する。
- システム・モジュールのシンボルをインストールしてシンボルへのパスを指定する。
- 自作モジュールについては PDB ファイルを配置(PDB ファイルへのパス指定)
- シンボル サーバの指定は Symbol File Path に下記を設定する。
SRV*c:\websymbols*https://msdl.microsoft.com/download/symbols
-
lmコマンドを実行して、モジュールが名前解決(アドレス → モジュール名)されるか確認する。
※ 現行の WinDbg では .symfix と .reload を実行すれば
上記のシンボル サーバ設定が自動で入る。
- MS の Windows プロダクト・チームも利用している。
- VS デバッガは言語+ブレークの機能が中心だが、
WinDbg はカーネルモードのプロセス、スレッドスタックの分析まで可能。
ユーザモードのデバッグでも、カーネルモードのデバッグでも利用可能。
- 裏で動いているデバッグ・エンジン(
dbgeng.dll→ COM)は変わらない。 - カーネル・モードは使用する拡張コマンドが違うだけ。
- なお、
dbgeng.dllは他の色々なツールで利用されている
(ntsd.exe / cdb.exe / kd.exe / dbgsrv.exe / userdump.exe / drwtsn32.exe)。
非侵入的アタッチが可能。
| 侵入的アタッチ | 非侵入的アタッチ | |
|---|---|---|
| API | DebugActiveProcess |
OpenProcess |
| break-in スレッド | 生成される | 生成されない |
| 対象スレッド | 実行制御できる | すべて凍結状態 |
| メモリの確認・変更 | 可 | 可 |
| ブレークポイント | 可 | 不可 |
| ステップ実行 | 可 | 不可 |
| デタッチ | XP以前は対象が終了する | 対象を終了せずデタッチ可 |
| 同時アタッチ | プロセスに1つだけ | 複数可(+侵入的1つ) |
こんな場合に便利…
- Visual Studio などの侵入的デバッガでアプリケーションをデバッグ中でも、
WinDbg を非侵入的デバッガとしてアタッチし、追加の情報を取得できる。 - デバッグ対象アプリケーションが完全に凍結しており、
真のアタッチに必要な break-in スレッドが生成されない場合(=ハング時)。
| 種類 | 用途 | 例 |
|---|---|---|
| 標準コマンド | プロセスのデバッグに使われる |
k, lm, g
|
| メタコマンド(ドットコマンド) | デバッガの制御に使われる |
.sympath, .cls, .lastevent, .detach
|
拡張コマンド(!) |
拡張DLLで提供。WinDbg が強力な理由 |
!analyze, !address, !handle, !peb
|
拡張DLL とそのヘルプ
!exts.help 一般的な拡張コマンド
!uext.help ユーザーモードの拡張コマンド(OS非依存)
!ntsdexts.help ユーザーモードの拡張コマンド(OS依存)
!kdexts.help カーネルモードの拡張コマンド
!logexts.help ログ取得拡張コマンド
!sos.help マネージコードのデバッグ
!wow64exts.help WOW64 デバッガ拡張
| コマンド | 説明 |
|---|---|
!vm |
システムの仮想メモリ使用統計要約情報を表示 |
!process 0 0 |
プロセス一覧・概要 |
!process 0 1 |
プロセス一覧・詳細 |
!process <addr or pid> 7 |
プロセス詳細・スタックトレース |
PEB(Process Environment Block : プロセス環境ブロック)
カーネルモード:EPROCESS → ユーザモード:PEB
- イメージ基本情報 / プロセスヒープの情報 / 環境変数、コマンドライン引数 / DLL検索パス
| コマンド | 説明 |
|---|---|
!peb |
PEB の情報を整形して表示 |
dt nt!_PEB <addr> |
PEB の全ダンプ |
lm |
ロードモジュール、アンロードモジュールの一覧 |
lmvm kernel32 |
kernel32 の詳細を出力 |
!lmi kernel32 |
上記の拡張コマンド版 |
!dlls |
ロードモジュールの一覧、ローダに関する情報 |
!dh kernel32 |
kernel32 のヘッダを表示 |
TEB(Thread Environment Block : スレッド環境ブロック)
カーネルモード:ETHREAD → ユーザモード:TEB(スタック情報 / TLS配列)
| コマンド | 説明 |
|---|---|
~ |
プロセス内の全スレッドのスレッド状態 |
~0 |
スレッド0(主スレッド)のスレッド状態 |
~. |
カレントのアクティブなスレッド状態 |
~* |
全スレッドのスレッド状態(+追加情報) |
~*k |
全スレッドのコールスタック |
~<thread>s |
カレントスレッドの設定 |
!gle |
ラストエラーの取得 |
runaway |
各スレッドの消費時間を表示 |
!teb |
TEB の情報を整形して表示 |
!teb → dt ntdll!_TEB DeallocationStack <addr> → !address esp の順に確認し、
-
? stackbase - stacklimit… スタックがコミットしたバイト数 -
? stackbase - DeallocationStack… スタックの予約したバイト数
| 用語 | 意味 |
|---|---|
| StackBase | スタックの始点 |
| StackLimit | スタックの使用量(コミット・サイズ) |
| DeallocationStack | スタックの終点(予約サイズ) |
※ ? コマンドは、さまざまな計算が可能。また10進数の表示ができる。
※ スレッドのスタックも参照。
| コマンド | 説明 |
|---|---|
!uniqstack |
プロセス内の全スレッドのコールスタック |
!findstack MySymbol 2 |
MySymbol を含む全コールスタックを探して表示 |
k |
カレントスレッドのコールスタックを表示 |
kP |
+ 呼び出しの全パラメータ |
kf |
+ 隣接フレームとの距離 |
kv |
+ FPO 情報と呼び出し規約を表示 |
kb |
+ 先頭3つのパラメータを表示 |
移行メモ(誤記): 原文の「FOP(frame pointer omission)」は FPO(Frame Pointer Omission)の綴り誤り。
| コマンド | 説明 |
|---|---|
d / dd / da / du
|
メモリ表示(既定 / ダブルワード / ASCII / UNICODE) |
f |
メモリを指定の値で埋める |
!vprot <addr> |
指定アドレスの仮想メモリ保護情報 |
!address <addr> |
指定アドレスのメモリ情報(タイプ、保護、使用状況など) |
!address -RegionUsageStack |
プロセスの全スレッドスタック領域を表示 |
dds / ddp
|
メモリ内容と対応するシンボル / 参照先メモリ内容 |
下記コマンドを実行する場合、グローバルフラグを設定する。
| コマンド | 説明 |
|---|---|
!heap -h |
ヒープのインデックスの範囲(開始-終了アドレス)を一覧 |
!heap -s 0 |
全ヒープの要約(=予約メモリ、コミットメモリ) |
!heap -flt s <Size> |
指定サイズに一致する割り当てを表示 |
!heap -stat -h 0 |
メモリ割り当てサイズ毎に使用状況の統計を表示 |
!heap -l |
デバッガにリーク原因とされた heap エントリを知らせる |
!heap -p |
Gflags の設定と、ヒープハンドルの一覧 |
!heap -p -all |
プロセスの全ヒープの割り当ての詳細 |
!heap -p -a <heapentryaddr> |
該当ヒープ割り当ての詳細(スタックトレース) |
※ リークのチェックの際は !heap -l で取得した heapentryaddr(Entry 列)を指定する。
※ ヒープ も参照。
| コマンド | 説明 |
|---|---|
.sympath / .sympath+ XY
|
シンボルの検索パスの取得と設定/追加 |
.symfix |
公式シンボル サーバを自動設定 |
!sym noisy |
シンボルの検索過程を表示 |
.reload |
シンボル情報を読み直す |
x kernel32!*LoadLibrary* |
指定文字列を含むシンボルを一覧表示 |
| コマンド | 説明 |
|---|---|
!analyze -v |
クラッシュ分析ヒューリスティックにより現在の例外に関する詳細情報を表示 |
~ |
スレッド一覧表示 |
~*k |
全スレッドのコール・スタックを表示 |
~<thread>s |
カレント・スレッドの設定 |
kn / .frame / dv / dt
|
現在のコール・スタックの引数、ローカル変数を確認 |
| コマンド | 説明 |
|---|---|
!PrintException -nested |
現在の例外(内部例外を含む)の詳細を表示 |
!threads |
スレッドの状態を表示(マネージ/アンマネージ、ファイナライザ等) |
!clrstack -a |
マネージドコードのコールスタック(~*k より詳しい) |
!clrstack -a に表示される引数・ローカル変数は、
- 変数が String である場合、
!DumpObjに指定すれば文字列情報を取得できる。 - 変数が配列である場合、
!DumpArrayで各要素の情報を取得できる。 - 参照渡しの引数である場合、
ddでアドレス情報を確認できる。
※ SOS 拡張の詳細は.NETのメモリ・リークを参照。
- プロセスのスレッドのヒープの使用状況を確認できる。
- ログを比較することで、どのスタックトレースがメモリ・リークに関係しているかを絞り込める。
- Java や .NET のマネージ・リソースのメモリ・リークは検出できないことがあるので注意する。
これは、マネージド・ヒープがガベージ・コレクタによって管理されているため。
ヒープ内の利用状況に関する情報を取得したい場合、
ダンプ取得の前にグローバルフラグを設定する。
※ リークを疑っている場合、同じダンプを見ても解らないので、差分を見る。
若しくは、UMDHツールを使用してログ出力しヒープの差分を確認する。
| コマンド | 説明 |
|---|---|
!address |
プロセスの仮想アドレス空間の全情報を表示 |
!address -summary |
プロセスの仮想アドレス空間のサマリを表示 |
!address -RegionUsageStack |
プロセスの全スレッドのスタック領域を表示 |
ただし、ヒープ・マネージャに管理されるヒープ内のメモリ利用状況に関する情報は取得できない。
- ヒープリーク検出(ページ ヒープ)…
!heap -p -aで stacktrace を出力 - ユーザモード スタックトレース データベース …
!heap -aで stacktrace を出力
準備と取得はカーネル・ダンプを参照。分析は !analyze -v から入る。
- Debugger Commands - Microsoft Learn
- WinDbg のインストール - Microsoft Learn
- WinDbg. From A to Z!
- 技術-Windows-WinDbgメモ - Glamenv-Septzen.net
-
Time Travel Debugging(TTD) … 実行をトレースとして記録し、
時間を巻き戻しながらデバッグできる。再現性の低い不具合の原因特定に有効。
Tags: インフラストラクチャ, Windows, 障害対応, 性能, デバッグ, ツール類
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。