chrootでriscv環境を動かす
chroot + qemu-aarch64-staticでaarch64のバイナリがx86_64のPC上で動くことを最近知った。どうやるかというと
# qemu-user-static(qemu-riscv64-static) is required for second stage debootstrap. see https://www.debian.org/releases/stretch/s390x/apds03.html.ja $ sudo apt-get install -y debootstrap qemu-user-static $ mkdir -p ./mnt $ sudo debootstrap --arch=arm64 --foreign --include=ifupdown,netbase,net-tools,openssh-server,vim,file,sudo stretch ./mnt $ sudo cp `which qemu-aarch64-static` ./mnt/debian-rootfs/usr/bin $ ls -ls ~/debian/debootstrap/debootstrap 20 -rwxr-xr-x 1 root root 19076 Jan 21 08:03 /home/vagrant/debian/debootstrap/debootstrap $ sudo chroot ./mnt/debian-rootfs debootstrap/debootstrap --second-stage $ sudo chroot ./mnt
用途としては、rasberry pi3などのarmの(非x86_64 architectureの)環境をboard上でなく、自身のPC(x86_64)で整えることができるのでとても便利である。
- https://www.debian.org/releases/stretch/s390x/apds03.html.ja
- http://blog.kmckk.com/archives/2342452.html
などを参考にした。
qemu-$(arch)-static
と対応するbinfmtの設定がありさえすれば、他のアーキテクチャでも動くはずである。
ということは、riscv architectureでも同じようなことができそうなので、やってみた。
Note) centos7の場合は、debootstrap
はepelレポジトリからとってくると良い:
sudo yum install epel-release # epel.repoが新しくできる。 yum --enablerepo=epel install debootstrap
Reference
- https://wiki.debian.org/RISC-V#Creating_a_riscv64_chroot
- https://gihyo.jp/admin/serial/01/ubuntu-recipe/0603 : 3日くらい前に同じようなことをやってる人がいた😓
本記事は、アーキテクチャによらず、debootstrap
の--foreign
と--second-stage
を用いれば、統一的にクロス開発環境を整えられるという点でメリットが有る。
Preparation
vagrantでホスト環境を整えておく。ubuntu 18.04を入れてるほかは変わったことはしてない:
Vagrant.configure("2") do |config| config.vm.box = "ubuntu/bionic64" config.vm.synced_folder ".", "/home/vagrant/shared" config.vm.provider "virtualbox" do |vb| vb.cpus = 2 vb.memory = "4096" end config.vm.provision "shell", inline: <<-SHELL SHELL end
debootstrap first stage
$ sudo apt-get install -y debootstrap $ mkdir -p ./riscv # debootstrap (option) (version) (path) (MIRROR) # debian-ports-archive-keyring : for `apt-get install` $ sudo debootstrap --arch=riscv64 --foreign \ --include=debian-ports-archive-keyring,ifupdown,netbase,net-tools,openssh-server,file,wget,openssl,sudo \ sid ./riscv http://ftp.ports.debian.org/debian-ports # or add option`--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg`
stretchはなかったので、debianのsid にしている。keyringオプションはパッケージの署名でつけたほうがよいが、つけなくても動く。
reigster binfmt
- chrootの先で
/usr/bin/qemu-riscv64-static
が実行できること。 - riscv64が実行できるbinfmtが準備されていること。
install qemu-riscv64-static
Ubuntu 18.04環境では、sudo apt-get -y qemu-user-static
でqemu-riscv64-staticが取得できなかったので、直接ソースからビルドする。
$ update-binfmts --display | grep riscv # if nothing, we have to build `qemu-riscv64-static` from source. # see https://wiki.qemu.org/Hosts/Linux#Required_additional_packages $ sudo apt-get install -y pkg-config git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev $ git clone https://git.qemu.org/git/qemu.git -b v4.2.0 --depth=1 $ cd qemu && mkdir build && cd build $ mkdir out # You have to build as a static binary. $ ../configure --static --target-list=riscv64-linux-user --prefix=$(pwd)/out $ make && make install $ cd ../../
configure binfmt
# Note that `qemu-riscv64` is from x86_64S $ readelf -h ./qemu/build/out/bin/qemu-riscv64 | grep Machine Machine: Advanced Micro Devices X86-64 $ sudo cp ./qemu/build/out/bin/qemu-riscv64 ./riscv/usr/bin/qemu-riscv64-static $ sudo apt-get install -y binfmt-support $ cat > /tmp/riscv64 <<- EOF > package qemu-user-static > type magic > offset 0 > magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00 > mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff > interpreter /usr/bin/qemu-riscv64-static > EOF
update-binfmtsするところのmagicはELFファイルのheader.
$ sudo update-binfmts --import /tmp/riscv64 update-binfmts: warning: /tmp/riscv64: no executable /usr/bin/qemu-riscv64-static found, but continuing anyway as you request # Any labels will do under binfmt_misc directory $ ls /proc/sys/fs/binfmt_misc/riscv64 /proc/sys/fs/binfmt_misc/riscv64 # if the file doesn't exist, `sudo systemctl binfmt-support` or restart vbox
Note) qemu-riscv64-staticを./riscv/usr/bin/qemu-riscv64-static
に置いているが、今回の目的であれば、/usr/bin/qemu-riscv64-static
に直におく必要はない。chrootの先で/usr/bin/qemu-riscv64-static
というバイナリが存在しさえすればいいだけなので。
configure under chroot
$ sudo chroot ./riscv debootstrap/debootstrap --second-stage # mount $ sudo mount --bind /sys ./riscv/sys $ sudo mount --bind /dev ./riscv/dev $ sudo mount --bind /proc ./riscv/proc # Without this, sudo command would `no tty present and no askpass program specified`.. $ sudo mount --bind /dev/pts ./riscv/dev/pts $ sudo chroot ./riscv # dive into riscv64 root@ubuntu-bionic:/# file `which bash` /bin/bash: ELF 64-bit LSB shared object, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1, BuildID[sha1]=02650defdd2fb0ebdf17ba89a28040bf403790d7, for GNU/Linux 4.15.0, stripped
ということで、riscv64のバイナリが実行できている!
といってもこのままだと、apt-getとかできないので少し修正。
# inside chroot environment $ echo "deb http://ftp.ports.debian.org/debian-ports sid main" >> /etc/apt/sources.list $ apt-get update # for test $ apt-get install -y curl
cleanup
$ sudo umount -v ./riscv/{sys,dev,proc}
で後始末しておく。