2012年2月9日木曜日

.NETプログラム例外落ちイベント(CLR20r3)を読み取る

.NETで作ったプログラムが例外落ちしますと、イベントビューアに記録が残ります。この情報をどのようにして読み取っていくか、につきまして。例:

ログの名前: Application
ソース: Windows Error Reporting
日付: 2012/02/09 14:27:58
イベント ID: 1001
タスクのカテゴリ: なし
レベル: 情報
キーワード: クラシック
ユーザー: N/A
コンピューター: DD5
説明:
障害バケット 、種類 0
イベント名: CLR20r3
応答: 使用不可
Cab ID: 0

問題の署名:
P1: wazato.exe
P2: 1.0.0.0
P3: 4f335959
P4: wazato
P5: 1.0.0.0
P6: 4f335959
P7: 4
P8: 10
P9: wazato.WazatoException
P10:


P1からP9までの意味する所につきましては、情報源が見つかりました。

How do you read a runtime (CLR20r3) error report?
http://social.msdn.microsoft.com/Forums/ar/clr/thread/eabef2f0-631b-41b8-91f1-431bbcb9b4df

clr20r3 from a window's service calling a dot net dll
http://social.msdn.microsoft.com/forums/en-US/clr/thread/3fca118c-cbba-4be8-ac64-02af7a4ec3ca/

要約しますと:

P1: exeファイル名の名前(32文字制限付き)
P2: exeファイルのアセンブリ バージョン
P3: exeファイルのタイムスタンプ(16進数)… new DateTime(1970, 1, 1).AddSeconds(P3).ToLocalTime()
P4: 欠陥アセンブリの名前(64文字制限付き)
P5: 欠陥アセンブリのバージョン
P6: 欠陥アセンブリのタイムスタンプ(16進数)… new DateTime(1970, 1, 1).AddSeconds(P6).ToLocalTime()
P7: 欠陥アセンブリの型とメソッド(16進数)。MethodDef
P8: 欠陥メソッドのIL命令(16進数)。オフセット
P9: スローされた例外の種類(32文字制限付き)

P9の文字列は長い場合、末尾のExceptionを省略してみたり、160ビット位(32進数×32桁)のハッシュ値にされたりしてしまいます。

ハッシュ関数はSHA-1か何かかと思いますが、未だ計算方法は判っていません。

P7とP8につきまして:

ildasmを使います。

[ファイル]→[ダンプ]で、.ilファイルを出力できます。このファイルを見ながら検証していきます。

P7が4。
上から見て4番目のメソッドかなとも思いますが、確証は有りません。
MemberInfo.MetadataToken の一部を抽出している模様です。
Assembly.LoadFile(P4_Assembly).GetModules()[0].ResolveMethod(0x06000004);

このようなコードで、対象メソッドの情報がゲットできるようです。

ildasm を用いる場合、Ctrl+M または [表示]→[メタ情報]→[表示!] で、一覧表示。
06000004 を探します。
TypeDef #1 (02000002)
-------------------------------------------------------
    TypDefName: wazato.Program  (02000002)
    Flags     : [NotPublic] [AutoLayout] [Class] [Abstract] [Sealed] [AnsiClass] [BeforeFieldInit]  (00100180)
    Extends   : 01000001 [TypeRef] System.Object
    Method #1 (06000001) 
    -------------------------------------------------------

    ...


    Method #4 (06000004) [ENTRYPOINT]
    -------------------------------------------------------
        MethodName: Main (06000004)
        Flags     : [Private] [Static] [HideBySig] [ReuseSlot]  (00000091)
        RVA       : 0x00002056
        ImplFlags : [IL] [Managed]  (00000000)
        CallCnvntn: [DEFAULT]
        ReturnType: Void
        No arguments.
        CustomAttribute #1 (0c000010)
        -------------------------------------------------------
            CustomAttribute Type: 0a000010
            CustomAttributeName: System.STAThreadAttribute :: instance void .ctor()
            Length: 4
            Value : 01 00 00 00                                      >                <
            ctor args: ()


P8が10。IL_0010を探します。丁度throwしているのが判ります。

...
  .method private hidebysig static void A() cil managed
...
  .method private hidebysig static void B() cil managed
...
  .method private hidebysig static void C() cil managed
...
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
    // コード サイズ       17 (0x11)
    .maxstack  8
    IL_0000:  call       void [System.Windows.Forms]System.Windows.Forms.Application::EnableVisualStyles()
    IL_0005:  ldc.i4.0
    IL_0006:  call       void [System.Windows.Forms]System.Windows.Forms.Application::SetCompatibleTextRenderingDefault(bool)
    IL_000b:  newobj     instance void wazato.WazatoException::.ctor()
    IL_0010:  throw 
  } // end of method Program::Main

ちなみにC#のソースコードはこうです:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace wazato {
    static class Program {
        static void A() { }
        static void B() { }
        static void C() { }
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            throw new WazatoException();       
        }
    }
    public class WazatoException : ApplicationException {
    }
}

[2022/06/01 追記]

.NET Framework 4.x のアプリで、クラッシュダンプを作成する方法がわかりました。

Visual Studio 2022 にて、クラッシュダンプファイルの内容を確認できました。

WinDbg のコマンドライン ツール CDB を使って、クラッシュダンプの stack trace を覗く方法です。


0 件のコメント:

コメントを投稿