ELF 程序头和虚拟地址
ELF Program Headers and Virtual Address
我了解 ELF 及其程序头。当我使用 readelf
读取文件类型为 DYN 的 ELF 时。我在程序头中看到虚拟地址值实际上来自内核虚拟地址 space.
Elf file type is DYN (Shared object file)
Entry point 0x1060
There are 13 program headers, starting at offset 64
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
0x0000000000000600 0x0000000000000600 R 0x1000
LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000
0x00000000000001f5 0x00000000000001f5 R E 0x1000
LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000
0x0000000000000168 0x0000000000000168 R 0x1000
LOAD 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
0x0000000000000258 0x0000000000000260 RW 0x1000
DYNAMIC 0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000358 0x0000000000000358 0x0000000000000358
0x0000000000000044 0x0000000000000044 R 0x4
GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000020 0x0000000000000020 R 0x8
GNU_EH_FRAME 0x0000000000002018 0x0000000000002018 0x0000000000002018
0x0000000000000044 0x0000000000000044 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
0x0000000000000248 0x0000000000000248 R 0x1
我能够推断出加载二进制文件时实际的 VirtAddr 应该是 = 基地址 + VirtAddr。但是我无法找出加载程序如何计算基址值?
此外,我知道 .text 和 .data 是用于加载二进制文件的两个 PT_LOAD 段。但是我在示例中看到了 4 PT_LOAD 个程序头。两个 PT_LOAD 程序头有什么用?
这是不是具有设置基地址的程序。相反,它是一个 position-independent 可执行文件,可以链接到内存中的 任何 地址,从而启用地址 space 布局随机化,即 ALSR。
它与普通共享库的区别在于它有程序解释器集,一般共享库没有...
这里的最低虚拟内存地址正好是0x0000000000000040
,对应文件偏移量0x0000000000000040
.
I see virtual address value in Program Headers is actually from kernel Virtual address space.
不,你没看到。 None 输出中的地址与内核有关。
您正在查看的是一个Position Independent executable,它可以加载到内存中任何地方。
I'm not able to find out how loader calculates the Base Address Value?
加载器不加载主可执行文件(内核加载),也不决定加载地址。
鉴于文件类型是ET_DYN
,内核执行相当于
mmap(0, ...)
(没有 MAP_FIXED
标志),并选择一个合适的虚拟地址,然后将其传送给 aux
向量中的加载程序。
But I see 4 PT_LOAD program headers in my example. What are two PT_LOAD program headers used for?
参见 答案。
我了解 ELF 及其程序头。当我使用 readelf
读取文件类型为 DYN 的 ELF 时。我在程序头中看到虚拟地址值实际上来自内核虚拟地址 space.
Elf file type is DYN (Shared object file)
Entry point 0x1060
There are 13 program headers, starting at offset 64
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
0x0000000000000600 0x0000000000000600 R 0x1000
LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000
0x00000000000001f5 0x00000000000001f5 R E 0x1000
LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000
0x0000000000000168 0x0000000000000168 R 0x1000
LOAD 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
0x0000000000000258 0x0000000000000260 RW 0x1000
DYNAMIC 0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000358 0x0000000000000358 0x0000000000000358
0x0000000000000044 0x0000000000000044 R 0x4
GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338
0x0000000000000020 0x0000000000000020 R 0x8
GNU_EH_FRAME 0x0000000000002018 0x0000000000002018 0x0000000000002018
0x0000000000000044 0x0000000000000044 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
0x0000000000000248 0x0000000000000248 R 0x1
我能够推断出加载二进制文件时实际的 VirtAddr 应该是 = 基地址 + VirtAddr。但是我无法找出加载程序如何计算基址值?
此外,我知道 .text 和 .data 是用于加载二进制文件的两个 PT_LOAD 段。但是我在示例中看到了 4 PT_LOAD 个程序头。两个 PT_LOAD 程序头有什么用?
这是不是具有设置基地址的程序。相反,它是一个 position-independent 可执行文件,可以链接到内存中的 任何 地址,从而启用地址 space 布局随机化,即 ALSR。
它与普通共享库的区别在于它有程序解释器集,一般共享库没有...
这里的最低虚拟内存地址正好是0x0000000000000040
,对应文件偏移量0x0000000000000040
.
I see virtual address value in Program Headers is actually from kernel Virtual address space.
不,你没看到。 None 输出中的地址与内核有关。
您正在查看的是一个Position Independent executable,它可以加载到内存中任何地方。
I'm not able to find out how loader calculates the Base Address Value?
加载器不加载主可执行文件(内核加载),也不决定加载地址。
鉴于文件类型是ET_DYN
,内核执行相当于
mmap(0, ...)
(没有 MAP_FIXED
标志),并选择一个合适的虚拟地址,然后将其传送给 aux
向量中的加载程序。
But I see 4 PT_LOAD program headers in my example. What are two PT_LOAD program headers used for?
参见