Blink: супербыстрый эмулятор x86_64 размером 119 КБ

mtl3cctuqtftdltyxmsfrdl7wee.png

На Хабре когда-то писали про талантливую программистку Джастин Танни, автора маленьких и очень быстрых приложений. Приятно знать, что она не останавливает свою неординарную деятельность. Например, одна из её последних разработок — крошечный эмулятор под названием Blink размером всего 116 КБ, который очень быстро компилирует WASM и выполняет Linux-программы x86_64 под разными платформами и даже в браузере.
Как уже рассказывалось, Джастин известна не только своей программистской, но и общественной деятельностью. В 2011 году она приняла участие в движении «Оккупируй Уолл-стрит», и чуть ли не сама его начала. По крайней мере, пост с таким названием (OCCUPYWALLSTREET) был опубликован в блоге alt-media Adbusters. Он содержал призыв к мирному протесту на Уолл-Стрит. Джастин же зарегистрировала домен occupywallst.

sm8b-uefjopvchsopggx_loopqw.jpeg

Широкой общественности Танни стала известна в 2014 году, когда обратилась к правительству США с предложением ввести должность гендиректора США, на которую назначить тогдашнего исполнительного директора Google Эрика Шмидта.

RedBean и APE


Одна из наиболее известных её программ — веб-сервер Redbean, который представляет собой кросс-платформенный бинарный файл с сайтом. Точнее, внутри бинарного файла внедрены статические файлы. На выходе мы имеем файл .com, который можно запустить на любом компьютере под Linux, Mac, Windows, FreeBSD, OpenBSD, NetBSD, BIOS. Джастин — автор и кросс-платформенного формата APE (αcτµαlly pδrταblε εxεcµταblε).

Именно благодаря этому формату и появился Redbean. Джастин выяснила, что совмещение в файле заголовков Windows и UNIX позволяет выполнить Windows Portable Executable в качестве скрипта для Thompson shell. Таким образом, бинарный файл запускается на Windows, Linux и Mac OS. Вот шаблон такого кода:

                    MZqFpD='
                    BIOS BOOT SECTOR'
                    exec 7<> $(command -v $0)
                    printf '\177ELF...LINKER-ENCODED-FREEBSD-HEADER' >&7
                    exec "$0" "$@"
                    exec qemu-x86_64 "$0" "$@"
                    exit 1
                    REAL MODE...
                    ELF SEGMENTS...
                    OPENBSD NOTE...
                    NETBSD NOTE...
                    MACHO HEADERS...
                     CODE AND DATA...
                     ZIP DIRECTORY...


Библиотека Cosmopolitan


Библиотека Cosmopolitan, реализует формат APE и даёт возможность компилировать кросс-платформенные бинарные файлы с помощью компилятора GCC.

Цель разработки состояла в том, чтобы сделать С языком однократной сборки, разработки «с нуля» и запуска в любой системе, избегая ограничений, которые препятствуют обмену программным обеспечением.

gcc -g -O -static -fno-pie -no-pie -mno-red-zone -nostdlib -nostdinc -o hello.com hello.c \
 -Wl,--oformat=binary -Wl,--gc-sections -Wl,-z,max-page-size=0x1000 -fuse-ld=bfd -gdwarf-4 \
 -Wl,-T,ape.lds -include cosmopolitan.h crt.o ape.o cosmopolitan.a


В приведённом выше фрагменте кода компилятор Linux перенастроен так, что он будет выводить бинарные файлы, которые будут запускаться в macOS, Windows, FreeBSD, OpenBSD и NetBSD и BIOS.

Braille Dump и Blinkenlights


У Джастин много проектов. Среди них Braille Dump — замена для hexdump -C, которая использует символы брайля в Юникоде для отображения шестнадцатеричных кодов 0×81… 0xff, тем самым улучшая читаемость двоичного кода.

Braille Dump будет работать в Linux 2.6.16 +, Windows Vista +, macOS XNU 15.6 +, FreeBSD 12 +, OpenBSD 6.4 + или NetBSD 9.1 +.

$ curl https://justine.lol/braille/bd.com >bd.com
$ chmod +x bd.com
$ echo 'hello→world→' | ./bd.com
00000000 68 65 6c 6c 6f e2 86 92 77 6f 72 6c 64 e2 86 92 │hello⢚⢠⢁world⢚⢠⢁│
00000010 0a │◙│
00000011


Отладчик командной строки Blinkenlights, который визуализирует изменения памяти программами. Он может эмулировать статически связанные программы i8086 и x86_64-pc-linux-gnu на платформах Linux, Mac, Windows, FreeBSD, NetBSD и OpenBSD.

3-1qp-03zvcfsqoo5jhhatuvhdy.png

Последняя упомянутая утилита отладки имеет отношение к разработке Джастин, которая вызвала достаточно большой интерес. Это Blink, эмулятор x86–64, работающий вдвое быстрее QEMU.

Скучная теория


Прежде чем рассказать о Blink, вспомним о виртуализации и эмуляции. И о QEMU, конечно.

