3

こんにちは。

ここで少し支援が必要です:

状況:
特定のドライバー バージョン以降、すべての nvidia カード (GeForce 8400GS 以降) でブルー スクリーン オブ デスを引き起こす不明瞭な DirectX 9 アプリケーション (名前とアプリケーションの詳細は質問には関係ありません) があります。この問題は、DirectX 9 呼び出しまたはドライバーのバグをトリガーするフラグによって間接的に引き起こされていると思います。

目標:
問題のあるフラグ/関数呼び出しを追跡し (楽しみのために、これは私の仕事/宿題ではありません)、プロキシ dll を作成してエラー状態を回避したいと考えています。IDirect3D9、IDirect3DDevice9、IDirect3DVertexBuffer9、および IDirect3DIndexBuffer9 のラッパーを提供し、Direct3D 呼び出しの基本的なログ記録/トレースを提供する完成したプロキシ DLL が既にあります。ただし、クラッシュの原因となる機能を特定することはできません。

問題:

  1. ソースコードや技術サポートはありません。援助はなく、誰も問題を解決しません。
  2. カーネルによって生成されたメモリ ダンプは役に立ちませんでした - nv4_disp.dll 内でアクセス違反が発生したようですが、スタック トレースを使用して IDirect3DDevice9 メソッド呼び出しに移動することはできません。また、非同期でバグが発生する可能性もあります。
  3. (主な問題) Direct3D9Device メソッド呼び出しが多数あるため、それらをファイルまたはネットワーク経由で確実にログに記録できません。
    1. ファイルにログインすると、フラッシュしなくても速度が大幅に低下します。そのため、システムのBSODが発生すると、ログの最後の内容がすべて失われます。
    2. ネットワーク経由でのログ記録 (UDP および WINSOck を使用sendto) も大幅な速度低下を引き起こすため、非同期で実行してはなりません (非同期パケットは BSOD で失われます)。加えて、同期的に送信された場合でもパケット (クラッシュ周辺のもの) が失われることがあります。
    3. ルーチンのログ記録によってアプリケーションの速度が低下すると、BSOD が発生する可能性が低くなり、追跡が難しくなります。

質問:
私は通常、ドライバーを作成したり、このレベルのデバッグを行ったりしません。そのため、何か重要なものを見落としているような印象を受けました。カスタム ロギング メカニズムを使用して IDirect3DDevice9 プロキシ DLL を作成するよりも、問題を追跡する簡単な方法があります。 . それは何ですか?このような問題を診断/処理/修正する標準的な方法は何ですか (ソースコードなし、COM インターフェイスメソッドが BSOD をトリガーします)?

ミニダンプ解析(WinDBG) :

ユーザーシンボルの読み込み
アンロードされたモジュールのリストをロードしています
…………
イメージ nv4_disp.dll を読み込めません、Win32 エラー 0n2
*** 警告: nv4_disp.dll のタイムスタンプを確認できません
*** エラー: モジュールのロードは完了しましたが、nv4_disp.dll のシンボルをロードできませんでした
****************************************************** ****************************
* *
* バグチェック分析 *
* *
****************************************************** ****************************

詳細なデバッグ情報を取得するには、!analyze -v を使用します。

バグチェック 1000008E, {c0000005, bd0a2fd0, b0562b40, 0}

おそらく原因: nv4_disp.dll ( nv4_disp+90fd0 )

フォローアップ: MachineOwner
----------

0: kd> !analyze -v
****************************************************** ****************************
* *
* バグチェック分析 *
* *
****************************************************** ****************************

KERNEL_MODE_EXCEPTION_NOT_HANDLED_M (1000008e)
これは非常に一般的なバグチェックです。通常、例外アドレスはピンポイントです
問題の原因となったドライバー/機能。このアドレスを常にメモしておいてください
このアドレスを含むドライバー/イメージのリンク日付と同様に。
一般的な問題として、例外コード 0x80000003 があります。これは難しいことを意味します
コード化されたブレークポイントまたはアサーションにヒットしましたが、このシステムは起動されました
/NODEBUG. 開発者は決して起こらないはずなので、これは起こるべきではありません
リテール コードにハードコーディングされたブレークポイントですが、...
これが発生した場合は、デバッガーが接続されていることを確認してください。
システムが起動されます /DEBUG。これにより、このブレークポイントが
ハプニング。
引数:
Arg1: c0000005、処理されなかった例外コード
Arg2: bd0a2fd0、例外が発生したアドレス
Arg3: b0562b40、トラップ フレーム
Arg4: 00000000

