今回はデバッグをやってみようと思います。
デバッグ支援ツールであるWinDbg を使ってどのようなことがわかるのか、試してみます。
概要
NotMyFault を使ってわざとクラッシュを発生させ、出力されたカーネルメモリダンプをWinDbg で分析する。
- メモリダンプの設定
- NotMyFault のダウンロードとテストのクラッシュ発生
- WinDbg のインストールとメモリダンプの分析
作業
(事前作業)Azure 上に環境構築
適当に仮想マシンWindows Server 2022 Datacenter を立てました。
(Spot 割引でデプロイしてます。)
今やBastion のDeveloper SKU が無料で利用できるので、個人の検証は本当にやりやすいですね。
メモリダンプの設定
MS公式ドキュメント を参考に、メモリダンプの設定をします。
仮想マシンに接続して、"sysdm.cpl" と打てばシステムの詳細設定に行けます。
まずは仮想メモリのページング設定を有効にします。"System managed size" という設定にしました(触ったことのある環境でこれになっていた記憶があるので)。
ここでページングが無効になっていると、ダンプファイルが出力されませんでした。
仮想メモリの設定変更には再起動が必要である旨のポップアップが出るので、後で適宜再起動します。"OK" を押しても再起動はかかりません。
そして"Startup and Recovery" (日本語なら「起動と回復」)でカーネルメモリダンプを出力する設定に変更します。
NotMyFault のダウンロードとテストのクラッシュ発生
先ほどのMS公式ドキュメントのリンクからNotMyFault をダウンロードし、解凍します。
数種類の実行ファイルがありますが、"notmyfault64.exe" を実行します。
一番上のテスト項目を選択しCrash をクリックすると、Bastion の反応がなくなり、仮想マシンがフリーズしました。しばらくするとBastion が切断されました。本番環境で起こると本気で頭を抱えるやつです。
とりあえずBastion の"Reconnect" をクリックすると再度サインインできました。
カーネルの出力先を見に行きます。デフォルトでは"C:\Windows\MEMORY.DMP" です。
500MB のメモリダンプファイルができています。
実は2回目のCrash でしたが、MEMORY.DMP は上書きされるため、ダンプファイルは1個だけになりました。
このダンプファイルを料理して、エラーの原因を探るわけですね。
WinDbg のインストールと分析
WinDbg も公式から出ています。この記事が非常に参考になります。
最後のシンボルの設定まで同じ手順でやりました。
x64 のWinDbg じゃないと、プロセスとのattach に失敗します。
そしてWinDbg を管理者で実行します。管理者でないと、"Open Crash Dump" をはじめとする多くのメニューがグレーアウトされ、ファイルを開くことができません。
今回の方法で出力されたファイルは"Open Source File" の対象外のようです。
MEMORY.DMP を開くとこのような画面になります。
下の方にある、"!analyze -y" をクリックすると自動で分析されます。
分析
直接の原因
分析の結果、黄色く網掛けした部分に要約が付けられます。
なにやらIRQL が高いことが原因でcrash した、ということが書かれています。
NotMyFault で指定したテスト項目通りですが、ChatGPT にどういったことなのかを聞いてみます。
IRQL(Interrupt Request Level)が高すぎてクラッシュが発生する原因は、システムが適切に割り込み優先度を管理できない場合に起きます。
割り込み要求レベルは、CPUが割り込みを処理する際に使用する優先度のことです。一般的に、カーネルモードのプロセスが高いIRQLで動作しますが、特定の条件下でアクセス可能なアドレス範囲やメモリ領域に制限があります。この制限を超えて無効なアドレスにアクセスしようとすると、クラッシュ(ブルースクリーン)が発生します。
具体的な原因としては以下が挙げられます:
- ドライバーの問題: 古い、壊れた、または互換性のないドライバーが誤った動作を引き起こすことがあります。
- ハードウェアの不具合: メモリの問題、接続の不良、または過剰な負荷によりエラーが起きる場合があります。
- ソフトウェアのバグ: メモリアクセスが不適切に設計されている場合、システムがクラッシュすることがあります。
これを防ぐには、ドライバーを最新バージョンに更新したり、メモリ診断ツールを使用して問題を検出するのが効果的です。また、Windowsの設定からクラッシュダンプを有効にしておくと、問題解決の手助けになります。
なるほど、メモリの中にはカーネルが正しく働くために保護されている領域(=アドレス)があり、そこを利したいと割り込み要求を出してしまった結果、クラッシュが起きたということですかね。
原因となったプロセス
分析結果の下の方に行くと、原因となったプロセスが判明します。
当然ながら一つのアプリケーションは複数の実行ファイルから構成されています。そのうちどのファイルが悪さをしているか、ここからわかる、ということですね。
Failure ID Hash という項目があり、これはクラッシュ原因をグループ化したときのID だそうで、これをもとにマイクロソフト側は調査できるようになっているようです。
感想
お客さんのクライアント端末でエラーが起きているとき、ダンプファイルがあれば引っこ抜いて作業端末で解析、ということになるか。
私のお客さんは回復環境(行った変更が、シャットダウンや再起動時にすべて元通りになる)のクライアント端末が多いので、調査がしづらい。最初からメモリダンプ設定はきちんとしておくのが吉だと思った。
おしまい。お疲れさまでした。