次のページ 前のページ 目次へ

7. デバッグのヒントとプログラム情報

7.1 有益なバグレポートの送り方

最も好ましいバグレポートの送り方は、Linux PCMCIA 情報サイトにある HyperNews のメッセージリストを使うことです。この方法なら、現状の問題 (そして、もしあれば修正方法や回避方法)が他の人にも見えるからです。 バグレポートに必須の項目を以下に示します:

PCMCIA モジュールと cardmgr デーモンはステータスメッセージを システムログに送ります。システムログは普通、 /var/log/messages/usr/adm/messages といった名前 だと思います。問題を調べるときには、このファイルを最初に見るべきです。 バグレポートを送る時にも、このファイルの内容は必ず入れてください。 システムのメッセージが見つからない場合には、/etc/syslog.conf を見て、他のクラスのメッセージの出力先を調べてください。

バグレポートを送る前には、最新のドライバを使っていることを必ず確認して ください。既に直したバグのバグレポートを読むのは嬉しくないことでもない のですが、これはあまり有効な時間の使い方ではありませんから。

WWW にアクセスできなければ、直接私宛( dhinds@pcmcia.sourceforge.org) にメールで送ってくださっても構いません。ただし、できればバグレポートは 他の人にも見せられるように、WWW サイトの方に送って欲しいと思っています。

7.2 カーネルのトラップ通知の解釈

もしカーネル自身がフォールトする(エラーを起す)場合、あなたが問題となる アドレス、EIP 等から何か意味を読み取れるとしても、レジスタのダンプ情報 しか役に立たないでしょう。最近のバージョンの klogd はフォールトが 起きたアドレスを、現在のカーネルのシンボルマップに基づいて変換しますが、 フォールトがモジュール内で起こった場合や問題が深刻で klogd がフォー ルトの情報をシステムログに書き込めない場合にはこの方法は使えません。

フォールトがカーネル本体で起こっている場合、フォールトが起きたアドレス は System.map ファイルに残ります。このファイルは /System.map/boot/System.map にあると思います。 フォールトがモジュールで起こっている場合には、nm コマンドを使えば 同じ情報が得られますが、フォールトが起きたアドレスはモジュールがロード されたアドレスが基準になっています。例えば、カーネルが以下のような フォールトを起こしたとします:

Unable to handle kernel NULL pointer dereference
current->tss.cr3 = 014c9000, %cr3 = 014c9000
*pde = 00000000
Oops: 0002
CPU:    0
EIP:    0010:[<c2026081>]
EFLAGS: 00010282

フォールトが起きたアドレスは 0xc2026081 です。System.map を見ると、 このアドレスはカーネルの最後のアドレスを越えているが分かるでしょう。つ まり、フォールトはカーネルモジュールで起きているのです。どのモジュール でフォールトが起きたのかを調べるために、``ksyms -m | sort'' の 出力を調べましょう:

Address   Symbol                            Defined by
c200d000  (35k)                             [pcmcia_core]
c200d10c  register_ss_entry                 [pcmcia_core]
c200d230  unregister_ss_entry               [pcmcia_core]
          ...
c2026000  (9k)                              [3c574_cs]
c202a000  (4k)                              [serial_cs]

したがって 0xc2026081 は 3c574_cs モジュールの内部で、モジュール の先頭からのオフセットが 0x0081 です。3c574_cs.o 内部のこのオフセット 位置を参照する方法は今のところありません。カーネルがモジュールをロード した時、カーネルはモジュールをロードしたアドレスの先頭にヘッダを入れる ので、実際にモジュールが始まる位置は ksyms が示すアドレスから オフセットを取った位置となります。ヘッダの大きさはカーネルのバージョン ごとに異なります。お使いのカーネルでのヘッダの大きさを調べるには、 シンボルをエクスポートしているモジュール(前述の pcmcia_core 等)を 調べ、シンボルいずれかのアドレスをそのシンボルに対する nm コマンド の出力と比較します。この例では、register_ss_entry は 0xc200d10c - 0xc200d000 = 0x010c というオフセット位置にロードされてい ます。ここで ``nm pcmcia_core.o'' は 0x00c0 というオフセットを示 していますから、ヘッダの大きさは 0x010c - 0x00c0 = 0x004c ということに なります。

