Reducing Linux Binary Size

TLDR How do I write my own _start procedure while still dynamically linking with the systems libc?

Hey everybody,
Using gcc on my Ubuntu machine an empty main function compiles to a 14.3 Kb binary.
Typically on Windows I would compile without the runtime library to reduce the size, I just call the native API and everything works fine.
But on Linux the the runtime library is the native API. Because of this, I still want to dynamically link to libc; I don't want to use syscall.
I know I can get the Binary size down to 624 bytes if I don't link with libc, but then I wont be able to use libraries like xcb which requires you to call free.
I believe the startup files are causing the bloat, so my Idea was to try and write the initialization code myself, but I can't find any documentation on that.
The disassembly doesn't seem to be that much code, so I'm not sure whats taking up to much space. Does any one have any experience with doing this?
Are there any other things to watch-out for, like Initializing globals or something?

Edited by SedatedSnail on
You can still call functions to libc and provide your own _start. That will work fine.

Documentation on how executable starts is architecture specific. For x86_64 it is documented in System V Application Binary Inter...Architecture Processor Supplement. "3.4 Process Initialization".

You can check what typical _start does, for example, by looking into musl source code - __libc_start_main function in __libc_start_main.c file. As you said, it is not much.
Awesome, thanks for the links! Looks like these will be super useful.
Have you tried dlopen/dlsym on libc? I suspect you have to initialize libc with libc_start_main, but maybe not.

Edited by Lex Martin on