跳过导航链接 | |
退出打印视图 | |
Oracle Solaris 11.1 链接程序和库指南 Oracle Solaris 11.1 Information Library (简体中文) |
缺省情况下,目标文件包含可分配和不可分配节。可分配节是包含可执行代码和运行时该代码需要的数据的节。不可分配节包含补充信息,在运行时执行目标文件时这些信息不是必需的。这些节用于支持调试器和其他观察工具的操作。在运行时操作系统不会将目标文件中的不可分配节装入内存,因此,无论其大小如何,都不会影响内存使用或运行时性能的其他方面。
为方便起见,可分配节和不可分配节通常保留在同一文件中。但是,在某些情况下,将这些节分开会很有用。
减小目标文件的大小以便提高通过广域网对其进行复制的速度。
支持对高度优化的代码进行细粒度调试需要大量的调试数据。在现代系统中,调试数据可能很轻易地就大于其所描述的代码。32 位目标文件的大小限制为 4 GB。在非常大的 32 位目标文件中,调试数据可能会导致超出限制,并阻止创建目标文件。
限制内部实现详细信息泄漏。
传统上,将不可分配节从目标文件中剥离,以解决这些问题。剥离很有效,但是会销毁以后可能需要的数据。而 Solaris 链接编辑器可以将不可分配节写入辅助目标文件。此功能可使用 -z ancillary 命令行选项启用。
$ ld ... -z ancillary[=outfile] ...
缺省情况下,辅助文件和主输出目标文件同名,具有 .anc 文件扩展名。但是,可以将 outfile 值提供给 -z ancillary 选项来指定一个不同的名称。
指定了 -z ancillary 时,链接编辑器将执行以下操作。
将所有可分配节写入主目标文件。此外,将包含一个或多个设置了 SHF_SUNW_PRIMARY 节头标志的输入节的所有不可分配节写入主目标文件。
将所有其余的不可分配节写入辅助目标文件。
将以下不可分配节写入主目标文件和辅助目标文件。
节名称字符串表。
完整非动态符号表。
与 .symtab 关联的符号表扩展索引节。
与 .symtab 关联的非动态字符串表。
包含标识主目标文件、辅助目标文件和要检查的目标文件所需的信息。
主目标文件和所有辅助目标文件包含相同的节头数组。每个节在每个文件中具有相同的节索引。
尽管主目标文件和辅助目标文件均定义了相同的节头,但大多数节的数据将写入单个文件中,如上所述。如果给定文件中不存在某个节的数据,则会设置 SHF_SUNW_ABSENT 节头标志,且 sh_size 字段为 0。
通过该组织,可以从主目标文件或辅助目标文件中获取节头的完整列表、完整的符号表以及主目标文件和辅助目标文件的完整列表。
以下示例说明了辅助目标文件的底层实现。辅助目标文件是通过将 -z ancillary 命令行选项添加到原本采用常规方式的编译中创建的。file 实用程序显示生成了名为 a.out 的可执行文件和名为 a.out.anc 的关联辅助目标文件。
$ cat hello.c #include <stdio.h> int main(int argc, char **argv) { (void) printf("hello, world\n"); return (0); } $ cc -g -zancillary hello.c $ file a.out a.out.anc a.out: ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped, ancillary object a.out a.out.anc: ELF 32-bit LSB ancillary 80386 Version 1, primary object a.out $ ./a.out hello world
生成的主目标文件是可以用平常方式执行的普通可执行文件。在运行时,该文件与生成过程中不使用辅助目标文件,然后使用 strip 或 mcs 命令剥离不可分配内容的可执行文件没有区别。
如前所述,主目标文件和辅助目标文件包含相同的节头。要查看其如何工作,使用 elfdump 实用程序显示这些节头并对其进行比较会有所帮助。下表显示了从前一链接编辑示例中选择的部分节头的信息。
|
大多数节的数据仅存在于这两个文件之一中,不存在于另一个文件中。不存在数据时,会设置 SHF_SUNW_ABSENT 节头标志。运行时需要的可分配节数据在主目标文件中。用于调试但运行时不需要的不可分配节的数据放置在辅助文件中。一小组不可分配节在两个文件中都完整地存在。这些是用于将主目标文件和辅助目标文件联系在一起的 .SUNW_ancillary 节、节名称字符串表 .shstrtab 、符号表 .symtab 及其关联的字符串表 .strtab。
可以从主目标文件中剥离符号表。遇到不带符号表的目标文件的调试器可以使用 .SUNW_ancillary 节查找辅助目标文件并访问其中包含的符号。
主目标文件和所有相关的辅助目标文件均包含一个允许标识所有目标文件并将其关联在一起的 .SUNW_ancillary 节。
$ elfdump -T SUNW_ancillary a.out a.out.anc a.out: Ancillary Section: .SUNW_ancillary index tag value [0] ANC_SUNW_CHECKSUM 0x8724 [1] ANC_SUNW_MEMBER 0x1 a.out [2] ANC_SUNW_CHECKSUM 0x8724 [3] ANC_SUNW_MEMBER 0x1a3 a.out.anc [4] ANC_SUNW_CHECKSUM 0xfbe2 [5] ANC_SUNW_NULL 0 a.out.anc: Ancillary Section: .SUNW_ancillary index tag value [0] ANC_SUNW_CHECKSUM 0xfbe2 [1] ANC_SUNW_MEMBER 0x1 a.out [2] ANC_SUNW_CHECKSUM 0x8724 [3] ANC_SUNW_MEMBER 0x1a3 a.out.anc [4] ANC_SUNW_CHECKSUM 0xfbe2 [5] ANC_SUNW_NULL 0
两个目标文件的辅助节包含相同数量的元素,除第一个元素外均相同。每个目标文件(从主目标文件开始)都是以下述方式引入的:首先是用于指定文件名的 MEMBER 元素,后面跟着是用于标识目标文件的 CHECKSUM。在此示例中,主目标文件为 a.out,其校验和为 0x8724。辅助目标文件为 a.out.anc,其校验和为 0xfbe2。.SUNW_ancillary 节中的第一个元素(位于主目标文件的 MEMBER 元素之前)始终是 CHECKSUM 元素,它包含要检查的文件的校验和。
目标文件中存在 .SUNW_ancillary 节表示目标文件具有关联的辅助目标文件。
主目标文件和所有关联的辅助目标文件的名称可以从任何一个文件中的辅助节中获得。
通过将第一个校验和值与接下来的每个成员的校验和进行比较,可以从较大的一组文件中确定要检查哪个文件。
调试器和其他观察工具必须合并在主目标文件和辅助目标文件中找到的信息,以便生成目标文件的完整视图。这等同于处理单个文件中的信息。包含相同节头的主目标文件和辅助目标文件以及单个符号表可简化该合并。
调试器可以使用以下步骤组合这些文件中包含的信息。
从主目标文件或任何辅助目标文件开始,查找 .SUNW_ancillary 节。存在此节指示该目标文件是辅助组的一部分,其中包含的信息可用于获取完整文件列表以及确定这些文件中的哪一个是当前检查的文件。
使用要检查的目标文件中的节头数组作为初始模板,在内存中创建一个节头数组。
依次打开并读取 .SUNW_ancillary 节标识的每个文件。对于每个文件,使用不包含 SHF_SUNW_ABSENT 标志集的每个节的信息填充内存中的节头数组。
结果是节头的一个完整内存中副本,其中包含指向所有节的数据的指针。在获得该信息后,调试器会像在使用单个文件时一样继续访问和控制正在运行的程序。
注 - 辅助目标文件的 ELF 定义提供了单个主目标文件和任意数量的辅助目标文件。当前,Oracle Solaris 链接编辑器仅生成单个包含所有不可分配节的辅助目标文件。这种情况以后可能会改变。应该编写调试器和其他观察工具来处理多个辅助目标文件的一般情况。