[Ненормальное программирование, Программирование, Компиляторы, C] Один бинарник, любое окружение. Магия чистого C
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Как мы представляем себе кроссплатформенность? Мы пишем программу на языке, который либо компилируется в исполняемый файл отдельно для каждой поддерживаемой платформы, либо использует разновидность виртуальной машины вместо бинарника (и тогда эта среда должна присутствовать в целевых системах). Есть также и низкоуровневые языки, на которых писать серьёзные программы менее удобно, чем на высокоуровневых монстрах со своими компиляторами или рантаймами, но зато такие программы менее требовательны к предустановленному софту или наличию ОС в принципе, как и менее разборчивы в архитектуре. И всё же, есть возможность писать один и тот же код и собирать один и тот же бинарь под все популярные архитектуры и ОС (и даже bare metal), и эта возможность появилась благодаря гениальной Justine Tunney. Она написала Cosmopolitan, библиотеку на C, позволяющую исполнять один и тот же код на любой машине, подобно Java… но без какого-либо предустановленного интерпретатора или виртуальной машины! Один и тот же скомпилированный файл может исполняться как минимум в любом дистрибутиве Linux, на Mac OS, Windows NT, FreeBSD, OpenBSD, и NetBSD и на bare-metal на x86 и ARM*. Это настоящая магия.
* — для ARM всё же потребуется своего рода эмулятор, но он также встраивается в единственный исполняемый файл. При этом страдает минимальный размер файла, но не его производительность, и разница всё равно будет заметно только для совсем крохотных программ вроде hello world.
αcτµαlly pδrταblε εxεcµταblε
Всё началось с переосмысления формата Windows Portable Executable. Оказывается, совместив в одном файле заголовки Windows и UNIX, можно выполнять WPE как скрипт для Thompson shell: пока его не сменил sh в седьмой версии UNIX, скрипты не использовали шебанг. А значит, такой формат позволяет бинарнику запускаться на 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...
На видео ниже — визуализация выполнения этого кода в другом инструменте этого же разработчика, Blinkenlights. Если при выполнении файла в Win символы MZqFpD распознаются как заголовок WPE, то при запуске под UNIX это pop %r10 ; jno 0x4a ; jo 0x4a, \177ELF считывается как jg 0x47. Затем программа пропускает выражение mov, что означает что она выполняется в системе, а не в загрузчике, и переходит к точке входа в скрипт.
Извините, данный ресурс не поддреживается. :(
Этот формат теперь называется αcτµαlly pδrταblε εxεcµταblε (если вы против пост-мета-сарказмо-иронии, лучше не читайте исходники у этого разработчика, а формат называйте APE. Исходники правда классные). Проект Cosmopolitan — пример реального использования APE, развивавшийся от PoC до первых релизов и включения в другие проекты.
Скрытый текст
SPL
Нужна лишь одна строка, чтобы прокачать gcc для компиляции в APE:
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 \
-Wl,-T,ape.lds -include cosmopolitan.h crt.o ape.o cosmopolitan.a
Помимо простоты, Cosmopolitan удивляет легковесностью: hello world весит примерно в сто раз меньше аналога на «оптимизированном и кроссплатформенном» Go и занимает всего 16 килобайт! Вышеупомянутый эмулятор для ARM уменьшит превосходство с 100 до 10 раз, но такая большая разница только для такого малого размера. Но и это не всё: библиотека ещё и показывает великолепную производительность: чуть медленнее glibc, но с меньшим размером кода, и значительно быстрее Musl и Newlib при сопоставимом размере.
Например, по быстродействию функции memcpy() Cosmopolitan вообще всех обгоняет из-за специфичной механики копирования памяти:
Работает это так: чтобы ускорить часто используемые функции libc, функция вызывается внутри макроса, в котором компилятор получает информацию об используемых регистрах CPU, что позволяет экономить на сохранении состояния CPU, работая только с изменёнными регистрами. На примере memcpy:
#define memcpy(DEST, SRC, N) ({ \
void *Dest = (DEST); \
void *Src = (SRC); \
size_t Size = (N); \
asm("call memcpy" \
: "=m"(*(char(*)[Size])(Dest)) \
: "D"(Dest), "S"(Src), "d"(n), \
"m"(*(char(*)[Size])(Src)) \
: "rcx", "xmm3", "xmm4", "cc"); \
Dest; \
})
При этом ускоряется не только сам объект оптимизации, но и, в качестве побочного эффекта, вызывающие его функции. Таким образом, только при применении оптимизации к memcpy, количество генерируемого кода для многих других функций уменьшилось на треть.
Вот так выглядит код функции strlcpy, BSD-аналог strcpy:
/**
* Copies string, the BSD way.
*
* @param d is buffer which needn't be initialized
* @param s is a NUL-terminated string
* @param n is byte capacity of d
* @return strlen(s)
* @note d and s can't overlap
* @note we prefer memccpy()
*/
size_t strlcpy(char *d, const char *s, size_t n) {
size_t slen, actual;
slen = strlen(s);
if (n) {
actual = MIN(n - 1, slen);
memcpy(d, s, actual);
d[actual] = '\0';
}
return slen;
}
А теперь сравним результаты её компиляции:
классический libc
cosmopolitan libc
strlcpy:
push %rbp
mov %rsp,%rbp
push %r14
mov %rsi,%r14
push %r13
mov %rdi,%r13
mov %rsi,%rdi
push %r12
push %rbx
mov %rdx,%rbx
call strlen
mov %rax,%r12
test %rbx,%rbx
jne 1f
pop %rbx
mov %r12,%rax
pop %r12
pop %r13
pop %r14
pop %rbp
ret
1: cmp %rbx,%rax
mov %r14,%rsi
mov %r13,%rdi
cmovbe %rax,%rbx
mov %rbx,%rdx
call memcpy
movb $0,0(%r13,%rbx)
mov %r12,%rax
pop %rbx
pop %r12
pop %r13
pop %r14
pop %rbp
ret
.endfn strlcpy,globl
strlcpy:
mov %rdx,%r8
mov %rdi,%r9
mov %rsi,%rdi
call strlen
test %r8,%r8
je 1f
cmp %r8,%rax
lea -1(%r8),%rdx
mov %r9,%rdi
cmova %rax,%rdx
call MemCpy
movb $0,(%r9,%rdx)
1: ret
.endfn strlcpy,globl
Разница налицо!
Заключение
«As far as I'm concerned, this is literal magic», «this is the best programming-related thing I've seen on the internet in a long time», «This is one of the most interesting projects I have seen this year» — комментарии на hackernews и в твиттере буквально ломятся от восторженных возгласов. Несмотря на некоторые ограничения, концепция APE действительно выглядит как большой и важный прорыв в подходе к кроссплатформенности. Уже есть несколько реальных примеров использования Cosmopolitan, из них самым мощным точно можно назвать сервер Redbean. Однофайловый, независимый от платформы сервер. Потенциал этой штуки сложно даже мысленно охватить, а тред на HN собрал больше двух тысяч комментов. Помимо этого в твиттере автора периодически появляются всякие интерпретаторы (Lua, JS) и примеры помельче.
Облачные серверы по низким ценам для любых задач. Используем новейшее железо, лучший дата-центр в Москве уровня надёжности TIER IV, бесплатно предоставляем защиту от DDoS-атак на любом тарифном плане, который можно создать самостоятельно в течение мгновения.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
оригинал
===========
Источник:
habr.com
===========
Похожие новости:
- [Open source] Нетехнические вызовы Open Source разработки
- [Open source, Учебный процесс в IT, Управление персоналом, Карьера в IT-индустрии] Ваша любовь к разработке в первую очередь выгодна работодателю (перевод)
- [Cisco, Сетевые технологии] Spoke to spoke мультикаст в сетях DMVPN
- [Исследования и прогнозы в IT] Как ИТ-гиганты теряют лоск и становятся все более скучными
- [Разработка мобильных приложений, Машинное обучение, Искусственный интеллект, Natural Language Processing] OpenAI: более 300 сторонних приложений работают на GPT-3
- [Java, C++, Go] Внимание: все сервисы Bintray будут прекращены, а ваши учетные записи будут отключены 1 мая 2021 года. — JFrog
- [Децентрализованные сети, Информационная безопасность, Машинное обучение, Искусственный интеллект] Роевое обучение: превратите распределенные данные в фактор успеха
- [Киберпанк, Научно-популярное, Мозг, Здоровье] УЗИ для НКИ: неинвазивное считывание активности мозга
- [Информационная безопасность, Браузеры, IT-компании] Я тебя найду по JS, или какие возможности для фингепринтинга дают современные web-технологии
- Выпуск файлового менеджера GNOME Commander 1.12
Теги для поиска: #_nenormalnoe_programmirovanie (Ненормальное программирование), #_programmirovanie (Программирование), #_kompiljatory (Компиляторы), #_c, #_justine_tunney, #_cosmopolitan, #_c, #_krossplatformennost (кроссплатформенность), #_ape, #_blog_kompanii_maklaud (
Блог компании Маклауд
), #_nenormalnoe_programmirovanie (
Ненормальное программирование
), #_programmirovanie (
Программирование
), #_kompiljatory (
Компиляторы
), #_c
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 12:59
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Как мы представляем себе кроссплатформенность? Мы пишем программу на языке, который либо компилируется в исполняемый файл отдельно для каждой поддерживаемой платформы, либо использует разновидность виртуальной машины вместо бинарника (и тогда эта среда должна присутствовать в целевых системах). Есть также и низкоуровневые языки, на которых писать серьёзные программы менее удобно, чем на высокоуровневых монстрах со своими компиляторами или рантаймами, но зато такие программы менее требовательны к предустановленному софту или наличию ОС в принципе, как и менее разборчивы в архитектуре. И всё же, есть возможность писать один и тот же код и собирать один и тот же бинарь под все популярные архитектуры и ОС (и даже bare metal), и эта возможность появилась благодаря гениальной Justine Tunney. Она написала Cosmopolitan, библиотеку на C, позволяющую исполнять один и тот же код на любой машине, подобно Java… но без какого-либо предустановленного интерпретатора или виртуальной машины! Один и тот же скомпилированный файл может исполняться как минимум в любом дистрибутиве Linux, на Mac OS, Windows NT, FreeBSD, OpenBSD, и NetBSD и на bare-metal на x86 и ARM*. Это настоящая магия. * — для ARM всё же потребуется своего рода эмулятор, но он также встраивается в единственный исполняемый файл. При этом страдает минимальный размер файла, но не его производительность, и разница всё равно будет заметно только для совсем крохотных программ вроде hello world. αcτµαlly pδrταblε εxεcµταblε Всё началось с переосмысления формата Windows Portable Executable. Оказывается, совместив в одном файле заголовки Windows и UNIX, можно выполнять WPE как скрипт для Thompson shell: пока его не сменил sh в седьмой версии UNIX, скрипты не использовали шебанг. А значит, такой формат позволяет бинарнику запускаться на 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... На видео ниже — визуализация выполнения этого кода в другом инструменте этого же разработчика, Blinkenlights. Если при выполнении файла в Win символы MZqFpD распознаются как заголовок WPE, то при запуске под UNIX это pop %r10 ; jno 0x4a ; jo 0x4a, \177ELF считывается как jg 0x47. Затем программа пропускает выражение mov, что означает что она выполняется в системе, а не в загрузчике, и переходит к точке входа в скрипт. Извините, данный ресурс не поддреживается. :( Этот формат теперь называется αcτµαlly pδrταblε εxεcµταblε (если вы против пост-мета-сарказмо-иронии, лучше не читайте исходники у этого разработчика, а формат называйте APE. Исходники правда классные). Проект Cosmopolitan — пример реального использования APE, развивавшийся от PoC до первых релизов и включения в другие проекты. Скрытый текстSPLНужна лишь одна строка, чтобы прокачать gcc для компиляции в APE: 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 \ -Wl,-T,ape.lds -include cosmopolitan.h crt.o ape.o cosmopolitan.a Помимо простоты, Cosmopolitan удивляет легковесностью: hello world весит примерно в сто раз меньше аналога на «оптимизированном и кроссплатформенном» Go и занимает всего 16 килобайт! Вышеупомянутый эмулятор для ARM уменьшит превосходство с 100 до 10 раз, но такая большая разница только для такого малого размера. Но и это не всё: библиотека ещё и показывает великолепную производительность: чуть медленнее glibc, но с меньшим размером кода, и значительно быстрее Musl и Newlib при сопоставимом размере. Например, по быстродействию функции memcpy() Cosmopolitan вообще всех обгоняет из-за специфичной механики копирования памяти: Работает это так: чтобы ускорить часто используемые функции libc, функция вызывается внутри макроса, в котором компилятор получает информацию об используемых регистрах CPU, что позволяет экономить на сохранении состояния CPU, работая только с изменёнными регистрами. На примере memcpy: #define memcpy(DEST, SRC, N) ({ \
void *Dest = (DEST); \ void *Src = (SRC); \ size_t Size = (N); \ asm("call memcpy" \ : "=m"(*(char(*)[Size])(Dest)) \ : "D"(Dest), "S"(Src), "d"(n), \ "m"(*(char(*)[Size])(Src)) \ : "rcx", "xmm3", "xmm4", "cc"); \ Dest; \ }) При этом ускоряется не только сам объект оптимизации, но и, в качестве побочного эффекта, вызывающие его функции. Таким образом, только при применении оптимизации к memcpy, количество генерируемого кода для многих других функций уменьшилось на треть. Вот так выглядит код функции strlcpy, BSD-аналог strcpy: /**
* Copies string, the BSD way. * * @param d is buffer which needn't be initialized * @param s is a NUL-terminated string * @param n is byte capacity of d * @return strlen(s) * @note d and s can't overlap * @note we prefer memccpy() */ size_t strlcpy(char *d, const char *s, size_t n) { size_t slen, actual; slen = strlen(s); if (n) { actual = MIN(n - 1, slen); memcpy(d, s, actual); d[actual] = '\0'; } return slen; } А теперь сравним результаты её компиляции: классический libc cosmopolitan libc strlcpy:
push %rbp mov %rsp,%rbp push %r14 mov %rsi,%r14 push %r13 mov %rdi,%r13 mov %rsi,%rdi push %r12 push %rbx mov %rdx,%rbx call strlen mov %rax,%r12 test %rbx,%rbx jne 1f pop %rbx mov %r12,%rax pop %r12 pop %r13 pop %r14 pop %rbp ret 1: cmp %rbx,%rax mov %r14,%rsi mov %r13,%rdi cmovbe %rax,%rbx mov %rbx,%rdx call memcpy movb $0,0(%r13,%rbx) mov %r12,%rax pop %rbx pop %r12 pop %r13 pop %r14 pop %rbp ret .endfn strlcpy,globl strlcpy:
mov %rdx,%r8 mov %rdi,%r9 mov %rsi,%rdi call strlen test %r8,%r8 je 1f cmp %r8,%rax lea -1(%r8),%rdx mov %r9,%rdi cmova %rax,%rdx call MemCpy movb $0,(%r9,%rdx) 1: ret .endfn strlcpy,globl Разница налицо! Заключение «As far as I'm concerned, this is literal magic», «this is the best programming-related thing I've seen on the internet in a long time», «This is one of the most interesting projects I have seen this year» — комментарии на hackernews и в твиттере буквально ломятся от восторженных возгласов. Несмотря на некоторые ограничения, концепция APE действительно выглядит как большой и важный прорыв в подходе к кроссплатформенности. Уже есть несколько реальных примеров использования Cosmopolitan, из них самым мощным точно можно назвать сервер Redbean. Однофайловый, независимый от платформы сервер. Потенциал этой штуки сложно даже мысленно охватить, а тред на HN собрал больше двух тысяч комментов. Помимо этого в твиттере автора периодически появляются всякие интерпретаторы (Lua, JS) и примеры помельче. Облачные серверы по низким ценам для любых задач. Используем новейшее железо, лучший дата-центр в Москве уровня надёжности TIER IV, бесплатно предоставляем защиту от DDoS-атак на любом тарифном плане, который можно создать самостоятельно в течение мгновения. Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации! оригинал =========== Источник: habr.com =========== Похожие новости:
Блог компании Маклауд ), #_nenormalnoe_programmirovanie ( Ненормальное программирование ), #_programmirovanie ( Программирование ), #_kompiljatory ( Компиляторы ), #_c |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 12:59
Часовой пояс: UTC + 5