I assembled a simple "Hello, world" program and linked it using TCC, after which I got 4196 bytes of an executable.
The program has 31 sections: ['', '.text', '.data', '.bss', '.symtab', '.strtab', '.rel.text', '.rodata', '.rodata.cst4', '.note.GNU-stack', '.init', '.rel.init', '.gnu.linkonce.t.__x86.get_pc_thunk.bx', '.fini', '.rel.fini', '.text.unlikely', '.text.__x86.get_pc_thunk.bx', '.eh_frame', '.rel.eh_frame', '.preinit_array', '.init_array', '.fini_array', '.interp', '.dynsym', '.dynstr', '.hash', '.dynamic', '.got', '.plt', '.rel.got', '.shstrtab']
. I feel that's a real lot for such a simple binary - which ones are actually necessary here for my program to run?
Here's the source code and the way I compiled it:
extern printf
global main
section .data
msg: db "Hello World!", 0
section .text
main:
;; puts (msg)
push msg
call printf
add esp, 4
;; return 0
mov eax, 0
ret
nasm main.asm -f elf32 && tcc main.o -o main
Tested on 32bit/ubuntu:16.04
Docker image.
Note: this question is different from this one in that I'm not looking for a tensy Linux ELF, but one that allows me to call dynamic symbols. I believe that due to the nature of dynamic linking, I need some extra sections.
Your belief is mistaken. No section is necessary at runtime, only segments matter.
A runnable dynamically-linked ELF binary will have at least one
PT_LOAD
segment, aPT_INTERP
segment, andPT_DYNAMIC
segment.