none
イベントログの解析 RRS feed

  • 質問

  • こんにちわ

    久しぶりの投稿になります。

    アプリがイベントID:1000で死んでしまったので解析したいのですが

    障害オフセットというのは、対象DLLのMAPファイルのRva+BaseからPreferred load addressを引いたところと

    して解析してよいのでしょうか。

    たとえば、

    対象DLLが、test.dll

    障害オフセット:0x000cc534

    Preferred load address is 10000000

    の場合、test.mapから

    Rva+Baseが 100cc534を見つければ良いかどうかです。

    このフォーラムで似た質問がないかしらべましたが、見つけることができませんでした。

    検索のAND条件検索方法があれば、もっと効率的に検索できるのですが、わからなく

    質問することにしました。

    よろしくお願いします。

    2018年2月23日 3:56

回答

  • 違うと思います。
    map ファイルから調べる場合は、"Preferred load address" とイベント ログが示す "Base" は関係ない。
    「障害オフセット」が示す値は、該当モジュールがロードされた仮想アドレスの先頭からのオフセット値です。
    例えば、32 ビット (x86) プロセスでは、アプリケーションなどのユーザー モード プログラム モジュール (exe, dll, ocx, etc.) がロードされるのは、0x00000000 ~ 0x7fffffff までの仮想アドレス空間ですが、個々のモジュールがロードされた先頭アドレスを 0 したアドレスが、障害オフセットになります。
    つまり exe や dll などのバイナリ ファイルの先頭からオフセット値を足したアドレスが、クラッシュの発生したアドレスになります。

    ちょうど仮想マシン上に APPCRASH のログがあったので、それを例にすると。。。。
    -------------------------------------------
    障害が発生しているアプリケーション名: procexp.exe、バージョン: 16.21.0.0、タイム スタンプ: 0x590673a5
    障害が発生しているモジュール名: COMCTL32.dll、バージョン: 6.10.16299.214、タイム スタンプ: 0xe040b5ad
    例外コード: 0xc0000005
    障害オフセット: 0x000459a1
    障害が発生しているプロセス ID: 0x4b4
    障害が発生しているアプリケーションの開始時刻: 0x01d39fba43b15370
    障害が発生しているアプリケーション パス: C:\workspace\Tools\ProcessExplorer\v16.21\ProcessExplorer\procexp.exe
    障害が発生しているモジュール パス: C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.16299.214_none_5d78081fa7df188e\COMCTL32.dll
    -------------------------------------------

    上記例は procexp.exe。。。つまり "Process Explorer" ツールがクラッシュした際のエラー ログです。
    このログでは、COMCTL32.dll のオフセット 0x000459a1 で 例外コード 0xc0000005。。。つまり STATUS_ACCESS_VIOLATION のメモリ アクセス違反が発生したことを示しています。
    で、COMCTL32.dll のオフセット 0x000459a1 はどこかというと。。。。
    "Dependency Walker" でも "dumpbin" でも "Visual Studio" でも "WinDBG" でもなんでもいいので、COMCTL32.dll の中身が覗けるツールで中身を確認します。
    例えば WinDBG だと。。。。
    (以下は、カーネル モード デバッグだけど、ユーザー モード デバッグもおんなじ手順)
    ----------------------------------
    <WinDBG で確認する場合>

    0: kd> lmi
    start    end        module name
    01140000 013fd000   procexp    (deferred)
    0f210000 0f32f000   mscordbi   (deferred)
    0f920000 0f93f000   CorperfmonExt   (deferred)
    0fa50000 0fa86000   perfcounter   (deferred)
    .....
    60590000 605d4000   pdh        (deferred)
    60cf0000 60d3e000   thumbcache   (deferred)
    63280000 63375000   MSVCR120_CLR0400   (deferred)
    635a0000 6361d000   mscoreei   (deferred)
    63eb0000 640c1000   COMCTL32   (deferred)  ;; ☆ これ。
    640e0000 64134000   mscoree    (deferred)
    .....

    上記コマンド結果から、COMCTL32.dll の仮想メモリ空間での先頭アドレスは 0x63eb0000。
    「障害オフセット: 0x000459a1」だから、問題個所は 0x63EF59A1。
    0x63EF59A1 は COMCTL32.dll のどこかというと。。。。

    0: kd> x /a COMCTL32!*
    63eb1000          COMCTL32!CLVDrawManager::`vftable' = <no type information>
    63eb1020          COMCTL32!CListView::`vftable' = <no type information>
    63eb1274          COMCTL32!CListView::`vftable' = <no type information>
    63eb12a0          COMCTL32!CListView::`vftable' = <no type information>
    .....
    63ef57a6          COMCTL32!StripAccelerators (<no parameter info>)
    63ef5805          COMCTL32!Header_OnSetOrderArray (<no parameter info>)
    63ef5853          COMCTL32!Header_OnSetItemOrder (<no parameter info>)
    63ef5946          COMCTL32!Header_InitOrderArray (<no parameter info>)  ;; ☆ この中。
    63ef59c0          COMCTL32!Str_GetPtrW (<no parameter info>)
    63ef5a1d          COMCTL32!ScrollBar_GetControlBrush (<no parameter info>)
    .....

    ということで、COMCTL32.dll 内の Header_InitOrderArray() という関数内でメモリ アクセス違反が発生したことがわかります。

    なお、個々のモジュール内の関数の先頭アドレスは、ビルドごとに微妙に変化します。
    調べる際は、イベント ログに残されている "バージョン" と "タイムスタンプ" がちゃんと一致するバイナリ ファイルで確認する必要があります。
    ----------------------------------

    > 検索のAND条件検索方法があれば、もっと効率的に検索できるのですが、
    > わからなく質問することにしました。

    WER でアプリケーション クラッシュ時にプロセス ダンプを生成する設定をして、採取したプロセス ダンプを解析するのが、一番効率的だと思います。

    • 編集済み お馬鹿 2018年2月23日 7:53
    • 回答としてマーク まくお 2018年2月26日 1:04
    2018年2月23日 7:52

