henry_flower: A melancholy wolf (Default)
henry_flower ([personal profile] henry_flower) wrote2024-02-03 11:27 pm

aarch64 → x86_64

Шо тут відбувається? (Підказка: ніякого кроскомпайлінґу)

$ make
cc -std=c17 -Wall -Wextra -Wpedantic -O2    flperc.c   -o flperc
$ readelf -h flperc | grep Machine
  Machine:                           Advanced Micro Devices X86-64

$ rm flperc
$ nspawn-run ~/vm/systemd/debian64-aarch64 make
cc -std=c17 -Wall -Wextra -Wpedantic -O2    flperc.c   -o flperc
$ readelf -h flperc | grep Machine
  Machine:                           AArch64

nspawn-run--невеликий врапер (21 LOC шелóвих) над лайнаксним systemd-nspawn, який з'явився того ж року що і докер (2013), але не став популярним.

Врапер на федорі пускає systemd-nspawn над контейнером--директорією з aarch64 деб'яновським дістро і тоді

  • байндить $HOME до контейнера, в якому заздалегідь було

    • створено користувача з таким самим ім'ям/uid/gid як на федорі;
    • встановлено gcc/make/&c.
  • перед виконуванням make, змінює директорію ув контейнері на таку саму як поточна ув федорі.

Все виглядає так, ніби $HOME був на окремому драйві, який переставили до іншої воркстейшон (яка має CPU іншої архітектури). Там запустили make, потім зе драйва повернули на місце.

(Нового тут є 0, все це давно роблять з докером, але треба же чимось виділятися.)

aarch64 gcc ув контейнері працює на федорі x86_64 через

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

Я донедавна на qemu-*-static не звертав уваги, аж поки випадково не виконав aarch64 éкзек'ютабл на федорі (рєзультатом чєґо бил нєобичайно удівльон). Загалом, binfmt_misc мені ніколи не подобався з точки зору безпеки, але задля перетворювання на льоту інструкцій aarch64→x86_64, такі записи binfmt_misc вирішив не видаляти.

Команда

$ nspawn-run -b ~/vm/systemd/debian64-aarch64

запустить контейнера як псевдо-віртуальну мошину, яка всередені має systemd з (я вибачаюся) підом 1, але яка з федори виглядає ось так:

На відміну від стародавнього chroot'у, процеси хоста воно не бачить. Хост навпаки, бачить геть усе, а systemd навіть вміє оперувати над таким контейнером:

$ machinectl
MACHINE          CLASS     SERVICE        OS     VERSION ADDRESSES
debian64-aarch64 container systemd-nspawn debian 12      -

$ sudo systemctl -M debian64-aarch64
...
$ sudo journalctl -M debian64-aarch64
...

Шкода що qemu-aarch64-static підтримує не всі лайнаксні сісколи, і деякі речі не працюють взагалі:

$ nspawn-run ~/vm/systemd/debian64-aarch64 strace -e t=uname arch
/usr/bin/strace: test_ptrace_get_syscall_info: PTRACE_TRACEME: Function not implemented
/usr/bin/strace: ptrace(PTRACE_TRACEME, ...): Function not implemented
/usr/bin/strace: PTRACE_SETOPTIONS: Function not implemented
/usr/bin/strace: detach: waitpid(12): No child processes
/usr/bin/strace: Process 12 detached

Хто хоче зробити собі те саме, то archwiki має інструкцію для debootstrap, а врапер є осьо нижче:

#!/bin/sh

usage() {
    echo Usage: nspawn-run [-rb] [-d dir_to_bind] container_dir [cmd] 2>&1
    exit 1
}

dirs_to_bind=$HOME
bind=--bind
boot="-u $USER"
while getopts rbd: opt; do
    case $opt in
        r) bind=--bind-ro ;;
        b) boot=-b ;;
        d) dirs_to_bind="$dirs_to_bind $OPTARG" ;;
        *) usage
    esac
done
shift $((OPTIND-1))

[ -d "$1" ] || usage; container=$1; shift
[ 0 = $#  ] || boot="$boot -a"

dirs_to_bind=`printf -- "$bind %s " $dirs_to_bind`
exec sudo systemd-nspawn -q -D "$container" $dirs_to_bind \
     --chdir="$PWD" $boot "$@"

-d /foo -d /bar додає екстра директорії, окрім $HOME; -r монтує їх зсередини контейнера read-only.

vak: (Default)

[personal profile] vak 2024-02-03 09:56 pm (UTC)(link)
Це корисна фіча: можливість прозоро запускати бінарники другої архітектури. Але насправді дивує, коли перший раз зіштовхуєшся. 😀