链接程序和库指南

段声明

段声明可在输出文件中创建新段,或者更改现有段的属性值。现有段可以是指先前定义的段,也可以是随后即将介绍的四个内置段之一。

段声明的语法如下:

        segment_name = {segment_attribute_value}*;

对于每个 segment_name,都可以按任意顺序指定任何数量的 segment_attribute_values,但每个值都要由空格进行分隔。每个段属性只能有一个属性值。下表列出了段属性及其有效值。

表 9–1 Mapfile 段属性

属性 

值 

segment_type

LOAD | NOTE | STACK

segment_flags

? [E] [N] [O] [R] [W] [X]

virtual_address

Vnumber

physical_address

Pnumber

length

Lnumber

rounding

Rnumber

alignment

Anumber

有四个内置段,其缺省属性值如下所示:

缺省情况下,禁用 bss 段。任何类型为 SHT_NOBITS(此类型为节的唯一输入)的节都是在 data 段中捕获的。有关 SHT_NOBITS 节的完整说明,请参见表 7–5。最简单的 bss 声明:

        bss =;

便足以创建 bss 段。任何 SHT_NOBITS 节都是由此段(而不是 data 段)捕获的。此段采用最简单的形式,并且使用与应用于任何其他段相同的缺省值对齐。还可以声明其他既可创建段又可为指定属性赋值的段属性。

链接编辑器的行为方式就好像在读入 mapfile 之前已经声明了这些段。请参见Mapfile 缺省选项

输入段声明时,请注意以下事项:


注 –

如果指定了 virtual_address 值,则将段放置在该虚拟地址处。对于系统内核,此方法可生成正确的结果。对于通过 exec(2) 启动的文件,此方法将生成错误的输出文件,因为段与其页边界的相对偏移量是错误的。


可以使用 ?E 标志创建空段。此空段没有关联的节。此段只能为可执行文件指定,并且其类型必须为具有指定大小和对齐值的 LOAD。允许具有多个此类型的段定义。

可以使用 ?N 标志控制是否将 ELF 头和任何程序头作为第一个可装入段的一部分包括在内。缺省情况下,ELF 头和程序头包括在第一个段内。这些头中的信息通常由运行时链接程序用在映射的映像中。可以使用 ?N 选项从第一个段的第一个节开始计算映像的虚拟地址。

可以使用 ?O 标志控制输出文件中各节的顺序。此标志用于与编译器的 -xF 选项一起使用。使用 -xF 选项编译文件时,将该文件中的每个函数都放置在与 .text 节具有相同属性的单独节中。这些节称为 .text%function_name

例如,使用 -xF 选项编译包含 main()foo()bar() 这三个函数的文件时,会生成可重定位的目标文件,并会将三个函数的文本放置在名为 .text%main.text%foo.text%bar 的节中。由于 -xF 选项强制实行每节一个函数,因此使用 ?O 标志控制各节的顺序实际上是控制函数的顺序。

请考虑以下用户定义的 mapfile

        text = LOAD ?RXO;

        text: .text%foo;

        text: .text%bar;

        text: .text%main;

第一个声明将 ?O 标志与缺省文本段进行关联。

如果源文件中函数定义的顺序为 mainfoobar,则最终的可执行文件所包含的函数顺序为 foobarmain

对于具有相同名称的静态函数,还必须使用文件名。?O 标志强制按 mapfile 中的要求对节进行排序。例如,如果静态函数 bar() 位于文件 a.ob.o 中,并且要将文件 a.o 中的函数 bar() 放置在文件 b.o 中的函数 bar() 之前,则 mapfile 项将显示为:

        text: .text%bar: a.o;

        text: .text%bar: b.o;

虽然此语法允许具有项:

        text: .text%bar: a.o b.o;

但此项不能保证将文件 a.o 中的函数 bar() 放置在 b.o 中的函数 bar() 之前。由于结果不可靠,因此建议不要使用第二种格式。