为什么我的可执行文件的入口地址是0x8048330?(0x330是.text段的偏移量)

27

我写了一个小程序来相加两个整数,在使用readelf -a 可执行文件名命令时,它显示 elf header 中的入口点地址为:

Entry point address: 0x8048330
我的可执行文件如何在加载到内存之前就知道这个地址呢?elf_format.pdf中说,这个成员提供了系统首先传输控制权的虚拟地址,从而启动进程。请问有人能解释一下这个语句的意思以及这里虚拟地址的含义是什么吗?
另外,请告诉我,可执行文件从哪里获取了0x8048330作为入口点地址的值。仅供交叉检查,我编译了另一个程序,对于这个程序,入口点地址仍然是相同的值0x8048330(两种情况下.text段的偏移量都为0x330)。

1
如果你感兴趣的话,可以查阅维基百科上有关虚拟地址、虚拟地址转换或是虚拟内存等方面的内容。但是,除非你正在开发自己的操作系统并需要这些知识,否则你不需要了解这些概念,只需将“虚拟”一词忽略即可。此外,还有一些工具可以帮助你详细了解可执行文件,可以尝试使用objdump。 - Alexey Frunze
它适用于“EXEC(可执行文件)”类型的文件,但是现在gcc生成“DYN(位置无关可执行文件)”。使用“-no-pic”可以重现此问题。 - tripulse
3个回答

17

针对第一个问题:

你看到的入口点0x8048330是一个虚拟内存地址(相反,是物理内存)。 这意味着你的执行文件不需要知道要映射到哪个物理地址(在加载器加载后)。 它甚至没有访问物理内存的权限。 对于你程序的进程来说,你的`.text`部分总是从0x8048330开始,你的系统(操作系统和硬件)将在运行时将其(虚拟地址)映射到物理内存。

映射和管理物理内存涉及许多事情,你可以在Google上查阅更多信息。

针对第二个问题:

我不确定哪个部分让你感到困惑,所以我会尝试解决所有问题:

  • 是否可能有多个程序具有相同的入口点?

是的,可能有另一个程序具有相同的入口点0x8048330,因为这个地址是虚拟的,当你尝试同时运行它们时,这些程序将被映射到不同的物理内存。

  • 入口点是否总是0x8048330

嗯,Linux执行文件从0x8048000开始,但`.text`部分的偏移量与其他部分的长度有关。所以不,它可以是0x8048034或任何其他值。

  • 为什么它总是从0x8048000开始?

我认为这是历史原因,Linux的设计者基于某些未知甚至随机的原因选择了这个地址。你可以参考这个线程来了解该区域下方的内容。


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字节。该段将被映射为可读和可执行但不可写(它包含程序的代码)。

ELF头中指定的入口点地址为0x8048170,位于包含程序代码的区域内。

约翰·莱文(John Levine)的书籍“链接器和加载器”是一个很好的资源,可以在有关链接器和加载器的问题上进行咨询。


4
关于虚拟地址问题:
普通用户空间应用程序使用的是虚拟地址,这意味着它们不直接访问内存空间。操作系统(借助一些微处理器的特殊功能)将这些虚拟地址映射到物理地址。
这样,操作系统防止应用程序读取/写入其他应用程序或操作系统保留的内存。同时,这也允许内存分页(使用硬盘作为内存),对应用程序而言是透明的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接