VA Linux Systems Japan株式会社

ホーム 検索 お問い合わせ

English

 
 

 

ホーム VA Tech.Top テックライブラリーTop ダンプ解析講座 5

update : 2008/08/31

 

index

Xen特集

テックライブラリ

ダンプ解析講座

 

1

ダンプ解析とは

2

ダンプの準備

3

ダンプの構造

4

crashコマンドの準備

5

crashコマンドによるダンプ解析(1)

continued

プレゼンライブラリ

イベントレポート

tips

VA Virtual-suite

仮想化に関するレポート販売

Xenを使ってみよう

Kernel対応障害解析サービス VA Quest

Linux Virtual Server Project

信頼性の高いロードバランサ である「VA Balance」

大規模メーセージングソリューション「FMS」

 
 


ダンプ解析講座

隊長

第5回 crashコマンドによるダンプ解析(1)

helpサブコマンド

今回より、crashコマンドを使用して、ダンプの解析方法を解説していきます。本講座は、ダンプの解析方法を解説するのが目的であり、crashコマンドの解説をすることが目的ではありませんので、crashコマンドの機能について網羅的に解説することはしません。crashコマンドの機能については、helpサブコマンド(以下、単にコマンド)を実行すると一覧が出てくるので参考にしてください。

【 helpコマンドの実行例(1) 】

別ウィンドウで開く

helpコマンドでは、各コマンドの詳細な説明や使用例を見ることができます。本講座で出てきたコマンドについても、適宜、helpコマンドで詳細を確認するようにしてください。

【 helpコマンドの実行例(2) 】

別ウィンドウで開く

カーネルのデータの内容確認

それでは、いよいよお待ちかねのダンプ解析に入ります。まず最初は、カーネルのデータの内容を確認する方法について見ていきます。
メモリの内容を見るには、rdコマンドを使用します。一例として、変数num_physpagesの値を確かめて見ましょう。変数のアドレスは、symコマンドで分かります。rdコマンドの引数には、仮想アドレスを指定します。-pオプションを使用して、物理アドレスの指定をすることも可能ですが、実際の解析において、物理アドレスの参照が必要なケースはあまり多くないと思います。rdコマンドの引数には、シンボル名を直接指定することもできます。

【 変数の値の参照例 】

crash> sym num_physpages

c0793684 (B) num_physpages

crash> rd c0793684

c0793684:  0003fe70                              p...

crash> rd -p 0x793684

  793684:  0003fe70                              p...

crash> rd num_physpages

c0793684:  0003fe70                              p...

crash>

構造体の内容

構造体の内容も見てみましょう。一例として、変数mem_mapからポイントされるpage構造体(配列の先頭要素)を見てみます。rdコマンドでワード数を指定すれば、メモリの内容をいくらでも見れます。ソースコードと照らし合わせればメンバの値が確認できます。実は、構造体の形は、わざわざソースコードを見なくてもstructコマンドで分かります。これだけでもずいぶんありがたいことですが、なんと、structコマンドでアドレスを指定すれば、メンバの値を自動的に整形して出してくれます。

【 構造体の内容の表示例(1) 】

別ウィンドウで開く

page 構造体筆者のように、ノートに一生懸命【図1】のような絵を描いて、16進ダンプで解析を行っていた世代の人間にとっては、ありがたすぎて涙が出てくるくらい便利です。今では、task_struct構造体のように殺人的に巨大な構造体もありますから、このような機能がなければ生きていけません。余談ですが、筆者はソースコードの解析を行う際もcrashコマンドを実行して、structコマンドを使うことがよくあります。ヘッダファイルを確認するよりもその方が楽ですから。

カーネル仮想領域

カーネルの仮想アドレスを指定して、データの内容を見てきましたが、これまでのところ、ストレートマップ領域にあるデータだけでした(すなわち、0xc0000000を引けば物理アドレスに変換できます)。カーネル仮想領域(vmalloc領域)にあるデータについても見てみましょう。下の例は、scsi_modカーネルモジュールに対するmodule構造体の内容を見てみたものです。このように問題なく見れました。

【 構造体の内容の表示例(2) 】

別ウィンドウで開く

第3回の講座で解説したように、ダンプの中のデータは物理アドレスでアクセスします。つまり、crashコマンドの中で仮想アドレスから物理アドレスへの変換が行われていることを意味します。仮想アドレスから物理アドレスへの変換は、mm_struct構造体init_mmのpgdメンバが示すページテーブルを追うことによって行うことができます。init_mmは、ストレートマップ領域にあり、ページテーブルの内容は物理アドレスですから、init_mmのアドレスさえ分かっていばいいわけです。仮想アドレスから物理アドレスへの変換の様子は、vtopコマンドの出力により伺い知ることができます。