デバッグの詳細:
------------------


EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - "0x%08lx" の命令が "0x%08lx" のメモリを参照しました。メモリを "%s" にすることはできません。

FAULTING_IP:
nv4_disp+90fd0
bd0a2fd0 39b8f8000000 cmp dword ptr [eax+0F8h],edi

TRAP_FRAME: b0562b40 -- (.trap 0xffffffffb0562b40)
エラーコード = 00000000
eax=00000808 ebx=e37f8200 ecx=e4ae1c68 edx=e37f8328 esi=e37f8400 edi=00000000
eip=bd0a2fd0 esp=b0562bb4 ebp=e37e09c0 iopl=0 nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202
nv4_disp+0x90fd0:
bd0a2fd0 39b8f8000000 cmp dword ptr [eax+0F8h],edi ds:0023:00000900=????????
デフォルトのスコープのリセット

CUSTOMER_CRASH_COUNT: 3

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0x8E

LAST_CONTROL_TRANSFER: bd0a2e33 から bd0a2fd0 へ

STACK_TEXT:  
警告: スタック アンワインド情報は利用できません。次のフレームは間違っている可能性があります。
b0562bc4 bd0a2e33 e37f8200 e37f8200 e4ae1c68 nv4_disp+0x90fd0
b0562c3c bf8edd6b b0562cfc e2601714 e4ae1c58 nv4_disp+0x90e33
b0562c74 bd009530 b0562cfc bf8ede06 e2601714 win32k!WatchdogDdDestroySurface+0x38
b0562d30 bd00b3a4 e2601008 e4ae1c58 b0562d50 dxg!vDdDisableSurfaceObject+0x294
b0562d54 8054161c e2601008 00000001 0012c518 dxg!DxDdDestroySurface+0x42
b0562d54 7c90e4f4 e2601008 00000001 0012c518 nt!KiFastCallEntry+0xfc
0012c518 00000000 00000000 00000000 00000000 0x7c90e4f4


STACK_COMMAND: kb

FOLLOWUP_IP:
nv4_disp+90fd0
bd0a2fd0 39b8f8000000 cmp dword ptr [eax+0F8h],edi

SYMBOL_STACK_INDEX: 0

SYMBOL_NAME: nv4_disp+90fd0

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: nv4_disp

IMAGE_NAME: nv4_disp.dll

DEBUG_FLR_IMAGE_TIMESTAMP: 4e390d56

FAILURE_BUCKET_ID: 0x8E_nv4_disp+90fd0

バケット_ID: 0x8E_nv4_disp+90fd0

フォローアップ: MachineOwner
4

3 に答える 3

6

解決策を見つけました。

問題:
メッセージ (ファイルにダンプされたとき) が bsod 中に消えてしまうため、ログは信頼できません。

解決策:
ファイルまたはネットワーク経由でログを記録する代わりに、BSOD で完全な物理メモリ ダンプを生成し、すべてのメッセージを任意のメモリ バッファに記録するようにシステムを構成します。それはより速くなります。システムがクラッシュすると、メモリ全体がファイルにダンプされ、WinDBG のdt(デバッグ シンボルがある場合) コマンドを使用してログ ファイル バッファーの内容を表示するか、ログ ファイルを検索して見つけることができます。 「メモリ」ビューを使用してメモリに保存されます。

std::strings の循環バッファーを使用してメッセージを格納し、const char* の配列を分離して WinDBG で読みやすくしましたが、単純に巨大な char 配列を作成し、その中にすべてのメッセージをプレーンテキストで格納することもできます。

