概要

chroot 先で異なる CPU architecture をエミュレーションしたい場合は、static link された QEMU user space emulator を使うと便利である。しかし、Debian stretch でインストールできる QEMU 3.1 では APT コマンドが発行されると Segmentation fault が発生し、エミュレーションが正常に完了しない。QEMU 7 以降を使用すると動作する報告があるので、ソースコードをビルドして最新版をインストールする。

QEMU を static link でビルドする際には、静的ライブラリが必要である。しかし、Debian stretch (そしておそらくそれ以降) ではいくつかの必要な静的ライブラリが配布されていない (e.g. libpulseaudio0 は共有ライブラリのみの配布)。依存ライブラリはかなり多く、それぞれビルドするのはかなり難儀であるが、多くが音声や画面描画のツールキットであり、目的によっては不要となるものが多い。今回は、https://github.com/OmeSatoFoundation/ome2023 をビルドするのに (おそらく) 最低限必要なライブラリのみをリンクするよう設定する。

作業は QEMU をビルドして binfmt を設定しているだけなので、他のディストリビューション等でも動作する可能性はある。一方で、QEMU を static build するのに必要な静的ライブラリの配布状況はディストリビューションにより異なるので、Debian stretch 以外で試す際は無効にすべきライブラリが増えるかもしれない。

手順

QEMU のビルド

まず、QEMU をダウンロードする。今回は、7.1.0 をダウンロードした。

https://www.qemu.org/download/

ビルドする。キモは、--static で static link させることと、--disable-xxx で余剰な依存ライブラリをへらすこと。

./configure prefix=/usr --static '--disable-tools' '--disable-sdl' '--disable-gtk' '--disable-vnc' '--disable-virtfs' '--disable-attr' '--disable-libiscsi' '--disable-libnfs' '--disable-libusb' '--disable-opengl' '--disable-numa' '--disable-usb-redir' '--disable-bzip2' '--audio-drv-list=' '--disable-guest-agent' '--disable-vte' '--disable-mpath' '--disable-libudev' '--disable-vhost-user' '--disable-curl' '--disable-gnutls' --disable-alsa --disable-coreaudio --disable-pa
make
sudo make install

(--prefix=/usr)/bin/qemu-aarch64 が生成される。これは事前の --static 設定のおかげで静的リンクされているので

$ ldd $(which qemu-aarch64)
        statically linked

慣例に従い qemu-aarch64-static にリネームする。

ln -sf /usr/bin/qemu-aarch64 /usr/bin/qemu-aarch64-static

binfmt の更新

binfmt を更新し、システムコールが正しく変換されるようにする。

/usr/share/binfmts/qemu-aarch64 に設定ファイルを書く。

package qemu-user-static
interpreter /usr/bin/qemu-aarch64-static
flags: OC
offset 0
magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00
mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff

参考: ARMing Yourself - Working with ARM on x86_64 | Code Pyre https://codepyre.com/2019/12/arming-yourself/

設定ファイルをもとに更新する。

sudo update-binfmts --import qemu-aarch64
sudo update-binfmts --enable qemu-aarch64

update-binfmts が反映されたか確認。/proc/sys/fs/binfmt_misc/qemu-aarch64/usr/share/binfmts/qemu-aarch64 と等価か確認する。

$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags:
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

以上で、qemu-aarch64-staticchroot 下ではたらき、異なるCPUアーキテクチャのエミュレーションが可能になる。

今後の展望

これをコンテナで行う。QEMU と、binfmt が必要。

Ubuntu以外のディストリビューションでarmhfなDocker imageを作成する - Qiita https://qiita.com/abtc/items/0696ebef11038f29261c

また、余談だが、chroot 先は .iso などディスクのアーカイブのループバックデバイスであることが多い。ループバックデバイスを (上手に隔離の上で) コンテナ内で使用するには、工夫が必要である。適当な隔離の上コンテナ内で異なる CPU アーキテクチャ向けのディスクアーカイブを (手動で) losetup し、chroot して作業する方法を調査することが今後の課題として残る。