この世の中には、ダンプを解析するためにcrashコマンドという大変便利なツールが存在しています。本講座では、ありがたくcrashコマンドを使用させてもらうことにします。
crashコマンドは、インストールCDにも入っています(crash-4.0-3.14.i386.rpm)が、最新版が下記のURLからダウンロードできるようになっています。
http://people.redhat.com/anderson/

crashコマンドは、後方互換を保ちながら開発が続けられていますので、常に最新版を使用して問題ありません。ここでは、この原稿執筆時点の最新版であるcrash-4.0-4.7を使用することにします。上記のURLには、src rpm パッケージとtarballが置いてありますので、お好きな方をダウンロードしてください。どちらもソースコードの状態ですので、展開後、コマンドを作る必要があります。それには、トップディレクトリで「make」と打つだけでお終いです(ただし、結構時間はかかります)。
crashコマンドの作成と使用には一点注意事項があります。それは、ダンプを取ったシステムと同じCPUアーキテクチャのシステムで作成、使用する必要があるということです。i386システムのダンプを解析したい場合は、i386システムで作成したcrashコマンドを使用し、i386システムで解析を行ってください。(つまり、crashコマンドは、クロス環境で解析できるようには作られていません。)
ダンプを取ったシステムと解析を行うシステムは、CPUアーキテクチャさえ同じであれば、ディストリビューションのバージョン・レベルやカーネルのバージョン・レベルは異なっていても構いません。ただし、実は、後で分かることですが、同じものにしておくと一番楽ができます。

crashコマンドの実行

ダンプを解析するためには、crashコマンドとダンプだけでは不足で、もう少し用意するものがあります。それをこれから説明していくわけですが、そろそろ説明だけでは飽きてきたところでしょうから、コマンドの実行をしてみましょう。第2回で用意したサンプル(※1)を使用します。crashコマンドを以下のように実行します。

# crash System.map-2.6.18-9.el5 vmlinux vmcore

すると、以下のように表示され、crashコマンドのセッションが始まります。(※2)

crashコマンドのセッション

crash 4.0-4.7
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006 IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to  see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.
GNU gdb 6.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
  SYSTEM MAP: System.map-2.6.18-8.el5
DEBUG KERNEL: vmlinux (2.6.18-8.el5)
    DUMPFILE: vmcore
        CPUS: 2
        DATE: Wed Sep  5 09:47:30 2007
      UPTIME: 18 days, 18:21:41
LOAD AVERAGE: 0.00, 0.04, 0.01
       TASKS: 101
    NODENAME: oda
     RELEASE: 2.6.18-8.el5
     VERSION: #1 SMP Fri Jan 26 14:15:21 EST 2007
     MACHINE: i686  (2394 Mhz)
      MEMORY: 1 GB
       PANIC: "SysRq : Trigger a crashdump"
         PID: 17412
     COMMAND: "bash"
        TASK: f7f8faa0  [THREAD_INFO: d7cfd000]
         CPU: 1
       STATE: TASK_RUNNING (SYSRQ)
crash>

デバッグ情報付きのvmlinux

crashコマンドの起動時にダンプの他にSystem.mapファイルとvmlinuxを指定しています。それぞれの役割をこれから説明していきますが、vmlinuxの方が重要なので、こちらから始めましょう。
vmlinuxはカーネルをビルドしたとき、カーネルソースツリーのトップディレクトリにできるカーネルのELF形式バイナリです。大事なのは、crashコマンドが必要とするのは、デバッグ情報付きのvmlinuxだということです。
デバッグ情報付きのvmlinuxを得るためには、カーネルのビルド時にgccのオプションとして、-gを追加します。具体的には、カーネルソースツリーのトップディレクトリにあるMakefileに下記のような修正を加えます。

最近のカーネルでは、わざわざ手で修正しなくても、コンフィグメニューで選択できるようになっています。上記Makefile中に以下の部分があれば、OKです。

最近のカーネルでは、わざわざ手で修正しなくても、コンフィグメニューで選択できるようになっています。上記Makefile中に以下の部分があれば、OKです。

コンフィグメニューの「Kernel hacking」の「Kernel debugging」をオンにし、「Compile the kernel with debug info」をオンにします。
当然のことですが、デバッグ情報付き vmlinux を作るときのコンフィグレーションは、ダンプを取ったシステムのカーネルのものを同じにしておく必要があります(CONFIG_DEBUG_INFO は除く)。
gccの-gオプションを付けることで、vmlinuxがどう違ってくるのか、少し確認しておきましょう。-g付き、-gなし、それぞれのvmlinuxをreadelf -Sコマンドで比べて見ると、-g付きの方に以下のセクションが追加されていることが分かります。

-gオプションにより追加されたセクション

