5

When I compiled a no-op program:

int main(void)
{
    return 0;
}

with various compilers:

  • GCC (similar result to LLVM as well): Gave a 10-KiB executable (compiled with -s)

    • Sections: .CRT, .bss, .data, .idata, .rdata, .text, .tls

    • Depends on msvcrt.dll and kernel32.dll

  • MSVC 2010: Gave a 5.5 KiB executable (compiled with /MD /Ox)

    • Sections: .data, .rdata, .reloc, .text

    • Depends on msvcr100.dll and kernel32.dll

    • Could have been further reduced by merging .rdata with .text

  • Windows Driver Kit 7.1: Gave a 6.5 KiB executable (compiled with /MD /Ox, linked with msvcrt_winxp.obj to allow it to run on XP)

    • Sections: .data, .rdata, .text

    • Depends on msvcrt.dll and kernel32.dll

    • Could have been further reduced by merging .rdata with .text

  • Windows 2003 Driver Development Kit: Gave a 3.5 KiB executable

    • Sections: .data, .rdata, .text

    • Depends on msvcrt.dll

    • Could have been further reduced by merging .rdata with .text

  • Tiny C Compiler (TCC): Gave a 1.5 KiB executable

    • Sections: .data, .text

    • Depends on msvcrt.dll

So I guess the question is simple:

Is it possible to further reduce GCC or LLVM's target executable sizes so that they are closer to the bare-minimum possible, while still linking to msvcrt.dll?

(Edit: I'm obviously not looking for packers like UPX, etc.)

user541686
  • 205,094
  • 128
  • 528
  • 886
  • Could you explain why are you asking? Do you often compile such a tiny program? Isn't it more important for a compiler to compile well realistic programs?? (most of them are much bigger)! – Basile Starynkevitch Dec 17 '11 at 19:12
  • http://stackoverflow.com/questions/1413171/what-is-strip-gcc-application-used-for, http://embeddedfreak.wordpress.com/2009/02/10/removing-unused-functionsdead-codes-with-gccgnu-ld/ – Ulterior Dec 17 '11 at 19:19
  • @Ulterior: The `-s` option is pretty much the same as `strip`. The other options also didn't help. – user541686 Dec 17 '11 at 19:21
  • On Linux/x86-64/Debian/Sid with `gcc-4.6 -O2 -flto -s nop.c -o nop` I am getting a `nop` file of 4408 bytes, and of 4392 bytes when compiled with `gcc-4.6 -Os -flto -s nop.c -o nop` – Basile Starynkevitch Dec 17 '11 at 19:24
  • @BasileStarynkevitch: Part of it is being paranoid, part of it is actually a practical issue: I often send Base64 versions of executables around, and it's a LOT handier to send a Base64 version of a 1-KiB executable than a 10-KiB executable when you're pasting it within e.g. a message. – user541686 Dec 17 '11 at 19:28
  • Don't you send programs with several hundred lines of source code at least? – Basile Starynkevitch Dec 17 '11 at 19:29

1 Answers1

3

This isn't a particularly meaningful thing to do. It might be possible to eliminate a few things, but as soon as you have a program that actually does anything then it'll pull those things straight back in again.

For example, on another platform (I don't do much Windows stuff), the minimum size for a program is larger than you would think because every program has an atexit handler to clean up. That handler has a possible error case which means it pull in printf and all the I/O stuff. Atexit itself also pulls in malloc and all the memory handing stuff. And no doubt there's a few other bits besides. The end result is a 400KB static binary size. That's annoying in a no-op program, but in reality all programs would need this stuff, so it's a moot point.

In general, if you want to minimise program size, compile with -Os, and try to use -flto or -fwhole-program (but this last will need lots of changes to your build procedure). Also, don't use -g, and do strip the final binaries (if that doesn't break them).

ams
  • 24,923
  • 4
  • 54
  • 75