So executables are the elf image file type, that their purpose is to actually be executed. The contain a full program to be executed (although they may require shared libraries to be linked in).
Since executables are meant to be ran, and in order to be executed you just need a Program Header Table, not a Section Header Table. Program Header Tables are used when an ELF is being loaded (so it's being executed), and a Section Header Table is used when a binary is being linked. If the executable is never linked, it doesn't need the Section Header Table.
Here we see some of the ELF header data for an executable, that we've seen documented in detail earlier:
$ readelf -a try
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1080
Start of program headers: 64 (bytes into file)
Start of section headers: 14016 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000000318 00000318
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.gnu.pr[...] NOTE 0000000000000338 00000338
0000000000000030 0000000000000000 A 0 0 8
[ 3] .note.gnu.bu[...] NOTE 0000000000000368 00000368
0000000000000024 0000000000000000 A 0 0 4
[ 4] .note.ABI-tag NOTE 000000000000038c 0000038c
0000000000000020 0000000000000000 A 0 0 4
[ 5] .gnu.hash GNU_HASH 00000000000003b0 000003b0
0000000000000024 0000000000000000 A 6 0 8
[ 6] .dynsym DYNSYM 00000000000003d8 000003d8
00000000000000c0 0000000000000018 A 7 1 8
[ 7] .dynstr STRTAB 0000000000000498 00000498
0000000000000092 0000000000000000 A 0 0 1
[ 8] .gnu.version VERSYM 000000000000052a 0000052a
0000000000000010 0000000000000002 A 6 0 2
[ 9] .gnu.version_r VERNEED 0000000000000540 00000540
0000000000000030 0000000000000000 A 7 1 8
[10] .rela.dyn RELA 0000000000000570 00000570
00000000000000c0 0000000000000018 A 6 0 8
[11] .rela.plt RELA 0000000000000630 00000630
0000000000000030 0000000000000018 AI 6 24 8
[12] .init PROGBITS 0000000000001000 00001000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000001020 00001020
0000000000000030 0000000000000010 AX 0 0 16
[14] .plt.got PROGBITS 0000000000001050 00001050
0000000000000010 0000000000000010 AX 0 0 16
[15] .plt.sec PROGBITS 0000000000001060 00001060
0000000000000020 0000000000000010 AX 0 0 16
[16] .text PROGBITS 0000000000001080 00001080
0000000000000118 0000000000000000 AX 0 0 16
[17] .fini PROGBITS 0000000000001198 00001198
000000000000000d 0000000000000000 AX 0 0 4
[18] .rodata PROGBITS 0000000000002000 00002000
0000000000000009 0000000000000000 A 0 0 4
[19] .eh_frame_hdr PROGBITS 000000000000200c 0000200c
0000000000000034 0000000000000000 A 0 0 4
[20] .eh_frame PROGBITS 0000000000002040 00002040
00000000000000ac 0000000000000000 A 0 0 8
[21] .init_array INIT_ARRAY 0000000000003db0 00002db0
0000000000000008 0000000000000008 WA 0 0 8
[22] .fini_array FINI_ARRAY 0000000000003db8 00002db8
0000000000000008 0000000000000008 WA 0 0 8
[23] .dynamic DYNAMIC 0000000000003dc0 00002dc0
00000000000001f0 0000000000000010 WA 7 0 8
[24] .got PROGBITS 0000000000003fb0 00002fb0
0000000000000050 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000004000 00003000
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000004010 00003010
0000000000000008 0000000000000000 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 00003010
000000000000002b 0000000000000001 MS 0 0 1
[28] .symtab SYMTAB 0000000000000000 00003040
0000000000000378 0000000000000018 29 18 8
[29] .strtab STRTAB 0000000000000000 000033b8
00000000000001ea 0000000000000000 0 0 1
[30] .shstrtab STRTAB 0000000000000000 000035a2
000000000000011a 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000002d8 0x00000000000002d8 R 0x8
INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000660 0x0000000000000660 R 0x1000
LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000
0x00000000000001a5 0x00000000000001a5 R E 0x1000
LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000
0x00000000000000ec 0x00000000000000ec R 0x1000
LOAD 0x0000000000002db0 0x0000000000003db0 0x0000000000003db0
0x0000000000000260 0x0000000000000268 RW 0x1000
DYNAMIC 0x0000000000002dc0 0x0000000000003dc0 0x0000000000003dc0
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000030 0x0000000000000030 R 0x8
NOTE 0x0000000000000368 0x0000000000000368 0x0000000000000368
0x0000000000000044 0x0000000000000044 R 0x4
GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000030 0x0000000000000030 R 0x8
GNU_EH_FRAME 0x000000000000200c 0x000000000000200c 0x000000000000200c
0x0000000000000034 0x0000000000000034 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000002db0 0x0000000000003db0 0x0000000000003db0
0x0000000000000250 0x0000000000000250 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
03 .init .plt .plt.got .plt.sec .text .fini
04 .rodata .eh_frame_hdr .eh_frame
05 .init_array .fini_array .dynamic .got .data .bss
06 .dynamic
07 .note.gnu.property
08 .note.gnu.build-id .note.ABI-tag
09 .note.gnu.property
10 .eh_frame_hdr
11
12 .init_array .fini_array .dynamic .got
Dynamic section at offset 0x2dc0 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x1198
0x0000000000000019 (INIT_ARRAY) 0x3db0
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x3db8
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x3b0
0x0000000000000005 (STRTAB) 0x498
0x0000000000000006 (SYMTAB) 0x3d8
0x000000000000000a (STRSZ) 146 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x3fb0
0x0000000000000002 (PLTRELSZ) 48 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x630
0x0000000000000007 (RELA) 0x570
0x0000000000000008 (RELASZ) 192 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0x540
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x52a
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0
Relocation section '.rela.dyn' at offset 0x570 contains 8 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003db0 000000000008 R_X86_64_RELATIVE 1160
000000003db8 000000000008 R_X86_64_RELATIVE 1120
000000004008 000000000008 R_X86_64_RELATIVE 4008
000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000003fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0
000000003fe8 000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0 000600000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0
000000003ff8 000700000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x630 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003fc8 000300000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000003fd0 000500000007 R_X86_64_JUMP_SLO 0000000000000000 gets@GLIBC_2.2.5 + 0
No processor specific unwind information to decode
Symbol table '.dynsym' contains 8 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (3)
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND gets@GLIBC_2.2.5 (3)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
7: 0000000000000000 0 FUNC WEAK DEFAULT UND [...]@GLIBC_2.2.5 (3)
Symbol table '.symtab' contains 37 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS Scrt1.o
2: 000000000000038c 32 OBJECT LOCAL DEFAULT 4 __abi_tag
3: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
4: 00000000000010b0 0 FUNC LOCAL DEFAULT 16 deregister_tm_clones
5: 00000000000010e0 0 FUNC LOCAL DEFAULT 16 register_tm_clones
6: 0000000000001120 0 FUNC LOCAL DEFAULT 16 __do_global_dtors_aux
7: 0000000000004010 1 OBJECT LOCAL DEFAULT 26 completed.0
8: 0000000000003db8 0 OBJECT LOCAL DEFAULT 22 __do_global_dtor[...]
9: 0000000000001160 0 FUNC LOCAL DEFAULT 16 frame_dummy
10: 0000000000003db0 0 OBJECT LOCAL DEFAULT 21 __frame_dummy_in[...]
11: 0000000000000000 0 FILE LOCAL DEFAULT ABS try.c
12: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
13: 00000000000020e8 0 OBJECT LOCAL DEFAULT 20 __FRAME_END__
14: 0000000000000000 0 FILE LOCAL DEFAULT ABS
15: 0000000000003dc0 0 OBJECT LOCAL DEFAULT 23 _DYNAMIC
16: 000000000000200c 0 NOTYPE LOCAL DEFAULT 19 __GNU_EH_FRAME_HDR
17: 0000000000003fb0 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_mai[...]
19: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
20: 0000000000004000 0 NOTYPE WEAK DEFAULT 25 data_start
21: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5
22: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 25 _edata
23: 0000000000001198 0 FUNC GLOBAL HIDDEN 17 _fini
24: 0000000000004000 0 NOTYPE GLOBAL DEFAULT 25 __data_start
25: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
26: 0000000000004008 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
27: 0000000000002000 4 OBJECT GLOBAL DEFAULT 18 _IO_stdin_used
28: 0000000000000000 0 FUNC GLOBAL DEFAULT UND gets@GLIBC_2.2.5
29: 0000000000004018 0 NOTYPE GLOBAL DEFAULT 26 _end
30: 0000000000001080 38 FUNC GLOBAL DEFAULT 16 _start
31: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
32: 0000000000001169 47 FUNC GLOBAL DEFAULT 16 main
33: 0000000000004010 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
34: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
35: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@G[...]
36: 0000000000001000 0 FUNC GLOBAL HIDDEN 12 _init
Histogram for `.gnu.hash' bucket list length (total of 2 buckets):
Length Number % of total Coverage
0 1 ( 50.0%)
1 1 ( 50.0%) 100.0%
Version symbols section '.gnu.version' contains 8 entries:
Addr: 0x000000000000052a Offset: 0x00052a Link: 6 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.34) 1 (*global*) 3 (GLIBC_2.2.5)
004: 1 (*global*) 3 (GLIBC_2.2.5) 1 (*global*) 3 (GLIBC_2.2.5)
Version needs section '.gnu.version_r' contains 1 entry:
Addr: 0x0000000000000540 Offset: 0x000540 Link: 7 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 2
0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3
0x0020: Name: GLIBC_2.34 Flags: none Version: 2
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 feature: IBT, SHSTK
x86 ISA needed: x86-64-baseline
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 4cc4b2f91c32c41ca307258248646a50bdbdc43e
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.2.0
Now, looking at the type of a ELF, we see it's type is DYN
not EXEC
. This is because, this binary was compiled with PIE
. In order to acheive the address randomization, it's type is considered to be DYN
, so it can rebase the code. Like I mentioned in shared_libraries document, the line bewteen executable and shared library can be blurred a little.:
$ readelf --file-header try
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1080
Start of program headers: 64 (bytes into file)
Start of section headers: 14016 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30