我写了一个小程序来添加到整数并使用“readelf -a executable_name”它在elf标题中显示了入口点地址:
Entry point address: 0x8048330
即使在加载程序将内存加载到内存之前,我的可执行文件如何预先知道此地址? elf_format.pdf表示该成员提供系统首先转移控制的虚拟地址,从而启动该过程。任何人都可以解释这句话的含义是什么,这里虚拟地址的含义是什么?
另请注意,可执行文件的值为0x8048330,作为入口点地址。只是为了交叉检查,我编译了另一个程序,为此,入口点地址保持相同的值0x8048330(两种情况下.text部分的偏移量为0x330)。
答案 0 :(得分:13)
输入地址由链接编辑器在创建时设置 可执行文件。加载程序将程序文件映射到指定的地址 在将控制转移到入口地址之前,通过ELF标头。
要使用具体示例,请考虑以下事项:
% file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, \
for GNU/Linux 2.6.15, not stripped
% readelf -e a.out
... snip ...
Elf file type is EXEC (Executable file)
Entry point 0x8048170
There are 6 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x7cca6 0x7cca6 R E 0x1000
LOAD 0x07cf98 0x080c5f98 0x080c5f98 0x00788 0x022fc RW 0x1000
... snip ...
第一个程序头指定文件的内容 文件偏移量0应映射到虚拟地址0x08048000。该 该段的文件和内存大小为0x7cca6字节。这个 segment将以可读和可执行的方式映射,但不可写 (它包含程序的代码)。
ELF头中指定的入口点地址是0x8048170,其中 落在包含程序代码的区域内。
John Levine的书“Linkers and Loaders”是一个很好的资源,可以就链接编辑和加载器相关事宜进行咨询。
答案 1 :(得分:11)
您看到的入口点0x8048330
是虚拟内存地址(相反,是物理内存)。
这意味着您的主管不必知道要映射的物理地址。 (用装载机加载后)
它甚至无法访问物理内存。
对于程序的过程,您的.text部分始终从0x8048330
开始,您的系统(操作系统和硬件)将在运行时将其(虚拟地址)映射到物理内存。
映射和管理物理内存是很多事情,您可以在Google上查看更多信息。
我不确定哪一部分让你感到困惑,所以我会试着全部覆盖它们:
是的,可能有另一个具有相同入口点0x8048330
的程序。因为此地址是虚拟的,所以当您尝试同时运行程序时,程序将在运行时映射到不同的物理内存。
0x8048330
吗? 嗯,Linux主管从0x8048000
开始,但.text部分的偏移与其他部分的长度有关。所以不,它可以是0x8048034
或其他任何东西。
0x8048000
开始?我认为这是历史的事情,Linux的设计者选择这个是出于某种未知甚至随机的原因。您可以参考this thread查看该领域的内容。
答案 2 :(得分:4)
关于虚拟地址问题:
普通用户态应用程序使用虚拟地址,这意味着它们不能直接访问内存空间。操作系统(借助某些微处理器的特殊功能)将此虚拟地址映射到物理地址。
这样,操作系统可以防止应用程序读/写到其他应用程序内存或操作系统保留的内存中。此外,这允许以透明的方式为应用程序分页内存(使用硬盘作为内存)。