詳細:
winxp でのプロセス全体:

  1. 最小ページ ファイル サイズが、RAM の合計量 + 1 メガバイト以上であることを確認してください。(「マイ コンピュータ」を右クリック -> プロパティ -> 詳細設定 -> パフォーマンス -> 詳細設定 -> 変更)
  2. BSOD で完全なメモリ ダンプを生成するようにシステムを構成します ([マイ コンピュータ] -> [プロパティ] -> [詳細設定] -> [起動と回復] -> [設定] -> [デバッグ情報を書き込む] を右クリックします。[完全メモリ ダンプ] を選択し、必要なパスを指定します)。
  3. ディスク (ファイルが書き込まれる場所) に必要な空き容量 (システムの RAM の合計容量) があることを確認します。
  4. デバッグ シンボルを使用して app/dll (ログを記録するもの) をビルドし、BSOD をトリガーします。
  5. メモリ ダンプが完了するまで待ってから、再起動します。システムがメモリ ダンプを書き込んで再起動している間、ドライバ開発者を罵倒してください。
  6. 生成された MEMORY.DMP システムを安全な場所にコピーして、システムが再度クラッシュしてもすべてが失われないようにします。
  7. Windbg を起動します。
  8. メモリ ダンプを開きます ([ファイル] -> [クラッシュ ダンプを開く])。
  9. 何が起こったのかを確認したい場合は、!analyze -vコマンドを使用してください。
  10. 次のいずれかの方法を使用して、ログに記録されたメッセージを格納するメモリ バッファにアクセスします。
    1. グローバル変数の内容を表示するにはdt module!variable、"module" がライブラリの名前 (*.dll を除く)、"variable" が変数の名前である場合に使用します。ワイルドカードを使用できます。なしでアドレスを使用できますmodule!variable
    2. グローバル変数の 1 つのフィールドの内容を表示するには (グローバル変数が構造体の場合)、dt module!variable field「フィールド」が変数メンバーである場所を使用します。
    3. 変数 (配列と部分構造の内容) の詳細を表示するには、dt -b module!variable fieldまたはdt -b module!variable
    4. シンボルがない場合は、メモリ ウィンドウを使用して「ログ ファイル」を検索する必要があります。

この時点で、メモリに保存されたログの内容を確認できるほか、システムがクラッシュした瞬間のシステム全体のスナップショットを取得できます。

また...

  1. システムをクラッシュさせたプロセスに関する情報を表示するには、 を使用します!process
  2. ロードされたモジュールを確認するにはlm
  3. スレッドに関する情報については、出力!thread idで見た id が 16 進数の ID である場所があります。!process
于 2011-09-30T22:14:11.097 に答える
6
nv4_disp+90fd0
bd0a2fd0 39b8f8000000    cmp     dword ptr [eax+0F8h],edi

これが重要な部分です。これを見ると、eax が無効である可能性が最も高いため、無効なメモリ アドレスにアクセスしようとしています。

あなたがする必要があるのは、IDA に nv4_disp.dll をロードすることです (無料版を入手できます)。問題のある命令に直接移動する必要があります(セクション構造によって異なります)

ここから、制御フロー、および eax の設定方法と使用方法を分析できます。優れたカーネル レベルのデバッガーを使用している場合は、このアドレスにブレークポイントを設定して、ヒットさせてみることができます。

関数を分析して、関数が何をするのか、その時点で eax が何を指しているのか、実際に何を指しているのか、そしてその理由を理解しようとする必要があります。これは難しい部分であり、リバース エンジニアリングの難しさとスキルの大きな部分です。

于 2011-09-29T04:02:37.897 に答える
1

クラッシュは、不良ポインターまたはヒープの破損が原因である可能性があります。これは、クラッシュがメモリ解放関数 ( DxDdDestroySurface) で発生するため、わかります。サーフェスを破棄することは絶対に必要なことです。これをスタブ化するだけではいけません。プログラムが終了してもサーフェスは解放されます。カーネル内で無効にすると、カード上のメモリが不足します。非常に速く、そのようにクラッシュします。

どのようなイベント シーケンスがこのヒープの破損につながるのかを突き止めようとすることはできますが、ここに特効薬はありません。問題のあるドライバーのバージョンの前後にも!)

于 2011-09-30T22:20:41.167 に答える