Skip to content

MS_WinDbg

nishi_74322014 edited this page Aug 3, 2026 · 1 revision

WinDbg

概要

WinDbgでできること

  • ダンプ解析やライブデバッグなどができます。
  • ダンプ解析は高度な技術を要しますが、クラッシュダンプに以下のコマンドを実行することで
    スタックトレースを取得しプロセスをクラッシュさせたプログラムの特定などができます。

ダンプの分析例

クラッシュ・ダンプを 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 がプロセスをクラッシュさせていることが解る。

※ このスタックは RtlFreeHeapRtlpLogHeapFailure の並びなので、
ヒープの破壊(二重解放やバッファ オーバーラン)を疑う典型パターン。
再現時はグローバルフラグでページ ヒープを有効にすると特定しやすい。

基本的な使い方

インストール

  • 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)

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)

TEB(Thread Environment Block : スレッド環境ブロック)
カーネルモード:ETHREAD → ユーザモード:TEB(スタック情報 / TLS配列)

コマンド 説明
~ プロセス内の全スレッドのスレッド状態
~0 スレッド0(主スレッド)のスレッド状態
~. カレントのアクティブなスレッド状態
~* 全スレッドのスレッド状態(+追加情報)
~*k 全スレッドのコールスタック
~<thread>s カレントスレッドの設定
!gle ラストエラーの取得
runaway 各スレッドの消費時間を表示
!teb TEB の情報を整形して表示

コールスタックのサイズ取得コマンド

!tebdt 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 から入る。

参考

新しめのトピック

  • Time Travel Debugging(TTD) … 実行をトレースとして記録し、
    時間を巻き戻しながらデバッグできる。再現性の低い不具合の原因特定に有効。

Tags: インフラストラクチャ, Windows, 障害対応, 性能, デバッグ, ツール類

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally