バックナンバーはこちら

today&tomorrow

Technology Update

2018 vol.110

バーチャル・プロトタイプを使用した組込みソフトウェアのデバッグ

バーチャル・プロトタイプによるソフトウェア・トレース

バーチャル・プロトタイプでは、現在のプロセッサ・ステートだけでなく、非常に多くの情報がすぐに得られます。現在のステートを観測するのも大事ですが、プロセッサがどのようにしてそのステートに移行したのかを解析できることの方が更に重要です。図7は、トレース・データを2つの抽象度で示しています。上段に示したプロセス(オペレーティング・システムのコンテキスト)トレースを見ると、プロセッサが展開フェーズからブート・フェーズに移行していますが、MMUはオフのままです。下段にはブート中に実行された関数が表示されています。Linuxの知識がそれほどなくても、プロセッサ・タイプ/マシン・タイプのルックアップ関数が正しく実行されていることはエラー・ハンドラがトリガーされていないことからも明らかです。

画像

図7:コンテキストおよび関数トレース

このトレースで最後に観察できる関数呼び出しは、「__turn_mmu_on」関数です。ブート・プロセスでこれ以降の関数が実行されていない理由を調べるには、この関数の時間領域にズームインして関数をより詳細に解析する必要があります。この関数にカーソルを置くと、より詳細な命令レベル・トレースが表示されます。これを見ると、プログラムは0x00008074から0xc0008148へ分岐しています。通常、Linuxカーネルでは上位4ビットが0xcまたは0xbのアドレスは仮想アドレスです。つまり、これは物理アドレスから仮想アドレスへの移行を示しており、MMUは有効になっているように見えます。しかし図8の詳細な命令トレースを見ると、仮想アドレス0xc0008148の命令が無効であることが分かります。無効な命令とは、そのアドレスのデータがプロセッサ命令としてデコードされていないという意味で、その場合はプリフェッチ・アボートとなります。Armの場合、プリフェッチ・アボート・ハンドラはアドレス0xffff000cにあります。これはまさに先ほど見たアドレスです。

画像

図8:関数および命令トレース

バーチャル・プロトタイプではOSコンテキスト・レベル、関数レベル、命令レベルなど必要に応じた抽象度で可視化できるため、「何が正しく動作していないのか」という重要な問題を数分で解明できます。ここまでの調査では、MMUを有効にするはずのルーチンによってLinuxブートがプリフェッチ・アボート・ハンドラ(0xffff000c)にジャンプして実行が止まっていることを突き止めました。通常、この答えを見つけるのはデバッグ工程で最も手間と時間のかかる部分です。しかも多くの場合、「どのようにしてこの状態になったのか」は解明できず、推測と試行錯誤によるデバッグに多大な時間とコストを費やすことになります。

ディスアセンブリの情報以外にも、ソース・コードにはソフトウェアの意図を示すコメントが記述されています。現在の時間カーソル位置に対応するソース・コードはすぐに開くことができます(図9)。

ソース・コードのコメントを見ると、このルーチンが仮想アドレスへのジャンプを目的としたものであると書かれており、そのことは命令トレースを見ても明らかです。しかしなぜその仮想アドレスにある命令が無効なのかという理由が分かりません。そこで、そのアドレスのメモリー内容を調べてみることにします。そのためには、この仮想プログラム・アドレスがMMUによってどの物理メモリー・アドレスにマップされているかを調べる必要があります。特定のアドレスにどのようなデータが格納されているかを調べるには、MMUによるマッピングが正しいことを確認することが重要です。

画像

図9:ソース・コードとのリンク

ローレベル・ペリフェラルおよびドライバ

Linuxカーネルのボード・コンフィギュレーションでメモリー設定の誤りを修正した後、カーネルをビルドし直してもう一度ブートを実行しました。しかし新しいカーネル・イメージでも図5と同じ症状が発生し、ワークステーション上でLinuxをブートする場合と同じような詳細なカーネル情報が表示されません。しかし今回はコード内の別の不明な場所で実行が止まっているため、少なくともこの問題は別の場所で発生しているように思われます。

これはよくある誤解ですが、詳細なカーネル・メッセージが表示されないからといって、それらが実行されていないというわけではありません。これらのメッセージはUART経由でコンソール・ターミナルに送信されるため、UARTドライバが完全に動作するまでは表示されません。UARTドライバが動作を開始する前にはMMU、タイマ、割り込みコントローラなど多くのサービスをセットアップする必要があります。バーチャル・プロトタイプを使用すると、ソフトウェアから発行された時点でこれらのメッセージを捕捉できます。詳細なカーネル・ブートアップ・メッセージは何が問題なのかを知る上でヒントとなることがあるため、この機能は非常に役立ちます。図12は、カーネルから発行された時点でバーチャル・プロトタイプが捕捉したカーネル・デバッグ・メッセージのログを示したものです。ここで重要なのは、UARTドライバが機能していなくてもこれらのメッセージを確認できるという点です。これについては次のセクションでご説明します。

画像

図12:カーネル・デバッグ・メッセージのトレース

カテゴリートップ