ELF headers are included in the process memory because the program asked for them.
The ELF file contains a number of "program headers" which specify how the program is to be loaded. The ELF loader on your computer (typically in the kernel or dynamic linker) will load the program into memory as specified by the program headers (with allowances for extra pieces due to page size limitations).
Therefore, if the program headers include the start of the executable file in any LOAD command, then the ELF header will be loaded into memory. It is definitely possible to create functional ELF files that don't load the ELF headers into the program memory; the ELF loader will usually load the headers into a temporary (scratch) area in order to figure out how to load the program.
Sample program headers from an Android executable (using readelf
):
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00008034 0x00008034 0x00100 0x00100 R 0x4
INTERP 0x000134 0x00008134 0x00008134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /system/bin/linker]
LOAD 0x000000 0x00008000 0x00008000 0x00320 0x00320 R E 0x1000
LOAD 0x000ee8 0x00009ee8 0x00009ee8 0x00118 0x0011c RW 0x1000
DYNAMIC 0x000f08 0x00009f08 0x00009f08 0x000d0 0x000d0 RW 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
EXIDX 0x000318 0x00008318 0x00008318 0x00008 0x00008 R 0x4
GNU_RELRO 0x000ee8 0x00009ee8 0x00009ee8 0x00118 0x00118 RW 0x4
The first LOAD command starts at an offset of 0x0 from the start of the file and extends for 0x320 bytes, so it will include the ELF headers at address 0x8000 (assuming the executable isn't relocated due to ASLR).