Oracle® Solaris 11.2 链接程序和库指南

退出打印视图

更新时间: 2014 年 7 月
 
 

辅助目标文件

缺省情况下,目标文件包含可分配不可分配节。可分配节是包含可执行代码和运行时该代码需要的数据的节。不可分配节包含补充信息,在运行时执行目标文件时这些信息不是必需的。这些节用于支持调试器和其他观察工具的操作。在运行时操作系统不会将目标文件中的不可分配节装入内存,因此,无论其大小如何,都不会影响内存使用或运行时性能的其他方面。

为方便起见,可分配节和不可分配节通常保留在同一文件中。但是,在某些情况下,将这些节分开会很有用。

  • 减小目标文件的大小以便提高通过广域网对其进行复制的速度。

  • 支持对高度优化的代码进行细粒度调试需要大量的调试数据。在现代系统中,调试数据可能很轻易地就大于其所描述的代码。32 位目标文件的大小限制为 4 GB。在非常大的 32 位目标文件中,调试数据可能会导致超出限制,并阻止创建目标文件。

  • 限制内部实现详细信息泄漏。

传统上,将不可分配节从目标文件中剥离,以解决这些问题。剥离很有效,但是会销毁以后可能需要的数据。而 Solaris 链接编辑器可以将不可分配节写入辅助目标文件。此功能可使用 –z ancillary 选项启用。

$ cc .... -z ancillary[=outfile] ....

缺省情况下,辅助文件和主输出目标文件同名,具有 .anc 文件扩展名。但是,可以将 outfile 值提供给 –z ancillary 选项来指定一个不同的名称。

指定了 –z ancillary 时,链接编辑器将执行以下操作。

  • 将所有可分配节写入主目标文件。此外,将包含一个或多个设置了 SHF_SUNW_PRIMARY 节头标志的输入节的所有不可分配节写入主目标文件。

  • 将所有其余的不可分配节写入辅助目标文件。

  • 将以下不可分配节写入主目标文件和辅助目标文件。

    .shstrtab

    节名称字符串表。

    .symtab

    完整非动态符号表。

    .symtab_shndx

    .symtab 关联的符号表扩展索引节。

    .strtab

    .symtab 关联的非动态字符串表。

    .SUNW_ancillary

    包含标识主目标文件、辅助目标文件和要检查的目标文件所需的信息。

  • 主目标文件和所有辅助目标文件包含相同的节头数组。每个节在每个文件中具有相同的节索引。

  • 尽管主目标文件和辅助目标文件均定义了相同的节头,但大多数节的数据将写入单个文件中,如上所述。如果给定文件中不存在某个节的数据,则会设置 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.anc
a.out.anc: ELF 32-bit LSB ancillary 80386 Version 1, primary object a.out
$ ./a.out
hello world

生成的主目标文件是可以用平常方式执行的普通可执行文件。在运行时,该文件与生成过程中不使用辅助目标文件,然后使用 stripmcs 命令剥离不可分配内容的可执行文件没有区别。

如前所述,主目标文件和辅助目标文件包含相同的节头。要查看其如何工作,使用 elfdump 实用程序显示这些节头并对其进行比较会有所帮助。下表显示了从前一链接编辑示例中选择的部分节头的信息。

索引
节名称
类型
主标志
辅助标志
主大小
辅助大小
13
.text
PROGBITS
ALLOC EXECINSTR
ALLOC EXECINSTR SUNW_ABSENT
0x131
0
20
.data
PROGBITS
WRITE ALLOC
WRITE ALLOC SUNW_ABSENT
0x4c
0
21
.symtab
SYMTAB
0
0
0x450
0x450
22
.strtab
STRTAB
STRINGS
STRINGS
0x1ad
0x1ad
24
.debug_info
PROGBITS
SUNW_ABSENT
0
0
0x1a7
28
.shstrtab
STRTAB
STRINGS
STRINGS
0x118
0x118
29
.SUNW_ancillary
SUNW_ancillary
0
0
0x30
0x30

大多数节的数据仅存在于这两个文件之一中,不存在于另一个文件中。不存在数据时,会设置 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 节表示目标文件具有关联的辅助目标文件。

  • 主目标文件和所有关联的辅助目标文件的名称可以从任何一个文件中的辅助节中获得。

  • 通过将第一个校验和值与接下来的每个成员的校验和进行比较,可以从较大的一组文件中确定要检查哪个文件。


注 -  链接编辑器不将辅助目标文件作为输入文件进行读取。如果用 –z ancillary 选项创建可重定位目标文件,之后引用此生成的目标文件生成另一个目标文件,则辅助目标文件中的节将不会传播到最终的目标文件中。