Consider the following program targeting Linux x86_64:
inf.s:
.global _start
.text
_start:
jmp _start
Which is basically an infinite loop.
If I link and strip this I get an ELF executable:
$ gcc -nostdlib inf.s
$ ./a.out &
[1] 15862
$ cat /proc/15862/maps
00400000-00401000 r-xp 00000000 fc:00 11404632 a.out
7fffacdb8000-7fffacdd9000 rwxp 00000000 00:00 0 [stack]
7fffacddd000-7fffacdde000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
In the ELF executable the first program header LOAD
contains the map that accounts for the first of the entry in the above mmaps (a.out). (Even if I strip everying but this header and code the same maps are observed.) execve(2)
calls the ELF handler in fs/binfmt_elf.c
which reads the program header and calls mmap on the file.
What I don't understand is where the other three come from (stack, vdso, vsyscall). They are not mentioned in the ELF file, so the Linux kernel must setup these three "anonymous" or "special" maps up by default.
My question is where in the kernel code (or how) does the Linux kernel create these other three maps? Are they inherited across the execve? I can't seem to see where in fs/exec.c
they are created.