为什么我的 x64 进程基地址不是从 0x400000 开始的?
why my x64 process base address not start from 0x400000?
我从这个 link Why is address 0x400000 chosen as a start of text segment in x86_64 ABI? 中得知 64 位 Linux 进程起始地址默认应该是 0x400000,但是在我的 Ubuntu 上,我只找到了我的bash
进程从一个非常高的基地址 (0x55971cea6000) 开始。
有谁知道为什么?动态 linker 如何选择 64 位进程的起始地址?
$ uname -r
5.15.0-25-generic
$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"
...
$ file /usr/bin/bash
/usr/bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=33a5554034feb2af38e8c75872058883b2988bc5, for GNU/Linux 3.2.0, stripped
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
$ cat maps
55971ce77000-55971cea6000 r--p 00000000 08:02 153 /usr/bin/bash
55971cea6000-55971cf85000 r-xp 0002f000 08:02 153 /usr/bin/bash
55971cf85000-55971cfbf000 r--p 0010e000 08:02 153 /usr/bin/bash
55971cfc0000-55971cfc4000 r--p 00148000 08:02 153 /usr/bin/bash
55971cfc4000-55971cfcd000 rw-p 0014c000 08:02 153 /usr/bin/bash
55971cfcd000-55971cfd8000 rw-p 00000000 00:00 0
...
$ readelf -h /usr/bin/bash
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: 0x32eb0
Start of program headers: 64 (bytes into file)
Start of section headers: 1394600 (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: 30
Section header string table index: 29
I learned from this link Why is address 0x400000 chosen as a start of text segment in x86_64
该地址用于可执行文件(ELF
类型 ET_EXEC
)。
I only found my bash process starts from a very high base address (0x55971cea6000). Any one knows why?
因为您的 bash
是(较新的)position-independent 可执行文件(ELF
类型 ET_DYN
)。它的行为很像共享库,并在 运行 时间重新定位到随机地址。
您找到的 0x55971cea6000
地址会因一次执行而异。相比之下,ET_EXEC
可执行文件只能 运行 在其“链接地址”加载时正确(通常为 0x400000
)。
how does dynamic linker choose the start address for a 64-bit process?
动态链接器不选择可执行文件的起始地址 -- 内核会选择(当动态链接器启动 运行ning 时,可执行文件已经 mmap
ed内存)。
内核查看 ELF
头中的 .e_type
和第一个程序头的 .p_vaddr
字段,然后从那里开始。 IFF .e_type == ET_EXEC
,然后内核将可执行段映射到它们的 .p_vaddr
地址。对于 ET_DYN
,如果 ASLR 有效,内核会在随机地址执行 mmap
s。
我从这个 link Why is address 0x400000 chosen as a start of text segment in x86_64 ABI? 中得知 64 位 Linux 进程起始地址默认应该是 0x400000,但是在我的 Ubuntu 上,我只找到了我的bash
进程从一个非常高的基地址 (0x55971cea6000) 开始。
有谁知道为什么?动态 linker 如何选择 64 位进程的起始地址?
$ uname -r
5.15.0-25-generic
$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"
...
$ file /usr/bin/bash
/usr/bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=33a5554034feb2af38e8c75872058883b2988bc5, for GNU/Linux 3.2.0, stripped
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
$ cat maps
55971ce77000-55971cea6000 r--p 00000000 08:02 153 /usr/bin/bash
55971cea6000-55971cf85000 r-xp 0002f000 08:02 153 /usr/bin/bash
55971cf85000-55971cfbf000 r--p 0010e000 08:02 153 /usr/bin/bash
55971cfc0000-55971cfc4000 r--p 00148000 08:02 153 /usr/bin/bash
55971cfc4000-55971cfcd000 rw-p 0014c000 08:02 153 /usr/bin/bash
55971cfcd000-55971cfd8000 rw-p 00000000 00:00 0
...
$ readelf -h /usr/bin/bash
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: 0x32eb0
Start of program headers: 64 (bytes into file)
Start of section headers: 1394600 (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: 30
Section header string table index: 29
I learned from this link Why is address 0x400000 chosen as a start of text segment in x86_64
该地址用于可执行文件(ELF
类型 ET_EXEC
)。
I only found my bash process starts from a very high base address (0x55971cea6000). Any one knows why?
因为您的 bash
是(较新的)position-independent 可执行文件(ELF
类型 ET_DYN
)。它的行为很像共享库,并在 运行 时间重新定位到随机地址。
您找到的 0x55971cea6000
地址会因一次执行而异。相比之下,ET_EXEC
可执行文件只能 运行 在其“链接地址”加载时正确(通常为 0x400000
)。
how does dynamic linker choose the start address for a 64-bit process?
动态链接器不选择可执行文件的起始地址 -- 内核会选择(当动态链接器启动 运行ning 时,可执行文件已经 mmap
ed内存)。
内核查看 ELF
头中的 .e_type
和第一个程序头的 .p_vaddr
字段,然后从那里开始。 IFF .e_type == ET_EXEC
,然后内核将可执行段映射到它们的 .p_vaddr
地址。对于 ET_DYN
,如果 ASLR 有效,内核会在随机地址执行 mmap
s。