Linux64/x86_64 机器中进程的虚拟地址

Virtual Address of process in Linux64/x86_64 machine

我有两个与进程地址映射相关的问题;

  1. 我知道在32位的Linux机器上,一个进程的虚拟地址分为两部分,3GB给Userspace,1GB给Krnel。 x86_64/Linux64机也是一样吗?
  2. linux 可执行文件的 objdump 显示 _init 大约从地址 0x400000 开始。为什么exe地址从0x400000左右开始?
bash-4.2$ objdump -S a.out
       a.out:     file format elf64-x86-64
       Disassembly of section .init:
       0000000000400390 <_init>:
       400390:       48 83 ec 08             sub    [=11=]x8,%rsp

下面显示了相同 a.out 的 pmap 输出。这里的映射也从 0000000000400000(即 4MB)开始。那么4MB之前的虚拟内存在哪里?

bash-4.2$ pmap 95297
95297:   ./a.out
0000000000400000      4K r-x-- a.out
0000000000600000      4K r---- a.out
0000000000601000      4K rw--- a.out
00007fdfd0f37000   1800K r-x-- libc-2.17.so
00007fdfd10f9000   2048K ----- libc-2.17.so
00007fdfd12f9000     16K r---- libc-2.17.so
00007fdfd12fd000      8K rw--- libc-2.17.so
00007fdfd12ff000     20K rw---   [ anon ]
00007fdfd1304000    136K r-x-- ld-2.17.so
00007fdfd1506000     12K rw---   [ anon ]
00007fdfd1524000      4K rw---   [ anon ]
00007fdfd1525000      4K r---- ld-2.17.so
00007fdfd1526000      4K rw--- ld-2.17.so
00007fdfd1527000      4K rw---   [ anon ]
00007fff09042000    132K rw---   [ stack ]
00007fff091c3000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total             4212K

在x86_64上,虚拟地址space是48位(只有64位地址,17位全0或全1有效),而在linux上被分成两半——用户 128TB,内核 128TB。

在那 128TB 的用户 space 中,堆栈被放置在随机选择的高地址(因此通常以 00007fff 开头)和低地址的可执行文件。然后共享库通常加载到堆栈下方的某个位置(也有些随机)选择的精确地址是随机的,以使其更难利用安全漏洞。