buildrootは組込み向けのLinuxを作成できるビルドシステムである。オープン ソースのビルドシステムは各種あるが、最も手軽に触れることができるものの ひとつである。今回はqemu-systemu-i386で利用する手順を記載する。また、 busyboxのinitをGDBでデバッグする。
1. メリット
1.1. 小サイズ
Ubuntu等のLinuxディストリビューションは最小構成でインストールしても数 GByteのルートファイルシステムとなるが、buildrootの場合は数MByteのルー トファイルシステムを作成できる。メインのパッケージとしてbusyboxと uClibcが使われている。以下はbuildrootでデフォルトで用意されている設定 のqemu_x86_defconfigを用いて作成した場合のサイズである。
-rw-rw-r-- 1 <me> <me> 2.0M 1月 16 19:05 bzImage -rw-rw-r-- 1 <me> <me> 2.4M 1月 16 19:05 rootfs.ext2
1.2. 幅広い対応アーキテクチャ
x86向けのみではなく、ARM等の各種CPU向けのバイナリを作成できる。
2. ダウンロード
安定板は以下から取得できる。
http://buildroot.uclibc.org/downloads/buildroot-2013.11.tar.gz
リポジトリは以下。
git clone git://git.buildroot.net/buildroot
3. 構成
自分が把握している構成は以下の通り。
3.1. dlディレクトリ
buildrootはmakeを実行する段階でパッケージのアーカイブを開発元サイトか らダウンロードする仕組みになっており、そのアーカイブが本ディレクトリに 格納される。make distcleanを実行するとdlディレクトリまで削除されてしま うので、パッケージの再ビルドを実行したい場合はmake cleanを使用した方が 良い。make cleanはoutputディレクトリを削除するに留まる為である。
3.2. outputディレクトリ
output/imagesにルートファイルシステムとカーネルのイメージが作成される。 output/targetはoutput/images/root.ext2とは別であるらしい。起動用のルー トファイルシステムとしてoutput/targetを使用すると上手く起動しない場合 がある。output/buildディレクトリにルートファイルシステムに格納されるパッ ケージとそのパッケージのビルドに必要なパッケージが置かれてビルドされる。
3.3. packageディレクトリ
各種パッケージのパッチとコンフィグが置かれている。uClibc-0.9.33.2のコ ンフィグを変えたい場合はpackage/uclibc/uClibc-0.9.33.configに反映させ、 パッチを当てたい場合はpackage/uclibc/0.9.33.2/に置けば良い。
3.4. boardディレクトリ
カーネルのコンフィグが置かれている。カーネルコンフィグを変え、それを恒 久的に反映させたい場合はboardディレクトリ配下に反映させる必要がある。
4. 設定
4.1 buildrootの設定
configsディレクトリ配下にqemu_x86_defconfigがあるので利用する。
$ make qemu_x86_defconfig $ make menuconfig
GCCのバージョンを4.6.xにする。4.4. GCCのバージョンを4.6.xにする理由を 参照。
Symbol: BR2_GCC_VERSION_4_6_X [=y] Type : boolean Prompt: gcc 4.6.x Location: -> Toolchain -> GCC compiler Version (<choice> [=y]) Defined at package/gcc/Config.in.host:41 Depends on: <choice> && !BR2_microblaze [=n] && !BR2_arc [=n] && !BR2_avr32 [=n] && !BR2_bfin [=n] && !BR2_cortex_a7 [=n] && BR2_sparc_sparchfleon [=n] && !BR2_sparc_sparchfleonv8 [=n] && !BR2_sparc_sparcsfleon [=n] && !BR2_sparc_sparcsfleonv8 [=n] && BR2_pj4 [=n] Selects: BR2_GCC_NEEDS_MPC [=y]
QEMUで-nographicオプションを利用する為、コンソールをtty1からttyS0にす る。-nographicを使用せず、GUIウィンドウを利用する場合はtty1で良い。
Symbol: BR2_TARGET_GENERIC_GETTY_PORT [=ttyS0] Type : string Prompt: TTY port Location: -> System configuration -> Run a getty (login prompt) after boot (BR2_TARGET_GENERIC_GETTY [=y]) -> getty options Defined at system/Config.in:217 Depends on: BR2_ROOTFS_SKELETON_DEFAULT [=y] && BR2_TARGET_GENERIC_GETTY [=y]
4.2. busyboxの設定
busyboxの設定を変える場合は以下を使用。
make busybox-menuconfig
デバッグシンボルを有効にする。
Symbol: DEBUG [=y] Prompt: Build BusyBox with extra Debugging symbols Defined at Config.in:652 Location: -> Busybox Settings -> Debugging Options
最適化を無効にする。なくても良いだろうけど、ステップ実行が飛び飛びにな るのが嫌なので。
Symbol: DEBUG_PESSIMIZE [=y] Prompt: Disable compiler optimizations Defined at Config.in:663 Depends on: DEBUG Location: -> Busybox Settings -> Debugging Options -> Build BusyBox with extra Debugging symbols (DEBUG [=y])
4.3. その他の設定
uClibcの設定を変える場合は以下を使用。
$ make uclibc-menuconfig
Linuxカーネルの設定を変える場合は以下を使用。
$ make linux-menuconfig
4.4. GCCのバージョンを4.6.xにする理由
GCC-4.7.x以降でuClibcをビルドするとundefined referenceな関数がいくつか 存在し、stripコマンドを用いない場合にエラーとなってしまう。buildrootで はuClibcの修正待ちというステータスである。
http://buildroot-busybox.2317881.n4.nabble.com/ucilbc-0-9-33-2-fails-to-build-on-buildroot-2013-11-internal-toolchain-td56650.html
uClibcのパッチを持ってくるこ とでx86では問題が解消されるが、ARMでは完全に解消されないようである。 本書ではこの問題を避ける為に4.6.xを使用している。
commit 8d31a6e50db423b89082b64a3250eec1b94a7456 Author: Bernhard Reutner-Fischer <...> Date: Wed Jan 16 13:36:40 2013 +0100 buildsys: link libgcc_eh if DODEBUG with -O0 we (e.g. lockf) might end up with references to _Unwind_Resume, so pull in gcc_eh in this case.. Signed-off-by: Bernhard Reutner-Fischer <...>
5. ビルド
$ make
パッケージをビルドし直すには<package name>-rebuildを実行する。busybox の場合は以下となる。
$ make busybox-rebuild
6. 実行例
output/images/rootfs.ext2にルートファイルシステムのイメージが作成され る。GDBから参照できるようにループバックでバイスとしてマウントする。
$ mkdir mnt $ sudo mount -t ext2 -o loop,rw output/images/rootfs.ext2 mnt/
QEMUを以下の設定で起動する。-hdaオプションで指定したルートファイルシス テムのイメージはパーティションを設定していないのでroot=/dev/sdaでマウ ント先を指定している。
$ qemu-system-i386 --kernel output/images/bzImage \ -hda output/images/rootfs.ext2 \ -gdb tcp::10000 -S \ -nographic \ -append "console=ttyS0,115200 root=/dev/sda rw"
GDBを以下の設定で起動する。
$ cat gdb.scr target remote localhost:10000 symbol-file output/build/busybox-1.22.0/busybox source output/build/busybox-1.22.0 b main la src c $ gdb -x gdb.scr
以下はbusyboxへのシンボリックリンクの/sbin/initからbusyboxが呼び出され、 busyboxのmain関数でbreakした所である。busyboxは複数のコマンド群から形 成されており、シンボリックリンク経由あるいは第一引数にコマンド名を指定 して各コマンドを実行する。