I noticed that if I compile a C program with the gcc
or clang
command on macOS 10.15.7 the executable will be around 50 KB, no matter how simple the program. In older versions, the same program produces an executable of just 8 KB. I also noticed that most of the extra size are just large contiguous regions of 0 bytes.
The answer for what the 0 bytes are and how they can be reduced is explained here: Why is my hello world binary mostly zeroes?
Newer versions have more segments in the executable that have to be aligned and their default alignment is larger. Both of these lead to much more padding space in the executable. I can use -mmacosx-version-min=10.14
and -Wl,-segalign,0x1000
to force the compiler to use a lesser alignment and get rid of the __DATA_CONST
section, thus reducing the executable size by up to about 40 KB.
My question is, if using -mmacosx-version-min=10.14
and -Wl,-segalign,0x1000
can both reduce the executable to a fraction of the size for simple programs and can allow the executable to run on older versions of macOS too, are there any unforeseen penalties to using them? If not, why are these settings not the default?
For example:
__DATA_CONST
segment and smaller segment alignment somehow incur a (significantly) longer startup overhead?For what reason(s), if any, might I not want to indiscriminately/automatically use -mmacosx-version-min=10.14
and/or -Wl,-segalign,0x1000
to optimize all of my executables for size?
Adapted from a comment:
A segment size of 0x1000 shouldn't make a difference on x86_64, but it's not available on arm64. The kernel will refuse to load your binary. And
__DATA_CONST
is a security thing, but it arguably has a much greater impact on the arm64e ABI (which Apple has still not stabilized for 3rd parties) than for arm64 without pointer authentication.