2015年02月25日
Linux上でビルドしたGCCクロスコンパイラをQEMUユーザーモードでテストする方法
前回の記事では、GDB のシミュレータを使用してクロス GCC の dejagnu testsuite を通す方法を紹介しました。
Linux上でビルドしたGCCクロスコンパイラを(簡易)テストする方法
しかし、ARM ターゲット(arm-none-eabi)だと、この方法では上手く行きませんでした。どうもいろいろ調べてみると、GDB のシミュレータは ARM11 ぐらいまでしか対応してないようで(この時のターゲット CPU は Cortex-A9)、それ以上新しい ARM の場合は QEMU ユーザーモード(Linux アプリ実行環境)を使用してテストを実行するようです。これもほとんどウェブ上に情報が無く、非常に苦労したので、その時のメモを公開します。
(弊社の exeGCC の前任者の方が残してくださった技術メモやスクリプトには非常に助けられました。この場を借りてお礼申し上げます。)
Linux上でビルドしたGCCクロスコンパイラを(簡易)テストする方法
しかし、ARM ターゲット(arm-none-eabi)だと、この方法では上手く行きませんでした。どうもいろいろ調べてみると、GDB のシミュレータは ARM11 ぐらいまでしか対応してないようで(この時のターゲット CPU は Cortex-A9)、それ以上新しい ARM の場合は QEMU ユーザーモード(Linux アプリ実行環境)を使用してテストを実行するようです。これもほとんどウェブ上に情報が無く、非常に苦労したので、その時のメモを公開します。
(弊社の exeGCC の前任者の方が残してくださった技術メモやスクリプトには非常に助けられました。この場を借りてお礼申し上げます。)
確認した環境は Ubuntu 14.04 x86_64 になります。(他の環境でも、binfmt の設定等が異なると思いますが、同様に可能と思われます。)
要点は以下のようになります。
2015/3/6 追記
binfmt は不要でした。target_board を通常の arm-sim にして、site.exp で SIM 変数をセットすれば、デフォルトの ${target_alias}-run ではなく、設定した qemu が使われます。unix 設定は本来はホストネイティブの GCC のテスト用なので、arm-sim 設定を使った方が良さそうです。(このやり方ならば、binfmt のしくみが無い cygwin でもテストが可能かな?と思ったのですが、Windows では QEMU のユーザーモードエミュレーションは動かないので無理でした。)
要点は以下のようになります。
- sudo apt-get install qemu-user-static して、ARM Linux アプリを直接実行 apt-get すると、自動的に binfmt の設定ファイルもインストールされ、ARM Linux アプリを、ホスト(x86_64)の Linux アプリと同様に(QEMU ユーザーモード経由で)実行できるようになります。
- テストの際、ARM Linux アプリをターゲットにしたバイナリを生成
newlib の場合、ARM ターゲットで普通にインストールすると、libgloss の一部として linux.specs という設定ファイルと XXX-linux.a のようなライブラリアーカイブが生成されるので、"-specs=linux.specs" オプションを、CFLAGS_FOR_TARGET/CXXFLAGS_FOR_TARGET 環境変数で指定するか、runtest の --tool_opts で指定します。
(QEMU を使う場合は、GDB のシミュレータの stdio サポートは不要なので、newlib をビルドする際に --disable-newlib-supplied-syscalls を付けておくと余計な混乱を避けられると思います。)
テスト時に生成される ELF ファイルをバイナリエディタ等で見てみると、binfmt の qemu-arm 設定ファイルの通りのパターンになっていることがわかります。0000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............ 0000010: 0200 2800 0100 0000 dd80 0000 3400 0000 ..(.........4...
- target_board は arm-sim ではなく unix 何も指定しなければ、デフォルトで unix になるようです。これは、bash 等のコマンドラインから、直接ファイルを指定して実行した時と同じ挙動になるようです。実行されたファイルを binfmt が解釈し、qemu-arm 設定ファイルの magic パターンにマッチするので、設定通り /usr/bin/qemu-arm-static で実行される、という流れになります。
$ sudo apt-get install qemu-user-static パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下の特別パッケージがインストールされます: binfmt-support 以下のパッケージが新たにインストールされます: binfmt-support qemu-user-static (省略) $ cat /usr/share/binfmts/qemu-arm package qemu-user-static interpreter /usr/bin/qemu-arm-static credentials yes offset 0 magic \x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00 mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
2015/3/6 追記
binfmt は不要でした。target_board を通常の arm-sim にして、site.exp で SIM 変数をセットすれば、デフォルトの ${target_alias}-run ではなく、設定した qemu が使われます。unix 設定は本来はホストネイティブの GCC のテスト用なので、arm-sim 設定を使った方が良さそうです。(このやり方ならば、binfmt のしくみが無い cygwin でもテストが可能かな?と思ったのですが、Windows では QEMU のユーザーモードエミュレーションは動かないので無理でした。)
set SIM "/usr/bin/qemu-arm-static"