Linker U段开始(“文本段”,0x400000)代表什么?

Linker U段开始(“文本段”,0x400000)代表什么?,linker,binaryfiles,ld,binutils,memory-layout,Linker,Binaryfiles,Ld,Binutils,Memory Layout,我正在学习可执行二进制文件的布局。我的最终目标是分析特定可执行文件中可以重构(在其源代码中)以减少编译输出大小的内容 我一直在使用和作为这个初步学习的参考 据我所知,链接器脚本指定已编译二进制文件的节所在的地址。例如 > ld --verbose | grep text PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x4

我正在学习可执行二进制文件的布局。我的最终目标是分析特定可执行文件中可以重构(在其源代码中)以减少编译输出大小的内容

我一直在使用和作为这个初步学习的参考

据我所知,链接器脚本指定已编译二进制文件的节所在的地址。例如

> 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.*)
我认为这意味着编译后的二进制文件的
文本
段开始于内存地址
0x400000
-真的

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

0x4000000不是内存芯片所看到的物理地址。从CPU的角度来看,这是一个虚拟地址


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

什么是0x400000

我认为这意味着编译后的二进制文件的文本段从内存地址0x400000开始-真的

不,这在官方文件中有很好的解释:

段\起始(段,默认)

返回指定段的基址。如果已经为该段指定了显式值(使用命令行'-T'选项),则将返回该值,否则该值将为默认值。目前,'-T'命令行选项只能用于设置“文本”、“数据”和“bss”部分的基址,但您可以使用任何段名称开头的段

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

物理与虚拟的对比

正如您所说的,在userland中使用物理地址进行操作是非常少见的,并且至少总是需要
sudo
。下面是userland执行物理地址操作的示例,例如:

因此,当内核运行时,所有地址都被解释为虚拟地址

但请注意,这只是一个惯例问题。例如,当I或引导加载程序在实际系统中执行此操作时,ELF地址将被视为物理地址,因为此时没有可用的页表