I am following this archived article. (If you search for "624 a.out", this is where I am at). My binary is coming out to 8480 bytes in size while the article is reaching as low as 624! I'm clearly doing something wrong, but I don't know what. Weirdly enough, removing -static increases the binary size to 13264! Everything I've found online so far talks about how gcc adds a bunch of stuff when using the standard library (which I'm not using), or that static linking takes up a bunch of space (at the moment I don't believe I'm linking with anything).
My terminal
$ gcc -s -Og -march=native -static -nostdlib -fno-exceptions -fno-unwind-tables -fno-rtti -fno-asynchronous-unwind-tables start.S main.cpp
$ wc -c a.out
8744 a.out
$ strip -R .comment a.out
$ strip -R .note.gnu.property a.out
$ strip -R .note.gnu.build-id a.out
strip: a.out: warning: empty loadable segment detected at vaddr=0x400000, is this intentional?
$ wc -c a.out
8480 a.out
$ ./a.out
hello
start.S
#ifdef __linux__
#ifdef __LP64__
.intel_syntax noprefix
.text
.globl _start, syscall5
_start:
xor rbp,rbp
pop rdi
mov rsi,rsp
and rsp,-16
call main
mov rdi,rax /* syscall param 1 = rax (ret value of main) */
mov rax,60 /* SYS_exit */
syscall
ret /* should never be reached, but if the OS somehow fails
to kill us, it will cause a segmentation fault */
syscall5:
mov rax,rdi
mov rdi,rsi
mov rsi,rdx
mov rdx,rcx
mov r10,r8
mov r8,r9
syscall
ret
#endif
#endif
main.cpp
extern "C"
void* syscall5(
void* number,
void* arg1,
void* arg2,
void* arg3,
void* arg4,
void* arg5
);
int main(int argc, char* argv[])
{
syscall5(
(void*)1, /* SYS_write */
(void*)1,
(void*)"hello\n",
(void*)6,
0, /* ignored */
0 /* ignored */
);
return 0;
}
Edit:
Adding -Wl,--nmagic shrank the binary to a size much closer to what I was expecting. Seems some security changes made to the linker were responsible for the extra padding. See here.