GNU linker ld —— The Section of an Expression

GNU linker ld (GNU Binutils) version 2.42 —— Linker Scripts:The Section of an Expression

个人笔记,仅供参考!!

地址和符号可以是相对的,也可以是绝对的。段相对符号是可重定位的。如果使用-r链接选项请求可重定位的输出,则进一步的链接操作可能会更改那些与段相关的符号的值。另一方面,一个绝对符号将在以后的任何链接操作中保持相同的值。

链接器表达式中的一些术语(terms)是地址,例如那些相对于段的符号以及返回地址的内置函数,例如 ADDR、LOADADDR、ORIGIN 和 SEGMENT_START。
其他术语(terms)只是数字,或者是返回非地址值的内置函数,例如 LENGTH。

通常情况下,链接脚本中,数字和绝对符号在不同的位置上会被不同对待。在输出段定义之外的表达式中,所有数字都被视为绝对地址,这意味着,如果在表达式中使用一个数字,它将被解释为一个绝对地址。
在输出段定义之内的表达式中,绝对符号被视为数字,而数字被视为相对于当前段的地址。
但如果设置了 LD_FEATURE (“SANE_EXPR”),则绝对符号和数字在任何地方都被视为数字。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
SECTIONS
{
. = 0x100;
__executable_start = 0x100;
.data :
{
. = 0x10;
__data_start = 0x10;
*(.data)
}

}

这个例子中,.__executable_start在前两个赋值中都设置为绝对地址 0x100。
然后,在后两个赋值中,.__data_start都相对于 .data 节设置为 0x10。

对于涉及数字、相对地址和绝对地址的表达式,ld 遵循以下规则来计算:

  • 对绝对地址或数字的一元操作,以及对两个绝对地址或两个数字或一个绝对地址和一个数字之间的二元操作,将操作应用于值。
  • 对相对地址的一元操作,以及在同一段中的两个相对地址之间或相对地址和数字之间的二元操作,将操作应用于地址的偏移部分。
  • 其他二元操作,即在不同段中的两个相对地址之间或相对地址和绝对地址之间的操作,在应用操作之前首先将任何非绝对术语(term)转换为绝对地址。

每个子表达式的结果段如下:

  • 仅涉及数字的操作结果是一个数字。
  • 比较、‘&&’ 和 ‘||’ 的结果也是一个数字。
  • 当LD_FEATURE (“SANE_EXPR”)或在输出段定义内时,对同一段中的两个相对地址或两个绝对地址(经过上述转换)进行其他二进制算术和逻辑运算的结果也是一个数字,否则是一个绝对地址。
  • 对相对地址或一个相对地址加一个数字进行其他操作的结果是与相对操作数位于同一节中的相对地址。
  • 在绝对地址上的其他操作(经过上述转换)的结果是一个绝对地址。

可以使用内置函数 ABSOLUTE 来强制表达式成为绝对地址,否则它可能是相对的。例如,要创建一个绝对符号,其地址设置为输出段 .data 的末尾:

1
2
3
4
SECTIONS
{
.data : { *(.data) _edata = ABSOLUTE(.); }
}

如果没有使用 ABSOLUTE,_edata 将相对于 .data 段。

使用 LOADADDR 也会强制表达式成为绝对地址,因为这个特定的内置函数返回一个绝对地址。

参考连接:

【1】https://sourceware.org/binutils/docs/ld/Expression-Section.html