直到最近我还认为部分名称通常必须以点
.
开头。然而,在研究我的 bare-metal-C-IDE 的示例链接器文件时,我注意到似乎有一个例外:COMMON
部分。
.text :
{
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > ROM
.bss (NOLOAD):
{
*(.bss*)
*(COMMON)
} > RAM
这使我得出结论,以
.
开头的部分名称似乎只是一个 约定 而不是 要求 。
COMMON
例外?.bss
输出部分中实际上包含非 .bss
部分。 .text
部分也是如此。我的 .text
输出部分包含大量非 .text
部分。为什么为它们提供自己的输出部分并不常见?这样不是更符合逻辑吗?这背后有什么真正的原因吗?或者事情就是这样吗?
正如 @cremno 在评论中指出的,之所以使用点作为链接部分的前缀,是因为 ELF(可执行和可链接格式)规范(存档)为系统保留它们。在第一本书中,第 14 页。 16(第 30 页):
带点 (.) 前缀的节名称是为系统保留的,尽管应用程序可以使用这些节(如果它们的现有含义令人满意)。应用程序可以使用不带前缀的名称,以避免与系统部分发生冲突。目标文件格式允许定义不在上面列表中的部分。一个目标文件可能有多个同名部分。
该规范还在第一册第 15-16 页(第 29-30 页)中定义了标准部分的名称和含义 -
.text
、.rodata
和 .data
等。
COMMON
例外?因为开发人员想要这样做,并且规范允许他们做出例外。在这种情况下,做出这样选择的可能是 Fortran 编译器的开发人员。如上所述,如果标准部分适合应用程序的需要,应用程序“可以”使用标准部分。显然这些开发人员认为需要一个非标准的部分名称。 为什么输出节通常与输入节同名?为什么不为每个输入部分提供单独的输出部分?
输入节可能被放置到不同名称的输出节中的原因是因为给定的(引导)加载程序或应用程序不知道所述节(输入或输出)的存在。也许您有非标准部分,例如示例中的
.ctor
和
.dtor
部分,并且目标系统仅与 .text
、.rodata
、.bss
和 .data
部分加载/交互。或者,也许您正在编写一个代码生成器,并且包含已编译代码片段的 .text
段的某些部分需要放置在 .rodata
段中以进行读取访问。这背后有什么真正的原因吗?还是事情就是这样?