0

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.

  • Does this answer your question? [What is a reasonable minimum number of assembly instructions for a small C program including setup?](https://stackoverflow.com/questions/60570279/what-is-a-reasonable-minimum-number-of-assembly-instructions-for-a-small-c-progr) – wxz Apr 18 '21 at 22:02
  • @wxz No, the extra size here isn't because of assembly instructions. – Joseph Sible-Reinstate Monica Apr 18 '21 at 22:03
  • It looks like almost all of the size is null bytes to pad to the 0x1000 and 0x2000 positions. I'm not 100% sure why though. – Joseph Sible-Reinstate Monica Apr 18 '21 at 22:14
  • With `-nostdlib`, there's nothing extra that's being linked in with `-static` (no libc, no CRT start files), so no reason to expect `-static` to increase executable size. `-static` implies `-no-pie`, and without it you're still getting a dynamically-linked executable. [What's the difference between "statically linked" and "not a dynamic executable" from Linux ldd?](https://stackoverflow.com/q/61553723) – Peter Cordes Apr 18 '21 at 22:30

0 Answers0