Simics 上での Simics のデバッグ 投稿者 :Jakob Engblom,, 2012/12/05 私はたびたび書いたり話したりしていますが Simics は並列処理のバグのデバッグと マルチスレッドやマルチコアシステムの障害に対するデバッグには実に有効です 非常に複雑なアプリケーション 具体的に言えば Simics 自体の上で このことを証明した例を最近経験しました この例は Simics の反復の完成度と 複雑なソフトウェアに潜む手ごわいバグを解決する際の有効性の両方の 分かりやすい証明であると考えています 私はたびたび書いたり話したりしていますが Simics は並列処理のバグのデバッグと マルチスレッドやマルチコアシステムの障害に対するデバッグには実に有効です 非常に複雑なアプリケーション 具体的に言えば Simics 自体の上で このことを証明した例を最近経験しました この例は Simics の反復の完成度と 複雑なソフトウェアに潜む手ごわいバグを解決する際の有効性の両方の 分かりやすい証明であると考えています この例の説明は Simics に含まれていたバグから始めましょう ある特定の構成に限って発生するバグがありました Simics のターゲットは プロセッサのシミュレーションをテストする ベアメタル型テストコードを実行する Power アーキテクチャマシンです この構成ではたまに Simics またはモデルに含まれているバグのために Simics がクラッシュしました テストを 50 回実行するうちの 1 回程度しか発生しないので 追跡が難しいバグでした 診断のためにデバッガを接続してバグの再現を試みると そういうときに限って発生しません ( 昔からハイセンバグと呼ばれるものです )
この手の問題を診断する際に Simics は完璧なツールなのですが 実行するためには 問題が発生するプログラムを Simics に取り込まなければなりません すなわち Simics 上で Simics を実行するのです まず Simics 内部に開発ホストの複製を作成します これは何も難しいことではなく 単純に 8 コア Intel ターゲット上に標準的な Linux の Fedora 16 をインストールするだけです Linux をインストールしてブートすると システムのチェックポイントが取得されます 次に ホストからの開発コードツリーが TAR ファイルとしてパッケージングされて DVD イメージファイルに置かれます Simics は ブートされたターゲットシステムのチェックポイントから起動され Simics 上で稼働している Fedora Linux は DVD イメージを仮想 DVD ドライブに挿入してマウントします TAR ファイルは ターゲット上のファイルシステムにコピーされて展開されます このようにして Simics のインストールが完了すると新しいチェックポイントが取得されて Simics 上で Simics を実行できるようになります この時点で得られる成果は 完全に自身で完結していて 制御可能で 再現可能な環境です 以下のスクリーンショットは Simics 上で Simics が稼働する様子を示しています ホストと外部の Simics Fedora システムの両方で 同じデスクトップの壁紙を使っています
次のステップは Simics の中にあるバグの再現です この目的のために バグに遭遇するまで内部の Simics を繰り返し実行するシェルコマンドを使用します ( このセッションは明らかに Simics をインストールした 後のチェックポイントから開始します ) ここでの成果は バグに遭遇するまで Simics を実行する準備が整った この構成です
ここまでの流れをまとめると Simics 上で稼働する Simics を構築しました Power アーキテクチャ構成の 内部 Simics はホスト上でクラッシュしました Fedora 16 が稼働している 外部 Simics は 開発ホス トの仮想レプリカ ( ただし Simics 内部を除く ) を提供しています バグの検索とバグの再現の効率を上げるために スクリプトを追加して外部 Simics 内で使用しました
その Simics スクリプトで IA ターゲットシステムに含まれているプロセッサに割り当てたタイムスライスを変更しました こうすることで 並列実行プロセスと Simics でシミュレートしている Fedora 16 OS 内のスレッドのスケジューリングに大きな変化が起こり バグを早く再現する ( バグを再現するまでの内部 Simics の実行回数が少なくなる ) ことにつながります 内部 Simics が起動されて タイミングの変更が IA プロセッサに適用されたら 内部 Simics がテストケースの実行を開始する前にチェックポイントを取得します これで バグに直接つながるチェックポイントが利用できます バグの再現のためにターゲットのウォームアップや Simics を特定の構成にする必要は全くありません チェックポイントは結果的に この問題に関する自己完結したバグレポートとなります 内部 Simics の segfault( セグメントエラー ) ハンドラにマジック命令 ( ブルースター ) を埋め込みます これで 内部 Simics のクラッシュは簡単に捕捉できます 正しいページフォルトの捕捉を試みたり 正しい場所にブレークポイントを設定するよりも このようにマジック命令を使用する方が簡単な場合があります マジック命令とは コード中でバイオマーカーのような役割を果たすもので デバッグ情報や OS Awareness に関係なく常にトリガーの働きをします しかも マジック命令は起動するまでオーバーヘッドは発生しません
ついに 内部 Simics を 20 回程度実行すると バグをトリガーできるようになりました チェックポイントと Simics の反復能力によって バグの再現は困難ではなくなりました Simics のクラッシュは もはやいつでも再現できるようになったので 次はデバッグに移って Simics がクラッシュする理由を考えることにしましょう たまにしか起こらないハイセンバグは 100% 再現可能なボーアバグに変わりました デバッグの最初のステップは 内部 Simics の中に多数ある 動的にロードされたモジュールのマッピングについて考えることです これは 外部 Simics を稼働させて Fedora シェルに Ctrl-Z を送信し 内部 Simics を一時停止させることで実現します このとき Simics 上で動作している Fedora Linux 上の /proc ファイルシステムに ロードアドレスを検出するための応答指令信号が送られます Simics が起動した後にチェックポイントが取得されているので これはチェックポイント中で検出される ソフトウェア構成内のマッピングであることが分かります チェックポイントがオープンされるたびに 同じマッピングが適用されます こうして情報が保存され 使用している Simics モジュールのためのシンボリックデバッグ情報を設定するために利用されます デバッグの次のステップでは チェックポイントを再びオープンし そこからリバース実行を始めて マジック命令がヒットするまで実行を続けます ここで segfault ハンドラが実行される前に内部 Simics が動作していた最終時点のバックアップを取得するために OS awareness が利用されます これによって外部 Simics は 内部 Simics のクラッシュを引き起こした命令とまったく同じ命令を実行します Simics は コードが存在しないロケーション (BCDE) でコードの実行を試みていたことが判明しました そこから 1 命令戻ると BCDE ロケーションへの JMP 命令を実行していました では この JMP BCDE 命令を実行するに至った理由は何でしょう この命令は明らかに Simics の静的コー ドには含まれていませんが Simics 自身が命令実行中に何か生成したと考えられます (Simics には JIT コン パイラが含まれているので 実行中にコードを変更する可能性は 十分にあります )
誤った JMP 命令が作成された状況を調べるために 命令 (JMP BCDE) にメモリー書き込みブレークポイントを設定して リバース実行を進めてみました Simics は 命令の JMP 部分をメモリーに書き込んだ時点で停止しました ここでスタックのバックトレースを実行して コードは JIT が生成したコードストリームに 5 バイトの JMP XYZQ 命令を書き込もうとしていたことが分かりました JMP 命令コードを含むバイトの書き込み時にブレークポイントがヒットしたことから 命令が実行されて Simics がクラッシュしたとき 命令以外の 4 バイト (JMP 命令が本来目指していたロケーションである XYZQ) はまだ書き込まれていなかったことが分かります 命令を ( プロセッサ上で ) 書かれている順序どおりに 1 ステップずつ実行することで 内部 Simics の中でスレッドの切り替えが起こり 入ってきたスレッドが即座に 5 バイトの JMP 命令を実行して現在の問題が起こったと判明しました JMP バイトだけが書き込まれていたことから 狙っていた XYZQ( もともとの ABDCE コードを実行するにはそれでもよかった ) へのジャンプではなく BCDE へのジャンプとなってしまったことが分かります したがって 今回の状況は 読み取りはメモリーの内容をコードに書かれたとおりに実行して 書き込みは通常のデータの書き込みを行うという性質に基づいた 読み取りと書き込みの競合条件の問題であると診断されました 問題が特定されれば その修正はとてもたやすいことでした 同じ構成で Simics の競合条件がもう 1 つ見つかり それも修正されました さらに頻度の高いケースである 複数のスレッドの同時実行に関係する問題で 共有しているデータ構造の更新および読み取りを実行する間に 同期が不完全になるというものでした
要約すると このブログエントリーでは Simics を利用して 現実世界に存在する複雑なソフトウェアシステムの 1 つでもある Simics の 並列実行のバグを検出して修正した一例を説明しました 成功のカギとなったのは Simics が備えている反復能力です タイミングが関係する たまにしか発生しないイベントにも対応できますし チェックポイント スクリプティング リバース実行 デバッグ設備と連携させることもできます 原文はこちら :http://blogs.windriver.com/m2m/2012/12/biggest-predictions-for-m2m.html 本社ブログサイト :http://blogs.windriver.com/