ZHCUAU3J January 2018 – March 2024
用户可以在已初始化的输出段中创建一个空洞。当用户强制链接器在输出段内的输入段之间留出额外空间时,就会创建空洞。创建此类空洞时,链接器必须为该空洞提供原始数据。
只能在输出段内 创建空洞。输出段之间 可以存在空间,但这种空间不是空洞。若要填充输出段之间的空间,请参阅节 12.5.4.2。
若要在输出段中创建空洞,必须在输出段定义中使用特殊类型的链接器赋值语句。赋值语句会修改 SPC(由 . 表示),修改方法是向其添加、为其分配更大的值或在地址边界上将其对齐。有关赋值语句的运算符、表达式和语法的说明,请参阅节 12.5.9。
以下示例使用了赋值语句在输出段中创建空洞:
SECTIONS
{
outsect:
{
file1.c.obj(.text)
. += 0x0100 /* Create a hole with size 0x0100 */
file2.c.obj(.text)
. = align(16); /* Create a hole to align the SPC */
file3.c.obj(.text)
}
}
输出段 outsect 的构建方式如下:
在一个段内分配给 . 符号的所有值指代该段内的相对地址。链接器处理 . 符号的赋值语句时会认为该段从地址 0 开始(即使已指定绑定地址也是如此)。请考虑示例中的赋值语句 .= align(16)。该语句实际上会将 file3.c.obj .text 段与 outsect 内的 16 字节边界上的起点对齐。如果 outsect 最终分配至未对齐的地址起点,则 file3.c.obj .text 段也不会对齐。
. 符号指段的当前运行地址,而不是当前加载地址。
减小 . 符号的表达式是非法的。例如,在 . 符号的赋值语句中使用 -= 运算符是无效的。. 符号的赋值语句中最常用的运算符是 += 和 align。
如果输出段包含某种类型的所有输入段(例如 .text),则可使用以下语句在输出段的开头或结尾创建一个空洞。
.text: { .+= 0x0100; } /* Hole at the beginning */
.data: { *(.data)
. += 0x0100; } /* Hole at the end */
在输出段中创建空洞的另一种方法是,将未初始化的段与已初始化的段组合形成单个输出段。在这种情况下,链接器会将未初始化的段视为空洞并为其提供数据。以下示例说明了此方法:
SECTIONS
{
outsect:
{
file1.c.obj(.text)
file1.c.obj(.bss) /* This becomes a hole */
}
}
由于 .text 段有原始数据,整个 outsect 也必须包含原始数据。因此,未初始化的 .bss 段将成为空洞。
未初始化的段只有在与已初始化的段组合时才会成为空洞。如果将多个未初始化的段链接在一起,则生成的输出段也未经初始化。