【 vtopコマンドの表示例 】

crash> struct mm_struct.pgd init_mm

  pgd = 0xc0712000,

crash> vtop f891fa00

VIRTUAL   PHYSICAL

f891fa00  3fa54a00

 

PAGE DIRECTORY: c0712000

  PGD: c0712f88 => 98f8067

  PMD: c0712f88 => 98f8067

  PTE:  98f847c => 3fa54163

 PAGE: 3fa54000

 

  PTE     PHYSICAL  FLAGS

3fa54163  3fa54000  (PRESENT|RW|ACCESSED|DIRTY|GLOBAL)

 

  PAGE    PHYSICAL   MAPPING    INDEX CNT FLAGS

c97f4a80  3fa54000   -------    -----   1 c0000000

crash>

カーネルモジュールの情報

さて、structコマンドで、構造体の内容を自動的に表示してくれることが分かりましたが、構造体の形式についてはどこから情報を得ているのでしょうか。それは、crashコマンドの引数で指定したvmlinuxの中に入っているデバッグ情報から得ています。vmlinuxはカーネル本体ですが、カーネルモジュールの情報は入っていません。カーネルモジュール内で使用されている構造体については、きちんと表示できるのでしょうか。試しにscsiドライバ(scsi_modカーネルモジュール)で使用されている構造体について見てみましょう。

crash> struct scsi_cmnd

struct: invalid data structure reference: scsi_cmnd

crash>

残念ながら、失敗しました。これは、scsi_modカーネルモジュールのデバッグ情報がないためで、当然と言えば当然の結果です。ダンプ採取時点でロードされていたカーネルモジュールの一覧は、modコマンドで得ることができます。

【 modコマンドの表示例(読み込み前) 】

別ウィンドウで開く

カーネルモジュールのデバッグ情報を得るためには、デバッグ情報付きのカーネルモジュール(すなわち、コンパイル時に-gオプション付きでビルドされたカーネルモジュール)をmodコマンドの-sオプションを使用して読み込みます。

【 mod -s コマンド実行例 】

別ウィンドウで開く

上の【 mod -s コマンド実行例 1 】 で使用しているscsi_mod.ko.debugは、カーネルのdegubinfoパッケージ
(kernel-debuginfo-common-2.6.18-8.el5.i686.rpm、
kernel-PAE-debuginfo-2.6.18-8.el5.i686.rpm)
をインストールして得られたものです。実は、カーネルのdebuginfoパッケージがインストールされていれば、modコマンドの-Sオプションでロードされているすべてのモジュールに対して、一発で読み込みを行ってくれます。

【 mod -S コマンド実行例 】

別ウィンドウで開く

目的のカーネルモジュールのデバッグ情報が読み込まれれば、カーネルモジュール内の構造体についてもstructコマンドで表示できるようになります。先ほど失敗したscsi_cmnd構造体についても、以下のとおりです。

crash> struct scsi_cmnd

struct scsi_cmnd {

    struct scsi_device *device;

    struct list_head list;

    struct list_head eh_entry;

    int eh_eflags;

    void (*done)(struct scsi_cmnd *);

    long unsigned int serial_number;

    long unsigned int jiffies_at_alloc;

    int retries;

    int allowed;

    int timeout_per_command;

    unsigned char cmd_len;

    enum dma_data_direction sc_data_direction;

    unsigned char cmnd[16];

    unsigned int request_bufflen;

    struct timer_list eh_timeout;

    void *request_buffer;

    short unsigned int use_sg;

    short unsigned int sglist_len;

    unsigned int underflow;

    unsigned int transfersize;

    int resid;

    struct request *request;

    unsigned char sense_buffer[96];

    void (*scsi_done)(struct scsi_cmnd *);

    struct scsi_pointer SCp;

    unsigned char *host_scribble;

    int result;

    unsigned char tag;

    long unsigned int pid;

}

SIZE: 280

crash>

例えば、独自のカーネルモジュールを開発してロードしているようなケースでは、modコマンドの-sオプションで個別に読み込むことになります。crashでダンプ解析することを想定して、最初から-g付きでビルドしておくとよいでしょう。

 

今回は、ダンプに格納されたメモリの内容を見る方法について説明しました。基本的には、これだけ知っているだけで、ダンプを解析して障害原因の調査ができるはずです。もちろん、カーネルそのものが分かっていることは前提ではありますが。
次回は、解析作業における手間を軽減するための技を紹介していきたいと思っています。

 

戻る  次回へ続く


 
 
本サイトの利用に関して 免責事項 コピーライト 個人情報保護方針

Copyright C VA Linux Systems Japan. All rights reserved.