SEGMENT_START("text-segment", 0x400000) 代表什么?

What does SEGMENT_START("text-segment", 0x400000) represent?

我正在了解可执行二进制文件的布局。我的最终目标是分析一个特定的可执行文件,寻找可以重构(在其源代码中)以减少编译输出大小的东西。

我一直在使用 https://www.embeddedrelated.com/showarticle/900.php and https://www.geeksforgeeks.org/memory-layout-of-c-program/ 作为初步学习的参考资料。

据我所知,链接描述文件指定了放置已编译二进制文件部分的地址。例如

> ld --verbose | grep text
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)

我认为这意味着编译二进制文件的 text 段从内存地址 0x400000 开始 - 是吗?

那个值 0x400000 代表什么? 我可能没有正确理解某些东西,但 0x400000 肯定不代表物理内存位置,是吗?例如。如果我要 运行 我编译的 a.out 可执行文件的两个实例并行,它们不能 both 同时占用 space 在 0x400000,对吗?

0x4000000 不是 物理地址 在你的内存芯片如何看待它的意义上。从 CPU 的角度来看,这是一个 虚拟地址

您程序的加载器会将几页物理内存映射到 VA 0x400000,并将 text-segment 的内容复制到其中。是的,您的程序的另一个实例可能会占用 text-segment 的相同物理和虚拟内存块,因为文本(代码)是可读和可执行的,但 不可写 。其他段(数据、bss、堆栈、堆)可能具有相同的 VA,但每个段都将映射到它们私有的 protected 物理内存块。

什么是0x400000

I think this means that the text segments of compiled binaries starts at memory address 0x400000 - true?

不,这在官方文档中有很好的解释:https://sourceware.org/binutils/docs/ld/Builtin-Functions.html

SEGMENT_START(segment, default)

Return the base address of the named segment. If an explicit value has already been given for this segment (with a command-line ‘-T’ option) then that value will be returned otherwise the value will be default. At present, the ‘-T’ command-line option can only be used to set the base address for the “text”, “data”, and “bss” sections, but you can use SEGMENT_START with any segment name.

因此,SEGMENT_START 不是设置地址,而是返回它,如果提到的某些 CLI 机制没有确定地设置该值,则 0x4000000 在您的情况下只是默认值在文档中(例如 man ld 中提到的 -Ttext=0x200

物理与虚拟

正如您所说,在用户空间中在物理地址中做事是非常罕见的,并且至少总是需要 sudo 就像 break process separation. Here is an example of userland doing physical address stuff for example: How to access physical addresses from user space in Linux?

因此,当内核loads an ELF binary with the exec syscalls时,所有地址都被解释为虚拟地址。

但是请注意,这只是约定俗成的问题。例如,当我 give my Linux kernel ELF binary for QEMU to load into memory to start simulation,或者当引导加载程序在实际系统中执行此操作时,ELF 地址将被视为物理地址,因为此时没有页面 table 可用。