Виртуализация имитирует вычислительную среду (например, операционную систему) для программ, которые в ней работать не могут. Благодаря виртуализации на одном компьютере или сервере может быть создано несколько виртуальных машин (программ, имитирующих работу целого компьютера) с индивидуальным набором программ и выделенным объёмом ресурсов (процессорных, оперативной памяти, накопителей), распределяемых гипервизором основной (хостовой) ОС.

x-7bquniqdobpbus2ezb0aori28.jpeg

Эмуляция в простейшем варианте — это имитация программ или аппаратного комплекса с помощью созданного специально для этого программного обеспечения. Воспроизвести цифровую модель не так просто, но иногда необходимо, если требуется, например, подключить библиотеку, работавшую ещё на Intel 80486 или игру с приставки Sega.

Программы, эмулирующие среду (рабочее окружение) для различных программных комплексов, ОС и т.д называются виртуальными машинами. С их помощью можно поднять Windows на машине с Linux и наоборот. Виртуальных машин на одном компьютере может работать несколько — лишь бы ресурсов хватало.

Приложение с открытым кодом QEMU, предназначено для эмуляции аппаратного обеспечения различных платформ. Программа способна воспроизводить работу процессоров Intel x86 и устройств их ввода-вывода. Она может эмулировать x86 (32 и 64 бит), PowerPC (32 и 64 бит), ARM, MIPS (32 бит), Sprac (32 и 64 бит), Alpha, ColdFire (m68k), CRISv2, MicroBlaze.

QEMU работает на Syllable, FreeBSD, OpenBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android.

Эмулятор использует аппаратную виртуализацию и может работать в режиме полной эмуляции (full-system emulation). В этом случае программа полностью воспроизводит работу компьютера, и в режиме пользовательской эмуляции (user-mode emulation), когда приложения, разработанные для одной среды, запускаются в другой (только в хостовой системе Linux). Во втором случае QEMU превращает инструкции или бинарный код на входе (например, от ARM) в платформонезависимый бинарный код, который далее преобразуется в код или инструкции (к примеру, для x86). В общем, QEMU — отличная программа виртуализации с большими возможностями.

dmcjiwrdeieiwenvw9htsfusk54.png


Blink


Исполняемый файл эмулятора Blink весит всего 221 килобайт, а после отключения дефолтных функций вовсе 115 КБ (вместо 4 мегабайт у QEMU) и работает вдвое быстрее, чем QEMU.

iol4c40jafhanj8mwtp9cfjhc3m.jpeg

Эмулятор предназначается для запуска x86–64 Linux-программ в других операционных системах (macOS, FreeBSD, NetBSD, OpenBSD) и на оборудовании с различной аппаратной архитектурой (x86, ARM, RISC-V, MIPS, PowerPC, s390x). Код проекта написан на языке Си (ANSI C11) и распространяется под лицензией ISC (требуется libc (POSIX.1–2017)).

За счёт чего он такой быстрый? В первую очередь, за счёт использования вышеупомянутого портативного формата и множества оптимизаций. В документации указано, что Blink использует JIT-компилятор (just-in-time), который на лету преобразует исходные инструкции в код на предметно-ориентированном языке в стиле printf (поддерживаются x86_64 и aarch64). Компилятор во время выполнения генерирует функции, которые в свою очередь вызывают микрооперации (micro-op) в машинном коде. Чтобы ускорить выполнение микроопераций, Blink определяет длину байта скомпилированной функции, сканируя её на наличие RET-инструкции (инструкция возврата из ближней процедуры на ассемблере). Затем копирует скомпилированную функцию в JIT.

Кроме того, Blink виртуализирует память, используя тот же подход PML4T, что и аппаратное обеспечение, которое осуществляет поиск по четырёхуровневому основному дереву. Поскольку выполнение четырёх отдельных поисков в таблице страниц при каждом обращении к памяти может быть медленным, Blink проверяет буфер просмотра перевода, который содержит шестнадцать самых последних использованных записей таблицы страниц.

И это далеко не полный список оригинальных оптимизаций, которые сделала Джастин.

Blink проходит 194 тестовых набора из проекта Cosmopolitan Libc, 350 тестовых наборов из проекта Linux Test Project, 108 тестов из набора модульных тестов Musl Libc.

Из интересного, эмулятор способен эмулировать самого себя:

73ll7ewpgbv6gsjfs-t6_p3qjna.png

Поддерживаются форматы ELF, PE (Portable Executables) и bin (Flat executable), собранные с С-библиотеками Cosmopolitan, Glibc и Musl. Встроена поддержка системных вызовов Linux (в том числе fork () и clone ()). Эмулируются наборы инструкций i8086, i386, SSE2, x86_64, SSE3, SSSE3, CLMUL, POPCNT, ADX, BMI2 (MULX, PDEP, PEXT), X87, RDRND, RDSEED, RDTSCP.

Главная директива Blink — поддерживать бинарные файлы, созданные с помощью Cosmopolitan Libc. Собственно, переносимые исполняемые файлы составляют большую часть набора модульных тестов Blink.

Набор инструкций x86_64 в Blink покрыт полностью. Однако ABI системных вызовов Linux намного больше и поэтому не может быть полностью поддержан, если только Blink не эмулирует образ ядра Linux. Но такое чувство, что до этого осталось недолго…

© Habrahabr.ru