ビッグエンディアン検証環境構築 (Debian + systemd-nspawn)

市販のパソコンでビッグエンディアンの機器が絶滅して久しいが（異論あればコメントお願いします）、Debian (Ubuntu可) でビッグエンディアンでのプログラム動作検証環境を割と手っ取り早く作る手順です。ビッグエンディアンのCPU用のDebian Linuxが動作するコンテナを作ります。

# エンディアンって何よ？

```c:endian.c
#include <stdio.h>

int main(void)
{
  unsigned int test = 0x12345678;
  int i; unsigned char *ptr = &test;
  for(i=0; i<sizeof test; i++) printf("%02X ", (unsigned int)ptr[i]);
  putchar('\n');
  return 0;
}
```

をコンパイルして実行すると

```shell-session
$ ./a.out 
12 34 56 78 
```

となるのが**ビッグエンディアン**です。ARM, PowerPC, MIPSなどはエンディアンを選べます。「京」コンピュータで使われたSPARCはビッグエンディアン固定です。一方

```shell-session
$ ./a.out 
78 56 34 12 
```

となるのが**リトルエンディアン**です。インテル・AMDのCPUはリトルエンディアンです。

# qemu-user-static のインストール

`qemu-user-static` はホストLinuxのCPUとは異なるCPU用の実行可能ファイルを直接動作させるためのDebianパッケージです。これをインストールします。

```shell-session
# apt-get install qemu-user-static binfmt-support
```

# systemd-nspawn 用のディレクトリツリーの展開
## MIPS (32-bit big endian) 向けDebianの展開
[MIPS](https://ja.wikipedia.org/wiki/MIPS%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3) 向け [Debian Buster](https://www.debian.org/releases/buster/mips/release-notes/index.ja.html) のコンテナ用ディレクトリツリーを展開します。

```shell-session
# mkdir -p /var/lib/machines
# cd /var/lib/machines
# btrfs subvolume create mips-buster (もしbtrfs使ってれば)
# mmdebstrap --components="main contrib non-free" --architectures=mips --variant=apt\
 --include=systemd-sysv,libpam-systemd,libnss-systemd,dbus-user-session,locales,tzdata,apt-utils,whiptail,vim-tiny,bash \
 buster mips-buster
```

上記の手順だとコンテナ内に最小限のパッケージしか入らないので、より多くのパッケージを入れたい場合、 `--variant=important` あるいは `--variant=standard` を `mmdebstrap` のオプションに指定して下さい。

## PowerPC (64-bit big endian)向けDebianの展開
[PowerPC](https://ja.wikipedia.org/wiki/PowerPC) 向け [Debian PPC64](https://wiki.debian.org/PPC64) のコンテナ用ディレクトリツリーを展開します。PPC64 は https://buildd.debian.org/stats/graph2-week-big.png にあるように[Debian Ports](https://www.debian.org/ports/#portlist-other) の中ではかなりまともです。まず

```config:/var/tmp/ports.txt
deb http://deb.debian.org/debian-ports sid main
deb-src http://deb.debian.org/debian sid main
deb http://deb.debian.org/debian-ports unreleased main
deb-src http://deb.debian.org/debian-ports unreleased main
```

を作ります。その後に

```shell-session
# apt-get install debian-ports-archive-keyring
# cd /var/lib/machines
# btrfs subvolume create ppc64-sid (もしbtrfs使ってれば)
# cat /var/tmp/ports.txt | 
 mmdebstrap --components="main" --architectures=ppc64 --variant=apt \\
 --include=debian-ports-archive-keyring,systemd-sysv,libpam-systemd,libnss-systemd,dbus-user-session,locales,tzdata,apt-utils,whiptail,vim-tiny,bash \\
 sid ppc64-sid -
```

とすると、`/var/lib/machines/ppc64-sid` 以下に`systemd-nspan` 用のディレクトリツリーができます。 `--variant=apt` 以外を指定するとパッケージの欠如によりエラーが出ることがあります。

# コンテナの設定
最低限のコンテナの設定をします。PPC64を使う場合 `mips-buster` を `ppc64-sid` に置き換えて下さい


```shell-session
# systemd-nspawn -M mips-buster -a
以下はコンテナ内部で
# passwd (ルートのパスワードの設定)
# dpkg-reconfigure tzdata （タイムゾーンの設定）
# dpkg-reconfigure locales （ロカールの設定）
# echo mips-buster >/etc/hostname
# exit （コンテナから抜ける）
```

これで最低限のコンテナの設定ができたので、 `systemd-nspawn -M mips-buster -b` でコンテナを起動し、 `machinectl shell mips-buster` でコンテナ内のシェルを起動して操作して下さい。

# qemu-user-static の限界
gdb や [アドレスサニタイザー](https://qiita.com/watson1978/items/60e618c2c48dc7a19868) が使えません。[未定義サニタイザー](https://qiita.com/_EnumHack/items/218018e88cf9c5667507) は使えます。Debian MIPSには `libubsan` が無いため `-fsanitize-undefined-trap-on-error` を `gcc` にオプションとして渡すと未定義サニタイザーが使えます。PPC64ではそういう細工は要りません。

# Failed to enqueue loopback interface start request: Operation not supported

というエラーメッセージが出た場合、 https://bugs.launchpad.net/qemu/+bug/1886811 のパッチを当てると直る可能性があります。 Debian port PowerPC (32-bit big endian) の場合はそのパッチが必要です