3c574_cs の話に戻ると、フォールトが起きたオフセット位置は 0x0081 なので、これからヘッダの大きさである 0x004c を引くと、モジュールの実際 の位置は 0x0035 となります。ここで ``nm 3c574_cs.o | sort'' を 実行すると以下のような出力となります:

0000002c d if_names
0000002c t tc574_attach
00000040 d mii_preamble_required
00000041 d dev_info

したがって、フォールトが起きた位置は tc574_attach() です。

この例では、フォールトでシステム全体が固まることはないので、フォールト が起きた後に ksyms を実行することもできます。場合によっては、 モジュールがロードされた位置を間接的に推測するしかないこともあります。 同じ順序で操作すれば、普通はモジュールも同じ順序で同じ位置にロードされ ます。特定のカードを挿入した時にフォールトが起こる場合は、そのカードを 挿す直前か、代わりに別のカードを挿した時の ksyms コマンドの出力を 調べましょう。カードを挿す前に手動で insmod でカードのドライバ モジュールをロードし、ksyms コマンドを実行するという方法もありま す。

背景を詳しく知りたければ ``man insmod'', ``man ksyms'', ``man klogd'' を見てください。カーネルのソースコードに入っている Documentation/oops-tracing.txt も関連があります。カーネルの デバッグ関連のヒントをいくつか紹介します:

7.3 PCMCIA の低レベルのデバッグを行うための情報

PCMCIA モジュールにはコンパイル時のオプションで決まるデバッグ用コード がたくさん含まれています。 これらのコードの大部分はプリプロセッサの PCMCIA_DEBUG という定義で制御されています。もし PCMCIA_DEBUG が未定義ならば、デバッグ用のコードはコンパイルさ れません。もし 0 に定義されていれば、コードはコンパイルされるものの、 利用されません。この数字を大きくすればデバッグメッセージはより細かくな ります。PCMCIA_DEBUG を定義してコンパイルした各モジュールには 整数を値に持つ pc_debug という変数が設定され、この変数でデバッグ 出力の詳しさを制御できます。この変数はモジュールがロードされる際に設定 できるので、再コンパイルを行わなくてもモジュール別にデバッグ出力を制御 することができます。

syslogd のデフォルトの設定は、カーネルのデバッグメッセージを無視 するようになっているかもしれません。これを確実に記録するためには、 /etc/syslog.conf を編集して、``kern.debug'' クラスの メッセージがどこかに記録されるようにします。詳しくは ``man syslog.conf'' をご覧ください。

PCMCIA パッケージの debug_tools/ ディレクトリには、デバッグ用 のツールがいくつか入っています。dump_tcicdump_i365 コマンドは PCMCIA コントローラのレジスタを全て ダンプし、多くのレジスタ情報をデコードします。これらのコントローラ チップのデータシートを参照できるなら、この情報は非常に有効でしょう。 dump_cis(バージョン 3.0.2 以前は dump_tuples)コマンド は、カードの CIS(Card Information Structure)を出力し、いくつかの重要な ビットをデコードします。dump_cisreg コマンドはカードのローカル な設定レジスタを出力します。

メモリカードドライバである pcmem_cs も 16 ビット PC カードの デバッグに役立つことがあります。このドライバはどんな PCMCIA カードに対 しても利用でき、他のドライバと干渉することもありません。このドライバを 使えば、どんなカードの属性メモリや共通メモリにも直接アクセスできます。 CardBus カードの場合も同様で、memory_cb ドライバはどんな 32 ビッ トカードに対しても使うことができ、カードのアドレス空間にも直接アクセス することができます。詳しくはオンラインマニュアルを参照してください。

7.4 /proc/bus/pccard

