Skip to content

Smaller ReleaseSmall by default #22270

@ghost

Description

#6676 in the past helped make ReleaseSmall smaller by default.
However there is more that can be done when ReleaseSmall is enabled.
When you use ReleaseSmall you're asking for a small binary size, not debuggability.
Here are some things that could help achieve smaller binary size:

  • Set unwind_tables to .none by default. This should consistently result in smaller binary size. Unwind tables seem to be used for stack traces (debuggability) which I'm not asking for when I'm compiling with ReleaseSmall. Would be nice to fix Unable to omit unwind tables from binary when using ReleaseSmall + LLVM  #21942 before doing this.
  • (Module: keep frame pointer in ReleaseSmall on x86 #22271) Omit or keep the frame pointer based on the architecture. On some architectures in many cases keeping the frame pointer actually decreases binary size, such as on x86_64.
    This is purely a case-by-case thing and doesn't always apply so I think it's fine to omit frame pointers for most architectures except for some exceptions like x86_64 where in many (again, not all) cases keeping the frame pointer results in smaller binary size. The user can always fine-tune this if they feel the need to so I think a rough "estimate" here would be an improvement over the default in many cases.
    The current default seems to be to always omit the frame pointer if the optimize mode is not Debug.
  • (ELF-specific) don't emit section headers (including the .comment section) for binaries in the self-hosted ELF linker. As far as I understand in most cases section headers are not required for execution of the program itself and are usually useful for debugging and to figure out what a section's name is etc.
    • Do the same for LLVM-emitted binaries. I don't know if this is configurable upfront or if it requires an additional objcopy (see below also) to remove the undesired sections after the binary is emitted.
  • After Builtin function to tell you the maximum stack size of a given function #157 is implemented, it should be possible to get the maximum stack size of the whole program. For a Linux executable, if the required stack size is <= 8 MiB, do not expand the stack size because it will be 8 MiB anyway. This should not be done at runtime but using a builtin.stack_size to know the stack size at compile time so that there's no need to read the ELF itself. Either that or using @stackSize(_start) or something...? This could also be implemented before Builtin function to tell you the maximum stack size of a given function #157 by simply changing the default stack size from 16 MiB to 8 MiB and exposing the stack size using builtin.stack_size. I don't think programs need 16 MiB by default.
  • Make whether to initialize std.os.linux.elf_aux_maybe in lib/std/start.zig configurable using a @import("builtin") flag. (See also: linux: omit getauxval from binary if not needed #22276 (comment))

Additionally, here are some things that should help users achieve smaller binary size on their own:

  • (ELF-specific) support --strip-section-headers from GNU objcopy in Zig objcopy. This option seems to remove section name strings as well as the .comment section from a binary.
  • Support --remove-section from GNU objcopy in Zig objcopy. It should be possible to remove only specific sections from a binary and keep all others. This should be useful in specific cases where undesirable sections are being emitted. Can also be used to omit only .comment and keep section names, etc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSolving this issue will likely involve adding new logic or components to the codebase.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions