LOAD_SEGMENT / NOTE_SEGMENT / NULL_SEGMENT 指令
SIZE_SYMBOL 属性(仅限 LOAD_SEGMENT)
Mapfile 指令可用于指定输出目标文件的很多方面。这些指令具有通用的语法,即为属性使用名称值对,并使用 {...} 构造表示分层结构和分组。链接编辑器接受以下指令。
表 9-6 Mapfile 指令
|
后面的各个小节显示了每个支持的 mapfile 指令的特定语法。
通常在编译时会在目标文件中记录可重定位目标文件的硬件、软件、计算机和平台功能。链接编辑器结合所有输入可重定位目标文件的功能来创建输出文件的最终功能节。可以在 mapfile 中定义功能以扩充或完全取代由输入可重定位目标文件提供的功能。
CAPABILITY [capid] { HW = [hwcap_flag...]; HW += [hwcap_flag...]; HW -= [hwcap_flag...]; HW_1 = [value...]; HW_1 += [value...]; HW_1 -= [value...]; HW_2 = [value...]; HW_2 += [value...]; HW_2 -= [value...]; MACHINE = [machine_name...]; MACHINE += [machine_name...]; MACHINE -= [machine_name...]; PLATFORM = [platform_name...]; PLATFORM += [platform_name...]; PLATFORM -= [platform_name...]; SF = [sfcap_flag...]; SF += [sfcap_flag...]; SF -= [sfcap_flag...]; SF_1 = [value...]; SF_1 += [value...]; SF_1 -= [value...]; };
如果存在可选的 capid 名称,则它可以为目标文件功能提供一个符号名称,从而在输出目标文件中获得一个 CA_SUNW_ID 功能项。如果发现多个 CAPABILITY 指令,则会使用最后一个指令提供的 capid。
可以使用空 CAPABILITY 指令为目标文件功能指定一个 capid 而不指定任何功能值。
CAPABILITY capid;
对于每种功能类型,链接编辑器会维护一个当前值 (value) 和一组要排除的值 (exclude)。对于硬件和软件功能,这些值是位掩码。对于计算机和平台功能,它们是名称列表。在处理 mapfile 之前,必须清除所有功能的 value 和 exclude 值。赋值运算符的工作方式如下。
如果使用 "+=" 运算符,则指定值将添加到该功能的当前 value 中,并从该功能的 exclude 值中删除。
如果使用 "-=" 运算符,则指定值将添加到该功能的 exclude 值中,并从该功能的当前 value 中删除。
如果使用 "=" 运算符,则指定值将替换之前的 value,并且 exclude 将重置为 0。此外,使用 "=" 将覆盖通过输入文件处理收集的任何功能。
输入目标文件在读取 mapfile 后进行处理。输入目标文件指定的功能值将与来自 mapfile 的值合并,除非使用 "=" 运算符,在这种情况下,在输入目标文件中遇到时将忽略该功能。因此,"=" 运算符将覆盖输入目标文件,而 "+=" 运算符则用于扩充它们。
在将所获得的功能值写入到输出目标文件之前,链接编辑器会减去使用 "-=" 运算符指定的任何功能值。
要从输出目标文件中完全排除某个给定功能,使用 "=" 运算符和一个空值列表已足够。例如,以下示例将抑制输入目标文件提供的任何硬件功能:
$mapfile_version 2 CAPABILITY { HW = ; };
在 ELF 目标文件中,硬件和软件功能表示为目标文件功能节中的一个或多个位掩码中的位赋值。HW 和 SF mapfile 属性提供了这一实现的更抽象的视图,即接受一个空格分隔的符号功能名称列表,链接编辑器会将其转换为相应掩码和位。带有编号的属性(HW_1、HW_2、SF_1)旨在允许对底层功能位掩码进行直接数字访问。它们可用于指定尚未正式定义的功能位。如有可能,则建议使用 HW 和 SF 属性。
硬件功能指定为一个空格分隔的符号功能名称列表。对于 SPARC 平台,硬件功能定义为 <sys/auxv_SPARC.h> 中的 AV_ 值。对于 x86 平台,硬件功能定义为 <sys/auxv_386.h> 中的 AV_ 值。Mapfile 使用相同的名称,但不带 AV_ 前缀。例如,x86 AV_SSE 硬件功能在 mapfile 中称为 SSE。该列表可以包含为 CA_SUNW_HW_ 功能掩码定义的任意功能名称。
HW_1 和 HW_2 属性允许将 CA_SUNW_HW_1 和 CA_SUNW_HW_2 功能掩码直接指定为数字值,或者指定为与该掩码相对应的符号硬件功能名称。
MACHINE 属性指定目标文件可在其中执行的系统的计算机硬件名称。可通过实用程序 uname(1) 和 -m 选项显示系统的计算机硬件名称。一个 CAPABILITY 指令可以指定多个计算机名称。每个名称将在输出目标文件中获得一个 CA_SUNW_MACH 功能项。
PLATFORM 属性指定目标文件可在其中执行的系统的平台名称。可通过实用程序 uname(1) 和 -i 选项显示系统的平台名称。一个 CAPABILITY 指令可以指定多个平台名称。每个名称将在输出目标文件中获得一个 CA_SUNW_PLAT 功能项。
软件功能指定为一个空格分隔的符号功能名称列表。软件功能定义为 <sys/elf.h> 中的 SF1_SUNW_ 值。Mapfile 使用相同的名称,但不带 SF1_SUNW_ 前缀。例如,SF1_SUNW_ADDR32 软件功能在 mapfile 中称为 ADDR32。该列表可以包含为 CA_SUNW_SF_1 定义的任意功能名称。
SF_1 属性允许将 CA_SUNW_SF_1 功能掩码直接指定为数字值,或者指定为与该掩码相对应的符号软件功能名称。
链接可共享目标文件时,来自由目标文件导出的所有版本的符号通常可供链接编辑器使用。DEPEND_VERSIONS 指令用于将访问只限定于指定的版本。限制版本访问可用于确保给定输出目标文件不会使用在系统的较早版本上可能不可用的较新功能。
DEPEND_VERSIONS 指令的语法如下。
DEPEND_VERSIONS objname { ALLOW = version_name; REQUIRE = version_name; ... };
objname 是可共享目标文件的名称,在命令行中指定。在使用 -l 命令行选项指定目标文件的一般情况下,这将是带有 lib 前缀的指定名称。例如,libc 通常在命令行中引用为 -lc,因此在 DEPEND_VERSIONS 指令中指定为 libc.so。
ALLOW 属性指定所指定的版本以及该版本所继承的版本可供链接编辑器用来在输出目标文件中解析符号。链接编辑器会向输出目标文件要求中添加一个针对包含此版本的继承链中使用的最高版本的要求。
REQUIRE 将指定版本添加到输出目标文件要求中,而不管该版本是否是满足链接操作所实际需要的。
每个 ELF 目标文件在文件的偏移 0 处都有一个 ELF 头。可执行和可共享目标文件还包含通过 ELF 头访问的程序头。链接编辑器通常会将这些项目安排为包含在第一个可装入段中。因此,这些头中所含的信息会显示在映射的映像中,并通常由运行时链接程序使用。HDR_NOALLOC 指令会防止这种情况。
HDR_NOALLOC;
指定 HDR_NOALLOC 时,ELF 头和程序头数组仍显示在所获得的输出目标文件的开始处,但不包含在一个可装入段中,并且映像的虚拟地址计算始于第一个段的第一节,而非基于 ELF 头。
PHDR_ADD_NULL 指令会导致链接编辑器在程序头数组末尾添加指定数量的类型为 PT_NULL 的附加程序头项。额外的 PT_NULL 项可供后期处理实用程序使用。
PHDR_ADD_NULL = value;
value 必须是正整数值,并给出要创建的额外 PT_NULL 项数。所获得的程序头项的所有字段将设置为 0。
段是输出目标文件的一个连续部分,其中包含节。mapfile 段指令允许指定三种不同的段类型。
LOAD_SEGMENT
可装入段包含在运行时映射到进程地址空间的代码或数据。链接编辑器会为每个可分配段创建一个 PT_LOAD 程序头项,运行时链接程序使用它定位和映射段。
NOTE_SEGMENT
注释段包含注释节。链接编辑器会创建一个引用该段的 PT_NOTE 程序头项。注释段不可分配。
NULL_SEGMENT
空段中的节包含在输出目标文件中,但在运行时不能用于该目标文件。这种节的常见示例包括 .symtab 符号表以及为便于调试器操作而生成的各种节。针对空段不会创建程序头。
段指令用于在输出文件中创建新段,或更改现有段的属性值。现有段是之前定义的段,或者是预定义段中所讨论的内置段。每个新段将添加到目标文件中相同类型的最后一个此类段之后。先添加可装入段,然后是注释段,最后添加空段。与这些段相关联的任何程序头将按照与段本身相同的相对顺序放在程序头数组中。通过为可装入段设置显式地址或者使用 SEGMENT_ORDER 指令可以更改这一缺省放置方式。
如果 segment_name 是一个预先存在的段,则所指定的属性将修改现有段。否则,将创建一个新段并为新段应用指定属性。链接编辑器会为未明确提供的属性填入缺省值。
注 - 选择段名称时,请注意链接编辑器的未来版本可能会添加新的预定义段。如果您的段指令中使用的名称与此新名称相匹配,则新的预定义段会将 mapfile 的含义从创建新段更改为修改现有段。防止这种情况的最好方式是避免为段使用通用名称,并为您的所有段名称指定一个唯一的前缀,例如公司/项目标识符,甚至程序的名称。例如,名为 hello_world 的程序可以使用段名称 hello_world_data_segment。
所有这三个段指令共享一组通用的核心属性。段的声明如下,可用 LOAD_SEGMENT、NOTE_SEGMENT 和 NULL_SEGMENT 其中之一取代 directive。
directive segment_name { ASSIGN_SECTION [assign_name]; ASSIGN_SECTION [assign_name] { FILE_BASENAME = file_basename; FILE_OBJNAME = objname; FILE_PATH = file_path; FLAGS = section_flags; IS_NAME = section_name; TYPE = section_type; }; DISABLE; IS_ORDER = assign_name...; IS_ORDER += assign_name...; OS_ORDER = section_name...; OS_ORDER += section_name...; };
LOAD_SEGMENT 指令接受一组特定于可装入段的附加属性。这些附加属性的语法如下。
LOAD_SEGMENT segment_name { ALIGN = value; FLAGS = segment_flags; FLAGS += segment_flags; FLAGS -= segment_flags; MAX_SIZE = value; NOHDR; PADDR = value; ROUND = value; SIZE_SYMBOL = symbol_name...; SIZE_SYMBOL += symbol_name...; VADDR = value; };
其中的任何段指令都可指定为空指令。当空段指令创建新段时,将为所有段属性设置缺省值。空段的声明如下。
LOAD_SEGMENT segment_name; NOTE_SEGMENT segment_name; NULL_SEGMENT segment_name;
下面将说明一个或多个段指令所接受的所有属性。
ALIGN 属性用于指定可装入段的对齐方式。所指定的值设置在对应于该段的程序头的 p_align 字段中。段对齐用于计算段开头的虚拟地址。
指定的对齐方式必须是 2 的幂。缺省情况下,链接编辑器将段的对齐方式设置为内置缺省值。此缺省值随 CPU 的不同而不同,甚至也可能随软件修订版的不同而不同。
ALIGN 属性与 PADDR 和 VADDR 属性相互排斥,不能与其一起使用。当指定了 PADDR 或 VADDR 时,对应程序头的 p_align 字段将设置为缺省值。
ASSIGN_SECTION 指定一个节属性组合,例如节名称、类型和标志,它们共同确定将某个节分配给某个给定段。每个此类属性集合称为一个入口条件。当节属性与入口条件的那些属性精确匹配时,该节即匹配。未指定任何属性的 ASSIGN_SECTION 将匹配与条件进行比较的任何节。
针对某个给定段允许使用多个 ASSIGN_SECTION 属性。每个 ASSIGN_SECTION 属性都独立于其他属性。如果某节与其中任何一个与段关联的 ASSIGN_SECTION 定义相匹配,则将该节指定给该段。除非段具有至少一个 ASSIGN_SECTION 属性,否则链接编辑器不会将节指定给段。
链接编辑器使用一个内部入口条件列表将节指定给段。在 mapfile 中遇到的每个 ASSIGN_SECTION 声明都按照所遇到的顺序放在此列表中。预定义段中所讨论的内置段的入口条件将紧接最后一个 mapfile 定义的项放在此列表中。
可以为入口条件指定一个可选名称 (assign_name)。该名称可与 IS_ORDER 属性一起使用,以指定输入节在输出节中的放置顺序。
为放置输入节,链接编辑器从入口条件列表的开头开始,将节的属性依次与每个入口条件进行比较。节将指定给与节属性精确匹配的第一个入口条件所关联的段。如果没有匹配,该节将放置在文件的最后,所有非可分配节通常都是如此。
ASSIGN_SECTION 接受以下各项。
FILE_BASENAME、FILE_OBJNAME、FILE_PATH
这些属性允许基于其所来自的文件的路径 (FILE_PATH)、根基名称 (FILE_BASENAME) 或目标文件名称 (FILE_OBJNAME) 选择节。
文件路径使用标准 Unix 斜杠分隔约定来指定。最后的路径段是路径的根基名称,也可以简单地称为文件名。对于归档文件,可以使用归档成员的名称对根基名称进行扩充,即采用 archive_name(component_name) 的形式。例如,/lib/libfoo.a(bar.o) 指定在名为 /lib/libfoo.a 的归档文件中找到的目标文件 bar.o。
FILE_BASENAME 和 FILE_OBJNAME 在应用于非归档文件时是等效的,它们将文件的给定名称与根基名称进行比较。在应用至归档文件时,FILE_BASENAME 将检查归档文件名称的根基名称,而 FILE_OBJNAME 将检查包含在归档文件中的目标文件的名称。
每个 ASSIGN_SECTION 会维护所有 FILE_BASENAME、FILE_PATH 和 FILE_OBJNAME 值的一个列表。如果其中任何一个定义与某个输入文件相匹配,则文件匹配。
IS_NAME
输入节名称。
TYPE
指定 ELF section_type,它可以是 <sys/elf.h> 中定义的任何 SHT_ 常量,且不带 SHT_ 前缀。(例如,PROGBITS、SYMTAB、NOBITS)。
FLAGS
FLAGS 属性使用 section_flags 将节属性指定为表 9-7 中所给定的一个或多个值的空格分隔列表,这些值与 <sys/elf.h> 中定义的 SHF_ 值相对应。如果某个标志前面带有叹号 (!),则不能显式存在该属性。在下面的示例中,节定义为可分配但不可写入。
ALLOC !WRITE
未明确出现在 section_flags 列表中的标志将予以忽略。在上面的示例中,将节与指定标志进行匹配时,将只检查 ALLOC 和 WRITE 的值。其他节标志可以具有任意值。
表 9-7 节 FLAGS 值
|
DISABLE 属性会导致链接编辑器忽略段。不会将任何节指定给禁用的段。当由以下段指令引用时,将自动重新启用段。因此,空引用即足以重新启用禁用的段。
segment segment_name;
FLAGS 属性将段权限指定为表 9-3 中所示权限的空格分隔列表。缺省情况下,用户定义的段将获得 READ、WRITE 和 EXECUTE 权限。预定义段中所描述的预定义段的缺省标志由链接编辑器提供,在某些情况下可能与平台相关。
该属性允许采用三种形式。
FLAGS = segment_flags...; FLAGS += segment_flags...; FLAGS -= segment_flags...;
简单的 "=" 赋值运算符将当前标志替换为新集合,"+=" 形式将新标志添加到现有集合中,而 "-=" 形式将指定标志从现有集合中删除。
链接编辑器通常按照遇到输出节的顺序将其放入段中。类似地,构成输出节的输入节也按照遇到它们的顺序进行放置。IS_ORDER 属性可用于改变输入节的这种缺省放置方式。IS_ORDER 指定入口条件名称 (assign_name) 的空格分隔列表。通过其中一个入口条件匹配的节将放置在输出节的开头,并按 IS_ORDER 指定的顺序排序。通过未在 IS_ORDER 列表中的入口条件匹配的节将按照遇到它们的顺序放置在已排序节之后。
使用 "=" 形式的赋值时,将放弃给定段的 IS_ORDER 的先前值并替换为新列表。"+=" 形式的 IS_ORDER 将新列表串联到现有列表的最后。
IS_ORDER 属性与编译器的 -xF 选项一起使用时会更有用。使用 -xF 选项编译文件时,将该文件中的每个函数都放置在与 text 节具有相同属性的单独节中。这些节称为 .text%function_name。
例如,使用 -xF 选项编译包含 main()、foo() 和 bar() 这三个函数的文件时,会生成一个可重定位的目标文件,并会将三个函数的文本放置在名为 .text%main、.text%foo 和 .text%bar 的节中。当链接编辑器将这些节放入输出中时,将删除 % 和 % 之后的任何内容。因此,所有这三个函数都将放在 .text 输出节中。IS_ORDER 属性可用于强制将它们以相对于彼此的特定顺序放在 .text 输出节中。
请考虑以下用户定义的 mapfile。
$mapfile_version 2 LOAD_SEGMENT text { ASSIGN_SECTION text_bar { IS_NAME = .text%bar }; ASSIGN_SECTION text_main { IS_NAME = .text%main }; ASSIGN_SECTION text_foo { IS_NAME = .text%foo }; IS_ORDER = text_foo text_bar text_main; };
不管这三个函数在源代码中的顺序或者链接编辑器遇到它们的顺序如何,它们在输出目标文件文本段中的顺序都将是 foo()、bar() 和 main()。
缺省情况下,链接编辑器允许段增大到段内容所需要的大小。MAX_SIZE 属性可用于指定段的最大大小。如果设置了 MAX_SIZE,链接编辑器会在段增长超出指定大小时生成错误。
如果设置了 NOHDR 属性的段成为输出目标文件中的第一个可装入段,则 ELF 头和程序头将不会包含在该段中。
NOHDR 属性与顶级 HDR_NOALLOC 指令的区别在于 HDR_NOALLOC 是一个基于段的值,仅当段成为第一个可装入段时才有效。该功能主要用于为早期的 mapfile 提供功能奇偶校验。有关更多详细信息,请参见附录 E。
建议优先使用 HDR_NOALLOC 指令,而不是段 NOHDR 属性。
链接编辑器通常按照遇到输出节的顺序将其放入段中。OS_ORDER 属性可用于改变输出节的这种缺省放置方式。OS_ORDER 指定输出节名称 (section_name) 的空格分隔列表。列出的节放在段的开头,并按照 OS_ORDER 指定的顺序排序。未在 OS_ORDER 中列出的节将按照遇到它们的顺序放在已排序节之后。
使用 "=" 形式的赋值时,将放弃给定段的 OS_ORDER 的先前值并替换为新列表。"+=" 形式的 OS_ORDER 将新列表串联到现有列表的最后。
PADDR 属性用于为段指定一个显式物理地址。所指定的值设置在对应于该段的程序头的 p_addr 字段中。缺省情况下,链接编辑器将段的物理地址设置为 0,因为此字段对于用户模式目标文件没有意义,它主要用于非用户级目标文件,如操作系统内核。
ROUND 属性用于指定段的大小应向上舍入为给定值。指定的舍入值必须是 2 的幂。缺省情况下,链接编辑器将段的舍入系数设置为 1,即不对段大小向上舍入。
SIZE_SYMBOL 属性定义要由链接编辑器创建的节大小符号名称的空格分隔列表。大小符号是全局绝对符号,以字节为单位表示段的大小。可以在目标文件中引用这些符号。为访问代码中的符号,应确保 symbol_name 是该语言中的合法标识符。建议采用 C 编程语言的符号命名规则,因为这种符号可能能够由任何其他语言访问。
可以使用 "=" 形式的赋值建立初始值,并且针对每个链接编辑器会话只能使用一次。"+=" 形式的 SIZE_SYMBOL 将新列表串联到现有列表的最后,并可根据需要使用任意次。
VADDR 属性用于为段指定一个显式虚拟地址。所指定的值设置在对应于该段的程序头的 p_vaddr 字段中。缺省情况下,链接编辑器会在创建输出文件时将虚拟地址指定给段。
SEGMENT_ORDER 指令用于为输出目标文件中的段指定非缺省顺序。
SEGMENT_ORDER 接受段名称的空格分隔列表。
SEGMENT_ORDER = segment_name...; SEGMENT_ORDER += segment_name...;
使用 "=" 形式的赋值时,将放弃之前的段顺序列表并替换为新列表。"+=" 形式的赋值将新列表串联到现有列表的最后。
缺省情况下,链接编辑器按以下方式确定段顺序。
具有通过 LOAD_SEGMENT 指令的 VADDR 属性设置的显式地址的可装入段,按地址排序。
使用 SEGMENT_ORDER 指令排序的段,按指定顺序排序。
没有显式地址且未在 SEGMENT_ORDER 列表中列出的可装入段。
没有显式地址且未在 SEGMENT_ORDER 列表中列出的注释段。
没有显式地址且未在 SEGMENT_ORDER 列表中列出的空段。
注 - ELF 具有一些格式正确的目标文件所必须遵循的隐式约定。
第一个可装入段应该是只读、可分配和可执行的,并接收 ELF 头和程序头数组。这通常是预定义的文本段。
可执行文件中的最后一个可装入段应该是可写的,并且动态堆的开头通常紧随其后放置在相同的虚拟内存映射中。
可以使用 Mapfile 创建不遵循这些要求的目标文件。但应避免如此操作,因为运行这种目标文件的结果是不确定的。
除非指定 HDR_NOALLOC 指令,否则链接编辑器将强制要求第一个段必须是可装入段,而不是注释段或空段。HDR_NOALLOC 不能用于用户级目标文件,因此没什么实用价值。生成操作系统内核时会使用该功能。
STACK 指令指定进程栈的属性。
STACK { FLAGS = segment_flags...; FLAGS += segment_flags...; FLAGS -= segment_flags...; };
FLAGS 属性指定段权限的空格分隔列表,其中包含表 9-3 中所描述的任意值。
该属性允许采用三种形式。简单的 "=" 赋值运算符将当前标志替换为新集合,"+=" 形式将新标志添加到现有集合中,而 "-=" 形式将指定标志从现有集合中删除。
缺省栈权限由平台 ABI 定义,并随平台的不同而变化。目标平台的值使用段标志名称 STACK 指定。
在某些平台上,ABI 要求的缺省权限包括 EXECUTE。一般很少需要 EXECUTE,并且它通常被视为一个潜在的安全风险。建议从栈中删除 EXECUTE 权限。
STACK { FLAGS -= EXECUTE; };
STACK 指令在输出 ELF 目标文件中反映为一个 PT_SUNWSTACK 程序头项。
STUB_OBJECT 指令通知链接编辑器可以将 mapfile 所描述的目标文件生成为一个桩目标文件。
STUB_OBJECT;
桩共享目标文件是完全通过命令行中提供的 mapfile 中的信息生成的。当指定 -z stub 选项生成桩目标文件时,要求 mapfile 中存在 STUB_OBJECT 指令,链接编辑器使用符号 ASSERT 属性中的信息创建与实际目标文件的符号相匹配的全局符号。
SYMBOL_SCOPE 和 SYMBOL_VERSION 指令用于指定全局符号的作用域和属性。SYMBOL_SCOPE 在未命名的基础符号版本的上下文中工作,而 SYMBOL_VERSION 用于将符号收集到显式命名的全局版本中。SYMBOL_VERSION 指令允许创建稳定接口,该接口支持目标文件以向下兼容方式发展。
SYMBOL_VERSION 的语法如下。
SYMBOL_VERSION version_name { symbol_scope: *; symbol_name; symbol_name { ASSERT = { ALIAS = symbol_name; BINDING = symbol_binding; TYPE = symbol_type; SIZE = size_value; SIZE = size_value[count]; }; AUXILIARY = soname; FILTER = soname; FLAGS = symbol_flags...; SIZE = size_value; SIZE = size_value[count]; TYPE = symbol_type; VALUE = value; }; } [inherited_version_name...];
SYMBOL_SCOPE 不接受版本名称,除此之外都相同。
SYMBOL_SCOPE { ... };
在 SYMBOL_VERSION 指令中,version_name 为该符号定义集合提供一个标签。该标签标识输出目标文件中的 version definition。可以指定一个或多个由空格分隔的继承版本 (inherited_version_name),这时新定义的版本将从命名的版本继承。请参见第 5 章。
symbol_scope 定义 SYMBOL_SCOPE 或 SYMBOL_VERSION 指令中符号的作用域。缺省情况下,符号被假定为具有全局作用域。通过指定 symbol_scope 并后跟一个冒号 (:) 可以修改此缺省设置。这些行确定其后所有符号的符号作用域,直至后续作用域声明做出更改。下表给出了可能的作用域值及其含义。
表 9-8 符号作用域类型
|
symbol_name 是符号的名称。该名称可生成符号定义或符号引用,具体取决于任何限定属性。在最简单的没有任何限定属性的形式中,将创建符号引用。该引用与使用使用 -u 选项定义其他符号中所讨论的 -u 选项生成的引用完全相同。通常,如果符号名称后跟任何限定属性,则使用关联的属性生成符号定义。
定义了 local(局部)作用域时,可以将符号名称定义为特殊自动缩减指令 "*"。没有显式定义可见性的符号将在所生成的动态目标文件中降级为局部绑定。显式可见性定义源自 mapfile 定义或封装在可重定位目标文件中的可见性定义。类似地,定义了 eliminate(删除)作用域时,可以将符号名称定义为特殊自动删除指令 "*"。没有显式定义可见性的符号将从所生成的动态目标文件中删除。
如果指定了 SYMBOL_VERSION 指令,或者如果使用 SYMBOL_VERSION 或 SYMBOL_SCOPE 指定了自动缩减,则会在所创建的映像中记录版本控制信息。如果此映像是可执行目标文件或共享目标文件,则还会应用任何符号缩减。
如果要创建的映像是可重定位目标文件,则缺省情况下不会应用符号缩减。在这种情况下,任何符号缩减都将记录在版本控制信息中。当最终使用可重定位目标文件来生成可执行文件或共享目标文件时,将应用这些符号缩减。在生成可重定位目标文件时,可以使用链接编辑器的 -B reduce 选项强制执行符号缩减。
第 5 章中提供了版本控制信息的更详细说明。
注 - 为了确保接口定义的稳定性,定义符号名称时不提供通配符扩展功能。
symbol_name 可单独列出,以便仅将符号分配给一个版本和/或指定其作用域。可以在 {} 括号中指定可选符号属性。下面将说明各个有效属性。
ASSERT 属性用于指定符号的预期特征。链接编辑器会比较通过链接编辑所获得的符号特征与 ASSERT 属性指定的符号特征。如果实际属性与声明的属性不一致,则会发出致命错误并且不会创建输出目标文件。
ASSERT 属性的解释取决于是使用 STUB_OBJECT 指令还是使用 -z stub 命令行选项。三种可能的情况如下所述。
不使用 STUB_OBJECT 指令时,将不需要 ASSERT 属性。但是,如果 ASSERT 属性存在,则会根据通过链接编辑收集到的实际值对其属性进行验证。如果任何 ASSERT 属性与其关联的实际值不匹配,则链接编辑过程将终止且不成功。
使用 STUB_OBJECT 指令且指定了 -z stub 命令行选项时,链接编辑器将使用 ASSERT 指令定义目标文件提供的全局符号的属性。请参见桩目标文件。
使用 STUB_OBJECT 指令但未指定 -z stub 命令行选项时,链接编辑器要求所获得的目标文件中的所有全局数据都有一个将其声明为数据并提供大小的关联 ASSERT 指令。在此模式下,如果未指定 TYPE ASSERT 属性,则假定为 GLOBAL。类似地,如果未指定 SH_ATTR,则假定为缺省值 BITS。这些缺省值可确保桩目标文件和实际目标文件的数据属性是兼容的。所获得的 ASSERT 语句的计算方式与上述第一种情况相同。请参见STUB_OBJECT 指令。
ASSERT 接受以下各项。
ALIAS
为之前定义的符号定义别名。别名符号具有与主符号相同的类型、值和大小。ALIAS 属性不能与 TYPE、SIZE 和 SH_ATTR 属性一起使用。指定了 ALIAS 时,类型、大小和节属性将从别名符号中获取。
BIND
指定 ELF symbol_binding,它可以是 <sys/elf.h> 中定义的任意 STB_ 值,但去掉 STB_ 前缀。例如,GLOBAL 或 WEAK。
TYPE
指定 ELF symbol_type,它可以是 <sys/elf.h> 中定义的任意 STT_ 常量,但去掉 STT_ 前缀。例如,OBJECT、COMMON 或 FUNC。此外,为与其他 mapfile 使用情况兼容,还可以分别为 STT_FUNC 和 STT_OBJECT 指定 FUNCTION 和 DATA。TYPE 不能与 ALIAS 一起使用。
SH_ATTR
指定与符号关联的节的属性。表 9-9 列出了可指定的 section_attributes。SH_ATTR 不能与 ALIAS 一起使用。
SIZE
指定预期符号大小。SIZE 不能与 ALIAS 一起使用。size_value 参数的语法如 SIZE 属性的讨论中所述。请参见SIZE 属性。
表 9-9 SH_ATTR 值
|
指示此符号是共享目标文件名称 (soname) 的辅助过滤器。请参见生成辅助过滤器。
指示此符号是共享目标文件 name 的过滤器。请参见生成标准过滤器。过滤器符号不需要输入可重定位目标文件提供任何后备实现。因此,使用此指令并定义符号的类型可以创建绝对符号表项。
symbol_flags 将符号属性指定为一个或多个以下值的空格分隔列表。
表 9-10 符号 FLAG 值
|
设置大小属性。此属性会导致创建符号定义。
size_value 参数可以是数字值,或者是符号名称 addrsize。addrsize 表示可保存一个内存地址的计算机字的大小。在生成 32 位目标文件时,链接编辑器会将 addrsize 替换为值 4,在生成 64 位目标文件时替换为值 8。addrsize 对于表示类型为 long 的指针变量和 C 变量的大小很有用,因为它会自动针对 32 位和 64 位目标文件进行调整,而无需使用条件输入。
可以选择为 size_value 参数添加一个括在方括号中的 count 值后缀。如果存在 count,则 size_value 和 count 将相乘以得出最终的大小值。
符号类型属性。此属性可以是 COMMON、DATA 或 FUNCTION。COMMON 会生成一个暂定符号定义。DATA 和 FUNCTION 会生成一个节符号定义或绝对符号定义。请参见符号表节。
数据属性会导致创建 OBJT 符号。带有大小但不含值的数据属性会通过将符号与某个 ELF 节相关联来创建节符号。此节将填充零。函数属性会导致创建 FUNC 符号。
带有大小但不含值的函数属性会通过将符号与某个 ELF 节相关联来创建节符号。一个由链接编辑器生成的带有以下签名的 void 函数将指定给此节。
void (*)(void)
含有值的数据或函数属性将生成相应符号类型并带有一个绝对 ABS 节索引。
创建节数据符号对于创建过滤器很有用。从可执行文件中对过滤器的节数据符号的外部引用会导致生成相应的复制重定位。请参见复制重定位。
指示值属性。此属性会导致创建符号定义。