Just a quick note in case you would not be aware of this:
$ cat tiny.c
#include <unistd.h>
void _start() {
_exit(42);
}
on x86-64, here is what I get (you need a static libc: libc.a):
$ gcc -static -ffreestanding -nostartfiles -s -o tiny tiny.c
$ ./tiny || echo $?
42
Pay attention that:
$ file tiny
tiny: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=5557e6655b77976b7c248711af6f508d931fc3af, stripped
but only:
$ objdump -x tiny
tiny: file format elf64-x86-64
tiny
architecture: i386:x86-64, flags 0x00000102:
EXEC_P, D_PAGED
start address 0x0000000000400180
Program Header:
LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
filesz 0x0000000000000240 memsz 0x0000000000000240 flags r-x
LOAD off 0x0000000000001000 vaddr 0x0000000000601000 paddr 0x0000000000601000 align 2**21
filesz 0x0000000000000018 memsz 0x0000000000000018 flags rw-
NOTE off 0x0000000000000158 vaddr 0x0000000000400158 paddr 0x0000000000400158 align 2**2
filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
TLS off 0x0000000000001000 vaddr 0x0000000000601000 paddr 0x0000000000601000 align 2**2
filesz 0x0000000000000000 memsz 0x0000000000000004 flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 0000000000400158 0000000000400158 00000158 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000006a 0000000000400180 0000000000400180 00000180 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .eh_frame 00000050 00000000004001f0 00000000004001f0 000001f0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .tbss 00000004 0000000000601000 0000000000601000 00001000 2**2
ALLOC, THREAD_LOCAL
4 .got.plt 00000018 0000000000601000 0000000000601000 00001000 2**3
CONTENTS, ALLOC, LOAD, DATA
5 .comment 0000002c 0000000000000000 0000000000000000 00001018 2**0
CONTENTS, READONLY
SYMBOL TABLE:
no symbols