Я скомпилировал свой проект со следующими флагами: clang -MMD -MP -D_FORTIFY_SOURCE=2 -Weverything -Wno-poison-system-directories -O2 -fPIE -fPIC -fstack-protector -finline-functions -march=native -mtune=native src/getargv.c -o bin/getargv
, который создал исполняемый файл размером 49 КБ (50224Б) и 96% (47799Б) байтов NULL, по данным xxd -p -c 1 < bin/getargv | sort | uniq -c
и ls -l bin/getargv
.
llvm-size --format=darwin bin/getargv
говорит:
Segment __PAGEZERO: 4294967296
Segment __TEXT: 16384
Section __text: 1220
Section __stubs: 78
Section __stub_helper: 146
Section __cstring: 41
Section __unwind_info: 96
total 1581
Segment __DATA_CONST: 16384
Section __got: 32
total 32
Segment __DATA: 16384
Section __la_symbol_ptr: 104
Section __data: 8
Section __bss: 8
total 120
Segment __LINKEDIT: 1072
total 4295017520
Таким образом, исполняемый файл - это байты 3*16384+1072=50224
на диске (соответствует ls -l
), но в файле afaict есть только байты данных 1581+32+120+1072=2805
(94% пусто, что довольно близко к 96% выше, я предполагаю некоторые заполнители и нулевые байты в данных и т. д. ).
Похоже, что должен быть способ уменьшить размер файла, но команда strip не повлияла на размер.
Есть ли способ уменьшить размер сегмента? Или лучше убрать исполняемый файл?
[Редактировать]
$ du -h bin/getargv
52K bin/getargv
Проверил с xxd, нули.
Самый простой способ уменьшить размер - использовать Linux;) Похоже, компоновщик делает что-то действительно наполовину и не чередует сегменты в файле, как это стандартно для Gnu LD?
К сожалению, linux не подходит для этой программы, он существует, чтобы предоставить только sysctl для macOS, чтобы восполнить отсутствие /proc/<pid>/cmdline
.
Вы уверены, что он действительно занимает так много места на диске? Дисковые блоки с нулевыми значениями обычно оптимизируются. Используйте du -h bin/getargv
, чтобы узнать, сколько места он фактически использует.
Обновленный вопрос с выводом du
.
Разве сегменты Mach-O не требуют выравнивания страницы (16k в этой системе)? Если так, то я не думаю, что вы сможете выиграть, не потеряв ни одного сегмента… Это GOT в __DATA_CONST должно быть заманчиво для таргетинга, насколько вы привязаны к PIC / PIE?
Что дает вам уверенность в том, что есть блоки нулей побольше? Вы заглянули в двоичный файл? Могут быть всевозможные значения, превышающие 8-битные, с одиночными нулями, в дополнение к кодам операций, которые содержат нули.
@thebusybee да, я посмотрел на шестнадцатеричный вывод, там огромные серии всего по 00 байт.
@JamesGreenhalgh, это интересно, я бы подумал, что сегменты будут просто загружаться в ОЗУ при соответствующем выравнивании, а не храниться на диске таким образом.
Отвечает ли это на ваш вопрос? Почему не оптимизированы байты заполнения в исполняемых файлах?
Может также увидеть это: stackoverflow.com/a/65449833
Отвечает ли это на ваш вопрос? Почему мой двоичный файл hello world в основном нули?
@Siguza Я думаю, что второе.
Busybee и Siguza - да, эти ссылки хорошо это объясняют и даже дают мне возможность немного уменьшить размер исполняемого файла. Вы можете пометить это как дублирование или что-то еще, если хотите.
пропустите его через сжатие lz, чтобы увидеть энтропию. если он сократится до ~ 3k / 4k, вы будете уверены, что все равно нулю. Если нет, то его просто нет в списке.