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

退出打印视图

更新时间: 2014 年 7 月
 
 

符号排序节

由相邻的 .SUNW_ldynsym 节和 .dynsym 节构成的动态符号表可用于将内存地址映射到其对应的符号。这种映射可用于确定给定地址表示哪个函数或变量。但是,按照符号写入符号表的顺序分析符号表以确定映射是很复杂的。请参见符号表布局和约定。此布局使地址与符号名称之间的关联变得复杂,具体表现在以下几个方面。

  • 符号不是按地址排序的,这将强制对整个表进行线性搜索,从而增大开销。

  • 可能有多个符号指向给定地址。尽管这些符号均有效且正确,但调试工具应选择使用这些等效名称中的哪一个可能并不明确。不同的工具可能会使用不同的备用名称。这些问题可能会给用户带来困惑。

  • 许多符号提供无地址信息。搜索时不应考虑这类符号。

符号排序节就是用于解决这些问题的。符号排序节是 Elf32_WordElf64_Word 目标文件的数组。此数组中的每个元素都是 .SUNW_ldynsym.dynsym 组合符号表的索引。对数组中的元素进行排序,从而使引用的符号也按照排好的顺序提供。其中仅包含表示函数或变量的符号。使用 elfdump(1)–S 选项来显示与排序数组关联的符号。

不能同时排序常规符号和线程局部存储符号。常规符号的值是符号所引用的函数或变量的地址。线程局部存储符号的值是变量的线程偏移。因此,常规符号和线程局部存储符号使用两种不同的排序节。

.SUNW_dynsymsort

SHT_SUNW_SYMSORT 类型的节,其中包含 .SUNW_ldynsym.dynsym 组合符号表中常规符号的索引,该索引按地址排序。不表示变量或函数的符号不包括在内。

.SUNW_dyntlssort

SHT_SUNW_TLSSORT 类型的节,其中包含 .SUNW_ldynsym.dynsym 组合符号表中 TLS 符号的索引,该索引按偏移排序。仅当目标文件包含 TLS 符号时会生成此节。

链接编辑器按照显示的顺序使用以下规则来选择排序节引用的符号。

  • 符号必须具有函数或变量类型:STT_FUNCSTT_OBJECTSTT_COMMONSTT_TLS

  • 以下符号如果存在,则始终包含在内:_DYNAMIC_end_fini_GLOBAL_OFFSET_TABLE__init_PROCEDURE_LINKAGE_TABLE__start

  • 如果全局符号和弱符号引用同一个项,则会包含弱符号而排除全局符号。

  • 符号必须已定义。

  • 符号的大小不得为零。

这些规则可筛选出由编译器自动生成以及由链接编辑器生成的符号。所选择的符号是用户关注的符号。然而,在两种情况下可能需要手动干预来改进选择过程。

  • 规则未能选择所需的特殊符号。例如,某些特殊符号大小为零。

  • 选择了不需要的多余符号。例如,共享目标文件可以定义引用相同地址并且大小相同的多个符号。这些别名符号均有效地引用相同的项。您可能希望在排序节中仅包含多符号系列中的一个。

mapfile 的关键字 DYNSORTNODYNSORT 可以为符号选择提供更多的控制。请参见SYMBOL_SCOPE / SYMBOL_VERSION 指令

DYNSORT

标识应包含在排序节中的符号。符号类型必须为 STT_FUNCSTT_OBJECTSTT_COMMONSTT_TLS

NODYNSORT

标识不应包含在排序节中的符号。

例如,目标文件可能会提供以下符号表定义。

$ elfdump -sN.symtab foo.so.1 | egrep "foo$|bar$"
    [37]    0x4b0   0x1c  FUNC GLOB  D   0 .text      bar
    [38]    0x4b0   0x1c  FUNC WEAK  D   0 .text      foo

符号 foobar 表示一个别名对。缺省情况下,创建排序数组时,仅表示符号 foo

$ cc -o foo.so.1 -G foo.c
$ elfdump -S foo.so.1 | egrep "foo$|bar$"
    [13]    0x4b0   0x1c  FUNC WEAK  D   0 .text      foo

如果链接编辑器发现一个全局符号和一个弱符号引用同一个项,通常会保留弱符号。排序数组中忽略符号 bar 是因为与弱符号 foo 之间的关联。

以下 mapfile 会导致在排序数组中表示符号 bar。忽略了符号 foo

$ cat mapfile
{
        global:
                bar = DYNSORT;
                foo = NODYNSORT;
};
$ cc -M mapfile -o foo.so.2 -Kpic -G foo.c
$ elfdump -S foo.so.2 | egrep "foo$|bar$"
    [13]    0x4b0   0x1c  FUNC GLOB  D   0 .text      bar

.SUNW_dynsymsort 节和 .SUNW_dyntlssort 节,要求 .SUNW_ldynsym 节存在。因此,使用 –z noldynsym 选项还会阻止创建任何排序节。