Reputation: 527
I have simple program, which just calls few crypto functions. I can compile it linked dynamically, and it produces ~15KB binary:
gcc -s -o crypt crypt.c -lcrypto
When I try to compile it statically, it produces a gargantuan binary ~4MB:
gcc -s -o crypt crypt.c /usr/lib/x86_64-linux-gnu/libcrypto.a
I used to compile the same binary on previous system (Debian 10, gcc 8, libssl1.1 ), and it produces binary ~55KB.
Now I am compiling i ton Debian 12 and gcc 12 and libssl3 version 3.0.9, and it produces the said huge binary, approx 200x the size.
Is it perhaps possible, it includes all functions in the static binary, instead only the ones I am actually using?
or some other reason why the binary is so huge?
(I need to run my binary on minimal system, which does not have the dependent libraries)
Here is ldd
of the resulting binary:
ldd crypt
linux-vdso.so.1 (0x00007ffd72bdd000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd1680d0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd168662000)
Upvotes: 1
Views: 495
Reputation: 12708
I have simple program, which just calls few crypto functions. I can compile it linked dynamically, and it produces ~15KB binary:
gcc -s -o crypt crypt.c -lcrypto
libcrypto.a
(this problem has nothing to do with statically or dynamically linking) that solve (recursively) a link referencing.When I try to compile it statically, it produces a gargantuan binary ~4MB:
gcc -s -o crypt crypt.c /usr/lib/x86_64-linux-gnu/libcrypto.a
libcrypto.a
(not only the ones that solve references) and this is done independent of the contents of libcrypto.a
(this is, being its contents .so
shared executables or .o
normal static linking executables)compare the output of objdump -h crypt
and you will see the different modules included in the binary in one way or the other.
By the way, the size of an executable doesn't give you the actual final size it will have in memory, as the shared binaries that are linked to it will be loaded by different files that are searched at runtime. If you e.g. check the size of the C runtime library, you will see a tremendous size, and many binaries just don't appear to have it included. But as soon as your program (which uses it) is loaded in memory, the full binary of the library is loaded in memory (but it's text segment will be loaded only once, for all the executables that link against it, making a lot of savings in your system's memory) The same savings approach that made the text segment of a program text to be shared between all processes using the same program (e.g. ls
) is applied to shared libraries used by programs... But they are not included in any form in the executable binary.
The use of archive libraries (.a
files) made the possibility of the linker to decide if any of the files included in the library has to be included or not, based on the need to solve a dependency or no. But for that to work, the linking must reference the library with a -l
option, and not as an object in the command parameter list. Linking of unneeded files is now checked by the linker and this makes a good thing to build libraries of object files that should/shouldn't be linked, based on the internal workings of the linker.
Upvotes: 1