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

时间:2019-03-20 21:21:10

标签: linker binaryfiles ld binutils memory-layout

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

我一直使用https://www.embeddedrelated.com/showarticle/900.phphttps://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可执行文件的两个实例,那么它们不能同时在0x400000上占据空间,对吗?

2 个答案:

答案 0 :(得分:4)

从内存芯片的角度来看,

0x4000000不是物理地址。从CPU的角度来看,这是一个虚拟地址

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

答案 1 :(得分:0)

什么是0x400000

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

不,这在https://sourceware.org/binutils/docs/ld/Builtin-Functions.html

的官方文档中有很好的解释。

SEGMENT_START(细分,默认)

返回命名段的基地址。如果已经为此段指定了明确的值(使用命令行“ -T”选项),则将返回该值,否则该值为默认值。目前,“-T”命令行选项只能用于设置“文本”,“数据”和“ bss”部分的基址,但是您可以将SEGMENT_START与任何段名称一起使用。

因此,SEGMENT_START不是设置地址,而是返回它,如果您的情况下0x4000000并非默认值,则默认为-Ttext=0x200文档(例如man ld中提到的sudo

物理与虚拟

正如您所说的,在物理地址中执行操作在用户区中很少见,并且至少总是像break process separation一样需要#ifdef FOUND_THIRD_LIBRARY...。这是一个Userland进行物理地址处理的示例,例如: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地址将被视为物理地址。