Reputation:
I tested two successfully exiting minimal programs, first uses libc
, second does not use libc
.
First:
segment .text
global main
main:
xor eax, eax
ret
Build and check size:
yasm -f elf64 main.s; clang -o main main.o; stat ./main
...
Size: 8552
...
Second:
segment .text
global _start
_start:
mov eax, 60
xor edi, edi
syscall
Build and check size:
yasm -f elf64 main.s; ld -o main main.o; stat ./main
...
Size: 704
---
Obviously program using main is larger in size. Why linkers does not strip main routine from binaries to optimise for size? I mean linkers that get object files after compilation of C program.
Upvotes: 0
Views: 98
Reputation: 213596
why linker does not strip main routine from executable?
Because linkers in general do not strip any routines from the object files they are given. They are simply not in that business.
Linkers do not operate on routines, they operate on sections. Some linkers can do limited removal of unreferenced sections, e.g. GNU BFD ld and Gold have --gc-sections
flag, but in your example there are no unreferenced sections, so nothing would be GC'd anyway.
Now, the difference between your two programs is that the one with main
links in C runtime startup (usually crt0.o
), and sets up argc
and argv
arguments the way main
is defined to expect them.
Your main
doesn't care about this, but it would take a really smart linker to deduce that. Also, your main
does care about calling sys_exit
after returning, so it actually needs crt0.o
for proper shutdown.
Is is that argc/argv setting-up process, that takes up few kilobytes?
If you are using GNU ld, you can ask the linker to tell you exactly what's using how much space with the linker --print-map
argument.
On ELF platforms, you can also use nm main
to see which symbols are taking up space in the final binary, and use ld -y <symbol> ...
to see where these symbols are getting linked from.
Upvotes: 1