[59] .debug_aranges PROGBITS 00000000 31d7b2 009250 00 0 0 1
[60] .rel.debug_arange REL 00000000 2c39b98 0058d0 08 76 59 4
[61] .debug_pubnames PROGBITS 00000000 326a02 02eb01 00 0 0 1
[62] .rel.debug_pubnam REL 00000000 2c3f468 001d88 08 76 61 4
[63] .debug_info PROGBITS 00000000 355503 2092e0c 00 0 0 1
[64] .rel.debug_info REL 00000000 2c411f0 e887d0 08 76 63 4
[65] .debug_abbrev PROGBITS 00000000 23e830f 104d80 00 0 0 1
[66] .debug_line PROGBITS 00000000 24ed08f 1b8d8b 00 0 0 1
[67] .rel.debug_line REL 00000000 3ac99c0 002f80 08 76 66 4
[68] .debug_frame PROGBITS 00000000 26a5e1c 086bc4 00 0 0 4
[69] .rel.debug_frame REL 00000000 3acc940 0310c0 08 76 68 4
[70] .debug_str PROGBITS 00000000 272c9e0 0c919a 01 MS 0 0 1
[71] .debug_loc PROGBITS 00000000 27f5b7a 2f1ab1 00 0 0 1
[72] .rel.debug_loc REL 00000000 3afda00 1f8960 08 76 71 4
[73] .debug_ranges PROGBITS 00000000 2ae762b 065900 00 0 0 1
[74] .rel.debug_ranges REL 00000000 3cf6360 05cdc0 08 76 73 4

これがデバッグ情報に当たります。この中には、構造体の形の情報など、いろいろと役に立つ情報が入っています。
RHELでは、あらかじめデバッグ情報付きのvmlinuxをrpmパッケージで用意してくれています。RHEL5の場合は、以下のパッケージになります(同時にインストールします)。

 

  • kernel-debuginfo-common-2.6.18-8.el5.i686.rpm
  • kernel-PAE-debuginfo-2.6.18-8.el5.i686.rpm

先に示したcrashコマンドのURLには、RHELのあらゆるバージョン・アップデートに対する「debuginfo」パッケージが用意されています。先ほどのURLにアクセスし、「RHEL debuginfo RPMs」と書かれたリンクにアクセスしてみてください。
上記のパッケージをインストールすると、デフォルトでは、/usr/lib/debug/lib/modules/<kerenl version>ディレクトリの下にインストールされます。カーネル本体(vmlinux)だけでなく、全カーネルモジュールに関してもデバッグ情報付きのものが入っています。
実は、サンプルに入っていたvmlinuxはここから持ってきたものです。

System.map

次にSystem.mapファイルの説明に移ります。System.mapファイルは、シンボルのアドレスが記されたファイルです。crashコマンドは、System.mapファイルが指定されると、それをシンボルのアドレスとして使用します。シンボルのアドレスは、vmlinuxからも分かります。そもそも、System.mapファイルは、vmlinuxからnmコマンドを使用してシンボルとアドレスを取り出したものです。では、なぜSystem.mapファイルを指定するかというと、-gを付けたときと付けないときで、微妙にアドレスが異なる場合がある、という事実に基づいています。では、最初から-g付きで作っていれば、System.mapファイルはいらないのではないかと思われるかもしれません。実はそのとおりです。
RHEL5のカーネルのソースパッケージに入っているコンフィグレーションを見ると「CONFIG_DEBUG_INFO=y」になっていますので、最初から-g付きでカーネルがビルドされています。そのため、サンプルのダンプを解析するには、System.mapファイルを省略して、以下のように実行することができます。

# crash vmlinux vmcore

KERNEL: vmlinux <===
DUMPFILE: vmcore <===
CPUS: 2
DATE: Wed Sep 5 09:47:30 2007

crash>

指定したファイルの違いにより、最初の情報のところが異なっていますので確認しておいてください。
参考までに、System.mapファイルの代わりにvmlinux(-gなし。元々のカーネル作成時のもの)を指定することもできます。

# crash vmlinux(-gなし) vmlinux(-gあり) vmcore

使う場合はないと思いますが、知っておくと後で役に立つかもしれません。
補足として、もうひとつcrashコマンドの実行形式を紹介しておきます。
お使いの(RHEL)システムのカーネルのdebuginfoパッケージがインストール済みであれば、以下のように何も引数を指定せずにcrashコマンドを起動することができます。

crashコマンドの実行形式の紹介

# crash

KERNEL: /usr/lib/debug/lib/modules/2.6.18-8.el5/vmlinux
DUMPFILE: /dev/crash
CPUS: 2
DATE: Thu Oct 18 10:06:56 2007

crash>

これは何と今使っているシステムを解析できてしまうのです。「DUMPFILE」が「/dev/crash」となっていますが、これはシステムの物理メモリにアクセスするための特殊ファイルになります。crashコマンドを引数なしで実行すると、/dev/crash特殊ファイルのアクセスのために、「crash」というカーネルモジュールが密かにロードされます。
これで解析のための準備は終わりました。次回より待望の解析に入ります。

  • ※1 URLは以下のとおりです。
    http://people.valinux.co.jp/~oda/dump-analysis/sample-dump-1.tar.gz
  • ※2 手前味噌になりますが、コマンド起動時に表示されるコピーライトの中に弊社(VA Linux System Japan K.K.)のものがあることにお気づきになられたでしょうか。これは、Xenのhypervisor部分を解析するコードの寄与によるものです。Xen hypervisorの解析についても別の機会で解説することがあるかもしれません。