バージョン 2.1.103 以降のカーネルでは、PCMCIA パッケージはステータス情報 のツリーを /proc/bus/pccard ディレクトリ以下に作り ます。この情報の多くは、PCMCIA ホストコントローラのデータシートを使わ ないと意味が分かりません。この内容はドライバの設定によりますが、以下の 情報の全てあるいは一部を含んでいると思います:

/proc/bus/pccard/{irq,ioport,memory}

これらのファイルがある場合には、カーネルの通常のリソーステーブルを補う ためのリソースの割り当て情報が書かれています。最近のバージョンの PCMCIA システムは、(設定がしてあれば)追加のリソース情報をプラグ&プ レイ BIOS からできます。

/proc/bus/pccard/drivers

最近のリリースでは、このファイルには現在ロードされている PCMCIA クライ アントドライバが列挙されています。/proc/modules と異なり、こ のファイルはカーネル内に静的にリンクされているかもしれないドライバも列 挙します。

/proc/bus/pccard/*/info

それぞれのソケットについて、ソケットのホストコントローラとその機能を示 します。

/proc/bus/pccard/*/exca

このファイルには、コントローラの ``ExCA'' Intel i82365sl 互換レジスタ セットのダンプが含まれています。

/proc/bus/pccard/*/{pci,cardbus}

CardBus ブリッジについての、ブリッジの PCI 設定空間のダンプと、 ブリッジの CardBus 設定レジスタのダンプが含まれています。

7.5 出たばかりのカード向けに PCMCIA カードサービスのドライバを書くには

``Linux PCMCIA Programmer's Guide'' がクライアントドライバインタフェース に関する最善の文書です。最新版は sourceforge.org/pub/pcmcia/doc ディレクトリにあります。WWW 上では http://pcmcia.sourceforge.org から入手できます。

使いたいデバイスが普通の ISA デバイスによく似ていれば、既存の Linux 用 のドライバの一部を流用することもできるでしょう。場合によっては、既存の ドライバを修正してブート後にもデバイスを追加したり外したりできるように するのがもっとも苦労するところです。今あるドライバの中では、メモリカード 用のドライバが、あらゆる種類の汚れ仕事をするのにカーネルの他の部分を利 用しない、唯一の「自己完結した」ドライバです。

多くの場合、新しい種類のカードをサポートする際の最大の障害は、メーカー から技術情報を入手することです。誰に頼めばよいかも分かりにくいですし、 どんな情報が必要かを正確に説明するのも困難です。しかし、一部の例外を除 くと、メーカーからの技術情報無しでドライバを書くのは不可能とは行かない までも非常に困難です。

ドライバがカードサービスシステムとどのように通信するかを説明するために、 多数のコメントを入れたダミーのドライバを用意しています。PCMCIA パッケージ のソースコードに入っている clients/dummy_cs.c がそれです。

7.6 PCMCIA クライアントドライバを書く人のための手引き

私は、全ての PCMCIA クライアントドライバを PCMCIA パッケージの一部とし て配布するのは本当は適切でないと考えています。新しいドライバが加わるた びに本家のパッケージも段々メンテナンスしにくくなりますし、ドライバを取 り込むとメンテナンス作業の一部がドライバの作者から私へ移ってくるのも明 らかです。そこで全てのドライバを取り込む代わりに、寄付されたドライバは ケースバイケースの判断で取り込むかどうかを決めています。判断はユーザの 要望やメンテナンス性に基づいて行っています。本家のパッケージに取り込ま なかったドライバについては、私はドライバの作者に以下の方法で配布用のド ライバパッケージを作るようにお願いしています。

ドライバファイルは、PCMCIA のソース配布物で使われているのと同じディレクトリ 配置にしなければなりません。これはドライバを PCMCIA ソースツリーのトップ ディレクトリで展開できるようにするためです。ドライバには ソースファイル(./modules/ ディレクトリ内)、 オンラインマニュアル(./man/ ディレクトリ内)、 設定ファイル(./etc/)が含まれていなければなりません。トップレベル ディレクトリには README ファイルもなければなりません。

トップレベルディレクトリには makefile が必要で、これは ``make -f ... all'' でドライバをコンパイルでき、 ``make -f ... install'' で必要なファイルを全てインストールできる ように設定されていなければなりません。この makefile に .mk という 拡張子が付いていれば、このファイルはトップレベルの Makefile から ターゲット allinstall について自動的に呼び出されます。 このような makefile の作り方の例を以下に示します:

# Sample Makefile for contributed client driver
FILES = sample_cs.mk README.sample_cs \
        modules/sample_cs.c modules/sample_cs.h \
        etc/sample etc/sample.opts man/sample_cs.4
all:
        $(MAKE) -C modules MODULES=sample_cs.o
install:
        $(MAKE) -C modules install-modules MODULES=sample_cs.o
        $(MAKE) -C etc install-clients CLIENTS=sample
        $(MAKE) -C man install-man4 MAN4=sample_cs.4
dist:
        tar czvf sample_cs.tar.gz $(FILES)

この makefile では、バージョン 2.9.10 以降の PCMCIA パッケージで定義さ れているインストールターゲットを使っています。この makefile には、 ドライバ作者の利便のための ``dist'' ターゲットも入っています。最終的な パッケージのファイル名にはバージョン番号も入れるとよいでしょう( sample_cs-1.5.tar.gz 等)。完成品の配布ファイルの内容は以下のよう になります:

sample_cs.mk
README.sample_cs
modules/sample_cs.c
modules/sample_cs.h
etc/sample
etc/sample.opts
man/sample_cs.4

このファイル配置であれば、寄付されたドライバのパッケージを展開した時に、 実質的に PCMCIA のソースツリーの一部となります。PCMCIA のヘッダファイル やユーザのシステム設定を調べる仕組みの利用、ファイルの依存関係の自動チェック を「通常の」クライアントドライバと同じように行うことができます。

私はこの仕様に準拠しているクライアントドライバを受け取れば、 sourceforge.org/pcmcia/contrib ディレクトリに置きま す。このディレクトリにある README ファイルに、寄付されたドライバの 展開方法が書いてあります。

クライアントドライバのインタフェースは昔からあまり変わっていませんし、 後方互換性はほぼ保たれています。本家のパッケージのマイナーバージョンが 上がっても普通は更新の必要はないでしょう。ドライバの更新が必要となるよ うな変更があれば、ドライバを寄付してくださった作者の方々にはできるだけ お知らせするようにします。

7.7 Linux ディストリビューションのメンテナのための手引き

あなたが作っているディストリビューションのシステム設定ツールを PCMCIA 対応にしようとしているのなら、/etc/pcmcia にある *.opts ファイルを「止め具」として使ってください。これらの ファイルは、ユーザが新しいバージョンの PCMCIA パッケージのコンパイルと インストールを行っても変更されません。メインの設定スクリプトを修正する と、最初からのインストールを行った時にカスタマイズしたスクリプトが黙っ て上書きされ、設定ツールとの連係が途切れてしまいます。適切なオプション スクリプトの書き方が分からない場合や、追加の機能が必要な場合は、私に相 談してください。

あなたのディストリビューションとこの文書で説明している PCMCIA パッケージ の相違点を文書化してくだされば、ユーザにとって(そして私にとっても)役立 つでしょう。特に、起動スクリプトと設定スクリプトに関する変更点はぜひ 文書化してください。適切な情報を私まで送っていただければ、 個別ディストリビューションに関する注意 の節に追加させていただきます。

ディストリビューション用に PCMCIA パッケージを作る際には、寄付された ドライバ群は本家の PCMCIA パッケージの一部ではない点を覚えていてくださ い。メンテナンス上の理由により中心となるパッケージのサイズは制限しよう としており、新しいドライバを追加するのは特に需要が高いと思われるときだ けです。その他のドライバについては前の章で説明した通り、本家とは別に配 布しています。本家に統合されているドライバと別配布になっているドライバ の違いにはたいした意味はなく、歴史的経緯もある程度含まれています。また、 品質的な違いがあるわけでは決してありません。


次のページ 前のページ 目次へ