連載
» 2011年09月21日 11時50分 UPDATE

実践しながら学ぶ Android USBガジェットの仕組み(2):KGDBを使って、Android組み込みボードをリモートデバッグしよう!【前編】〜KGDBの仕組みを理解する〜 (1/3)

「AndroidのUSB機能」をテーマに、Android搭載の組み込みボードを実際に用いながら、その仕組みなどについて詳しく解説する連載。第2回となる今回は、Linuxカーネルデバッガ「KGDB」の仕組みについて詳しく解説する。

[中垣内勇祐、森崇、中谷洋一(永和システムマネジメント),@IT MONOist]

はじめに

 前回は、Android搭載の組み込みボードを使って、何とかUSBガジェットを使えるようにしました。ただ、このボードに搭載されているAndroidはあくまでもデモ用ですので、まだまだ多くのトラブルが予想されます。そのため、これから起こり得るさまざまな問題に備えるためにも、今回から2回にわたって、このAndroid組み込みボードでカーネルデバッグが行えるようにしていきたいと思います。

 ここで、「デバッグって何?」という疑問を持たれる読者の方もおられるかもしれませんので、まず簡単に「デバッグ」について説明します。次に、組み込みボードでデバッグをサポートするデバッガの代表的な方法を紹介した上で、今回使用するLinuxカーネルデバッガである「KGDB(Kernel Gnu DeBugger)」の位置付けについて確認しておきます。

 そして、KGDBを導入する方法を説明……といきたいところですが、その前に、今回は「KGDBの仕組み」を説明したいと思います。

 普段何げなく使っているデバッガが、どうやってCPUを停止させ、また処理を再開させているのか気になりませんか? KGDBはソースも公開されていますので、やる気と根気があればその仕組みを理解することができます。そして、そのデバッガの機能をソースから読み取ることができれば、デバッガ自体にトラブルが起きたときにも対処ができる……かもしれませんよね!

デバッグについて

 デバッグとは、プログラムが正常に動作しない場合に、その“誤り(バグ)”を調査して、バグを取り除く作業のことです(注1)。例えば、以下のプログラムがあったとします。

※注1:プログラムの処理がどのように動作するのかを調べるために使う場合もあります。


int func(int opt)
{
        int ret;
        swtich (opt) {
        case 0:
                ret = OK;
        default:
                ret = NG;
                break;
        }
        return ret;
}
プログラム1 バグがあるプログラム

 このプログラムでは、関数funcの引数optの値が0の場合は戻り値として“OK”を返し、0以外の場合は“NG”を返すものですが、どこかにバグあります。さて、どこにバグがあるか分かりますか(注2)? この関数を実行すると、optに0を指定しても、“NG”が返ってきます。

※注2:筆者がプログラムを習い始めたころは、この手のバグによく引っ掛かったものです。


 人は思い込みで物事を見ている・判断することが多いので、自分が作ったプログラムのバグがどこにあるのか分からない(なかなか見つけられない)ものです。こういうときは、初心に戻って、プログラムの処理の流れを1行ずつ実際に動作させてみるしかありません。とはいっても、プログラムを実行しただけでは、内部で実際にどうやって処理が進んでいるのかは分かりません。

 こういう場合に、「デバッガ」というツールを使います。デバッガは、ユーザーが1行ずつプログラムの処理を実行できるようにお願いすると、その通り1行進んで処理を止めて、ユーザーからの指示を待ってくれます。

 以下に、実際にデバッグしているときの様子を示してみます。

デバッグでプログラムのバグを調査する様子 図1 デバッグでプログラムのバグを調査する様子

 3番目のステップ実行で思いもよらず、break文が抜けているため処理が止まらないことが分かります。この例でデバッガのありがたみを(少し)感じていただけたでしょうか。

デバッガの代表的な機能

 デバッグ作業では、問題が潜んでいる箇所の周辺で処理を停止させ、メモリの変化状況などを監視しながらプログラムを少しずつ実行させていくことがほとんどだと思います。それらの作業を支援するための代表的な機能として、以下が挙げられます。

No. デバッガの機能 説明
1 ブレークポイント設定 プログラムの任意の箇所で処理を停止する機能
2 ブレークポイント解除 設定したブレークポイントを解除する機能
3 データ参照 CPUのレジスタ値やメモリを参照する機能
4 データ変更 CPUのレジスタ値やメモリを変更する機能
5 コンティニュー 停止しているプログラムの実行を再開する機能
6 ステップ実行 プログラムを1ステップずつ実行する機能
表1 デバッガの代表的な機能

デバッガ機能の実現方法

 デバッガの機能を実現するためには、プログラムの任意の箇所でCPUの実行を停止させ、その時のメモリ状態を参照し、実行を再開させたりする必要があります。これら一連の機能を実現するための方法として、大きく分けて“ハードウェアで実現”する方法と“ソフトウェアで実現”する方法があります。

 ハードウェアで実現する代表的な方法としては、以下が挙げられます。

No. 種類 説明
1 ICE(In-Circuit Emulator) ターゲットボード上のCPUの代わりにICEを接続して実現する
2 JTAGデバッガ ターゲットボード上のCPUに用意されているJTAGポートを使用して、JTAGデバッガとシリアル通信を行って実現する
表2 ハードウェアでの実現方法

 一方、ソフトウェアで実現する方法としては、「モニタデバッガ」があります。

No. 種類 説明
1 モニタデバッガ ターゲットプログラムにデバッグ用のプログラム(モニタプログラム)を組み込むことで実現する
表3 ソフトウェアでの実現方法

 Android OSのベースとなるLinuxカーネルには、標準でモニタデバッガが用意されており、それこそがKGDBなのです。

今回のデバッグ方法

 さて、今回のデバッグ方法ですが、ハードウェアデバッグの場合は専用のハードウェアやツールを購入する必要があるため、手軽にデバッグすることができません(注3)。一方、ソフトウェアデバッグであるKGDBの場合、Linuxカーネルのコンフィギュレーションをすることで手軽に導入できますし、GDBコマンドと連携してソースレベルのデバッグが容易に行うことができます。

 また、当然ながら、KGDBのソースは公開されており、ブレークポイントの設定などの仕組みを理解することもできますし、いざとなれば自分でカスタマイズ可能です! こうした理由により、今回、KGDBをデバッグツールとして採用することにしました。

※注3:その代わり、リアルタイムトレースなどの機能により、高精度な解析が行えます。


       1|2|3 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.