すべての返信

  • 違うと思います。
    map ファイルから調べる場合は、"Preferred load address" とイベント ログが示す "Base" は関係ない。
    「障害オフセット」が示す値は、該当モジュールがロードされた仮想アドレスの先頭からのオフセット値です。
    例えば、32 ビット (x86) プロセスでは、アプリケーションなどのユーザー モード プログラム モジュール (exe, dll, ocx, etc.) がロードされるのは、0x00000000 ~ 0x7fffffff までの仮想アドレス空間ですが、個々のモジュールがロードされた先頭アドレスを 0 したアドレスが、障害オフセットになります。
    つまり exe や dll などのバイナリ ファイルの先頭からオフセット値を足したアドレスが、クラッシュの発生したアドレスになります。

    ちょうど仮想マシン上に APPCRASH のログがあったので、それを例にすると。。。。
    -------------------------------------------
    障害が発生しているアプリケーション名: procexp.exe、バージョン: 16.21.0.0、タイム スタンプ: 0x590673a5
    障害が発生しているモジュール名: COMCTL32.dll、バージョン: 6.10.16299.214、タイム スタンプ: 0xe040b5ad
    例外コード: 0xc0000005
    障害オフセット: 0x000459a1
    障害が発生しているプロセス ID: 0x4b4
    障害が発生しているアプリケーションの開始時刻: 0x01d39fba43b15370
    障害が発生しているアプリケーション パス: C:\workspace\Tools\ProcessExplorer\v16.21\ProcessExplorer\procexp.exe
    障害が発生しているモジュール パス: C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.16299.214_none_5d78081fa7df188e\COMCTL32.dll
    -------------------------------------------

    上記例は procexp.exe。。。つまり "Process Explorer" ツールがクラッシュした際のエラー ログです。
    このログでは、COMCTL32.dll のオフセット 0x000459a1 で 例外コード 0xc0000005。。。つまり STATUS_ACCESS_VIOLATION のメモリ アクセス違反が発生したことを示しています。
    で、COMCTL32.dll のオフセット 0x000459a1 はどこかというと。。。。
    "Dependency Walker" でも "dumpbin" でも "Visual Studio" でも "WinDBG" でもなんでもいいので、COMCTL32.dll の中身が覗けるツールで中身を確認します。
    例えば WinDBG だと。。。。
    (以下は、カーネル モード デバッグだけど、ユーザー モード デバッグもおんなじ手順)
    ----------------------------------
    <WinDBG で確認する場合>

    0: kd> lmi
    start    end        module name
    01140000 013fd000   procexp    (deferred)
    0f210000 0f32f000   mscordbi   (deferred)
    0f920000 0f93f000   CorperfmonExt   (deferred)
    0fa50000 0fa86000   perfcounter   (deferred)
    .....
    60590000 605d4000   pdh        (deferred)
    60cf0000 60d3e000   thumbcache   (deferred)
    63280000 63375000   MSVCR120_CLR0400   (deferred)
    635a0000 6361d000   mscoreei   (deferred)
    63eb0000 640c1000   COMCTL32   (deferred)  ;; ☆ これ。
    640e0000 64134000   mscoree    (deferred)
    .....

    上記コマンド結果から、COMCTL32.dll の仮想メモリ空間での先頭アドレスは 0x63eb0000。
    「障害オフセット: 0x000459a1」だから、問題個所は 0x63EF59A1。
    0x63EF59A1 は COMCTL32.dll のどこかというと。。。。

    0: kd> x /a COMCTL32!*
    63eb1000          COMCTL32!CLVDrawManager::`vftable' = <no type information>
    63eb1020          COMCTL32!CListView::`vftable' = <no type information>
    63eb1274          COMCTL32!CListView::`vftable' = <no type information>
    63eb12a0          COMCTL32!CListView::`vftable' = <no type information>
    .....
    63ef57a6          COMCTL32!StripAccelerators (<no parameter info>)
    63ef5805          COMCTL32!Header_OnSetOrderArray (<no parameter info>)
    63ef5853          COMCTL32!Header_OnSetItemOrder (<no parameter info>)
    63ef5946          COMCTL32!Header_InitOrderArray (<no parameter info>)  ;; ☆ この中。
    63ef59c0          COMCTL32!Str_GetPtrW (<no parameter info>)
    63ef5a1d          COMCTL32!ScrollBar_GetControlBrush (<no parameter info>)
    .....

    ということで、COMCTL32.dll 内の Header_InitOrderArray() という関数内でメモリ アクセス違反が発生したことがわかります。

    なお、個々のモジュール内の関数の先頭アドレスは、ビルドごとに微妙に変化します。
    調べる際は、イベント ログに残されている "バージョン" と "タイムスタンプ" がちゃんと一致するバイナリ ファイルで確認する必要があります。
    ----------------------------------

    > 検索のAND条件検索方法があれば、もっと効率的に検索できるのですが、
    > わからなく質問することにしました。

    WER でアプリケーション クラッシュ時にプロセス ダンプを生成する設定をして、採取したプロセス ダンプを解析するのが、一番効率的だと思います。

    • 編集済み お馬鹿 2018年2月23日 7:53
    • 回答としてマーク まくお 2018年2月26日 1:04
    2018年2月23日 7:52
  • 詳しい説明ありがとうございます。

    "Dependency Walker"はよく使うのですが

    使っているモジュールをみるぐらいでした。

    助かりました。投稿してよかったです。

    失礼します。

    • 回答としてマーク まくお 2018年2月26日 1:03
    • 回答としてマークされていない まくお 2018年2月26日 1:04
    2018年2月23日 8:58
  • まくおさん、こんにちは。フォーラム オペレーターの立花です。
    MSDN フォーラムのご利用ありがとうございます。

    ご質問につきましてお馬鹿さんのご返信はお役に立ちましたでしょうか。
    同じ問題でお困りの方のためにも参考となった返信には
    [回答としてマーク] をご設定くださいませ。

    ご協力の程、どうぞよろしくお願いいたします。


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    2018年2月26日 0:10
    モデレータ