JavaScript is required to for searching.
跳过导航链接
退出打印视图
链接程序和库指南     Oracle Solaris 11 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

第 1 部分使用链接编辑器和运行时链接程序

1.  Oracle Solaris 链接编辑器介绍

2.  链接编辑器

3.  运行时链接程序

4.  共享目标文件

5.  接口和版本控制

6.  使用动态字符串标记建立依赖性

第 2 部分快速参考

7.  链接编辑器快速参考

8.  版本控制快速参考

第 3 部分高级主题

9.  直接绑定

10.  Mapfile

11.  可扩展性机制

第 4 部分ELF 应用程序二进制接口

12.  目标文件格式

文件格式

数据表示形式

ELF 头

ELF 标识

数据编码

节合并

特殊节

COMDAT 节

组节

功能节

散列表节

移动节

注释节

重定位节

重定位计算

SPARC: 重定位

SPARC: 重定位类型

64 位 SPARC: 重定位类型

x86: 重定位

32 位 x86: 重定位类型

x64: 重定位类型

字符串表节

符号表节

符号值

符号表布局和约定

符号排序节

寄存器符号

Syminfo 表节

版本控制节

版本定义章节

版本依赖性节

版本符号节

13.  程序装入和动态链接

14.  线程局部存储

第 5 部分附录

A.  链接程序和库的更新及新增功能

B.  System V 发行版 4(版本 1)Mapfile

索引

符号表节

目标文件的符号表包含定位和重定位程序的符号定义和符号引用所需的信息。符号表索引是此数组的下标。索引 0 指定表中的第一项并用作未定义的符号索引。请参见表 12-21

符号表项具有以下格式。请参见 sys/elf.h

typedef struct {
        Elf32_Word      st_name;
        Elf32_Addr      st_value;
        Elf32_Word      st_size;
        unsigned char   st_info;
        unsigned char   st_other;
        Elf32_Half      st_shndx;
} Elf32_Sym;

typedef struct {
        Elf64_Word      st_name;
        unsigned char   st_info;
        unsigned char   st_other;
        Elf64_Half      st_shndx;
        Elf64_Addr      st_value;
        Elf64_Xword     st_size;
} Elf64_Sym;
st_name

目标文件的符号字符串表的索引,其中包含符号名称的字符表示形式。如果该值为非零,则表示指定符号名称的字符串表索引。否则,符号表项没有名称。

st_value

关联符号的值。根据上下文,该值可以是绝对值或地址。请参见符号值

st_size

许多符号具有关联大小。例如,数据目标文件的大小是目标文件中包含的字节数。如果符号没有大小或大小未知,则此成员值为零。

st_info

符号的类型和绑定属性。表 12-18 中显示了值和含义的列表。以下代码说明了如何处理这些值。请参见 sys/elf.h

#define ELF32_ST_BIND(info)          ((info) >> 4)
#define ELF32_ST_TYPE(info)          ((info) & 0xf)
#define ELF32_ST_INFO(bind, type)    (((bind)<<4)+((type)&0xf))

#define ELF64_ST_BIND(info)          ((info) >> 4)
#define ELF64_ST_TYPE(info)          ((info) & 0xf)
#define ELF64_ST_INFO(bind, type)    (((bind)<<4)+((type)&0xf))
st_other

符号的可见性。表 12-20 中显示了值和含义的列表。以下代码说明了如何处理 32 位目标文件和 64 位目标文件的值。其他位设置为零,并且未定义任何含义。

#define ELF32_ST_VISIBILITY(o)       ((o)&0x3)
#define ELF64_ST_VISIBILITY(o)       ((o)&0x3)
st_shndx

所定义的每一个符号表项都与某节有关。此成员包含相关节头表索引。部分节索引会表示特殊含义。请参见表 12-4

如果此成员包含 SHN_XINDEX,则实际节头索引会过大而无法放入此字段中。实际值包含在 SHT_SYMTAB_SHNDX 类型的关联节中。

根据符号的 st_info 字段确定的符号绑定可确定链接可见性和行为。

表 12-18 ELF 符号绑定 ELF32_ST_BINDELF64_ST_BIND

名称
STB_LOCAL
0
STB_GLOBAL
1
STB_WEAK
2
STB_LOOS
10
STB_HIOS
12
STB_LOPROC
13
STB_HIPROC
15
STB_LOCAL

局部符号。这些符号在包含其定义的目标文件的外部不可见。名称相同的局部符号可存在于多个文件中而不会相互干扰。

STB_GLOBAL

全局符号。这些符号对于合并的所有目标文件都可见。一个文件的全局符号定义满足另一个文件对相同全局符号的未定义引用。

STB_WEAK

弱符号。这些符号与全局符号类似,但其定义具有较低的优先级。

STB_LOOS - STB_HIOS

此范围内包含的值(包括这两个值)保留用于特定于操作系统的语义。

STB_LOPROC - STB_HIPROC

此范围内包含的值(包括这两个值)保留用于特定于处理器的语义。

全局符号和弱符号主要在以下两个方面不同:


注 - 弱符号主要适用于系统软件。建议不要在应用程序中使用弱符号。


在每个符号表中,具有 STB_LOCAL 绑定的所有符号都优先于弱符号和全局符号。如中所述,符号表节的 sh_info 节头成员包含第一个非局部符号的符号表索引。

根据符号的 st_info 字段确定的符号类型用于对关联实体进行一般等级划分。

表 12-19 ELF 符号类型 ELF32_ST_TYPEELF64_ST_TYPE

名称
STT_NOTYPE
0
STT_OBJECT
1
STT_FUNC
2
STT_SECTION
3
STT_FILE
4
STT_COMMON
5
STT_TLS
6
STT_LOOS
10
STT_HIOS
12
STT_LOPROC
13
STT_SPARC_REGISTER
13
STT_HIPROC
15
STT_NOTYPE

未指定符号类型。

STT_OBJECT

此符号与变量、数组等数据目标文件关联。

STT_FUNC

此符号与函数或其他可执行代码关联。

STT_SECTION

此符号与节关联。此类型的符号表各项主要用于重定位,并且通常具有 STB_LOCAL 绑定。

STT_FILE

通常,符号的名称会指定与目标文件关联的源文件的名称。文件符号具有 STB_LOCAL 绑定和节索引 SHN_ABS。此符号(如果存在)位于文件的其他 STB_LOCAL 符号前面。

符号索引为 1 的 SHT_SYMTAB 是表示目标文件的 STT_FILE 符号。通常,此符号后跟文件的 STT_SECTION 符号。这些节符号又后跟已降为局部符号的任何全局符号。

STT_COMMON

此符号标记未初始化的通用块。此符号的处理与 STT_OBJECT 的处理完全相同。

STT_TLS

此符号指定线程局部存储实体。定义后,此符号可为符号指明指定的偏移,而不是实际地址。

线程局部存储重定位只能引用 STT_TLS 类型的符号。从可分配节中引用 STT_TLS 类型的符号只能通过使用特殊线程局部存储重定位来实现。有关详细信息,请参见第 14 章。从非可分配节中引用 STT_TLS 类型的符号没有此限制。

STT_LOOS - STT_HIOS

此范围内包含的值(包括这两个值)保留用于特定于操作系统的语义。

STT_LOPROC - STT_HIPROC

此范围内包含的值(包括这两个值)保留用于特定于处理器的语义。

符号的可见性根据其 st_other 字段确定。此可见性可以在可重定位目标文件中指定。此可见性定义了在符号成为可执行文件或共享目标文件的一部分后访问该符号的方式。

表 12-20 ELF 符号可见性

名称
STV_DEFAULT
0
STV_INTERNAL
1
STV_HIDDEN
2
STV_PROTECTED
3
STV_EXPORTED
4
STV_SINGLETON
5
STV_ELIMINATE
6
STV_DEFAULT

具有 STV_DEFAULT 属性的符号的可见性与符号的绑定类型指定的可见性相同。全局符号和弱符号在其定义组件(可执行文件或共享目标文件)外部可见。局部符号处于隐藏状态。另外,还可以替换全局符号和弱符号。可以在另一个组件中通过定义相同的名称插入这些符号。

STV_PROTECTED

如果当前组件中定义的符号在其他组件中可见,但不能被替换,则该符号处于受保护状态。定义组件中对这类符号的任何引用都必须解析为该组件中的定义。即使在另一个组件中存在按缺省规则插入的符号定义,也必须进行此解析。具有 STB_LOCAL 绑定的符号将没有 STV_PROTECTED 可见性。

STV_HIDDEN

如果当前组件中定义的符号的名称对于其他组件不可见,则该符号处于隐藏状态。必须对这类符号进行保护。此属性用于控制组件的外部接口。由这样的符号命名的目标文件仍可以在另一个组件中引用(如果将目标文件的地址传到外部)。

如果可执行文件或共享目标文件中包括可重定位目标文件,则该目标文件中包含的隐藏符号将会删除或转换为使用 STB_LOCAL 绑定。

STV_INTERNAL

此可见性属性当前被保留。

STV_EXPORTED

此可见性属性确保符号保持为全局。不能使用任何其他符号可见性技术对此可见性进行降级或消除。具有 STB_LOCAL 绑定的符号将没有 STV_EXPORTED 可见性。

STV_SINGLETON

此可见性属性确保符号保持为全局,并且符号定义的一个实例绑定到一个进程中的所有引用。不能使用任何其他符号可见性技术对此可见性进行降级或消除。具有 STB_LOCAL 绑定的符号将没有 STV_SINGLETON 可见性。不能直接绑定到 STV_SINGLETON

STV_ELIMINATE

此可见性属性扩展 STV_HIDDEN。当前组件中定义为要消除的符号对其他组件不可见。该符号未写入使用该组件的动态可执行文件或共享目标文件的任何符号表中。

STV_SINGLETON 可见性属性可以影响链接编辑过程中可执行文件或共享目标文件中的符号的解析。从一个进程中的任意引用只能绑定到单件的一个实例。

STV_SINGLETON 可以与 STV_DEFAULT 可见性属性组合,其中 STV_SINGLETON 优先级较高。STV_EXPORT 可以与 STV_DEFAULT 可见性属性组合,其中 STV_EXPORT 优先级较高。STV_SINGLETONSTV_EXPORT 可见性不能与任何其他可见性属性组合。链接编辑会将此类事件视为致命错误。

在链接编辑过程中,其他可见性属性不会影响可执行文件或共享目标文件中符号的解析。这样的解析由绑定类型控制。一旦链接编辑器选定了其解析,这些属性即会强加两种要求。两种要求都基于以下事实,即所链接的代码中的引用可能已优化,从而可利用这些属性。

如果符号的值指向节中的特定位置,则符号的节索引成员 st_shndx 会包含节头表的索引。节在重定位过程中移动时,符号的值也会更改。符号的引用仍然指向程序中的相同位置。一些特殊节索引值会具有其他语义:

SHN_ABS

此符号具有不会由于重定位而发生更改的绝对值。

SHN_COMMONSHN_AMD64_LCOMMON

此符号标记尚未分配的通用块。与节的 sh_addralign 成员类似,符号的值也会指定对齐约束。链接编辑器在值为 st_value 的倍数的地址位置为符号分配存储空间。符号的大小会指明所需的字节数。

SHN_UNDEF

此节表索引表示未定义符号。链接编辑器将此目标文件与用于定义所表示的符号的另一目标文件合并时,此文件中对该符号的引用将与该定义绑定。

如之前所述,索引 0 (STN_UNDEF) 的符号表项会保留。此项具有下表中列出的值。

表 12-21 ELF 符号表项:索引 0

名称
st_name
0
无名称
st_value
0
零值
st_size
0
无大小
st_info
0
无类型,局部绑定
st_other
0
st_shndx
SHN_UNDEF
无节

符号值

不同目标文件类型的符号表的各项对于 st_value 成员的解释稍有不同。

尽管符号表值对于不同的目标文件具有类似含义,但通过适当的程序可以有效地访问数据。

符号表布局和约定

按照以下顺序将符号写入符号表。

这些符号表是 Oracle Solaris OS 中的特殊内容。

.symtab (SHT_SYMTAB)

此符号表包含说明关联的 ELF 文件的每个符号。此符号表通常是不可分配的,因此在进程的内存映像中不可用。

通过使用 mapfileELIMINATE 关键字可以从 .symtab 中消除全局符号。请参见删除符号SYMBOL_SCOPE / SYMBOL_VERSION 指令

.dynsym (SHT_DYNSYM)

此表包含 .symtab 表中支持动态链接所需的符号的子集。此符号表可供分配,因此在进程的内存映像中可用。

.dynsym 表以标准 NULL 符号开始,后跟文件全局符号。STT_FILE 符号通常不包含在此符号表中。如果重定位项需要,可能会包含 STT_SECTION 符号。

.SUNW_ldynsym (SHT_SUNW_LDYNSYM)

扩充 .dynsym 表中包含的信息的可选符号表。.SUNW_ldynsym 表包含局部函数符号。此符号表可供分配,因此在进程的内存映像中可用。当不可分配的 .symtab 不可用,或已从文件中剥离时,调试器通过使用此节可在运行时上下文中产生精确的栈跟踪。此节还可以为运行时环境提供其他符号信息,以便与 dladdr(3C) 一起使用。

仅当 .dynsym 表存在时,才存在 .SUNW_ldynsym 表。当 .SUNW_ldynsym 节和 .dynsym 节同时存在时,链接编辑器会将其数据区域紧邻彼此放置,其中 .SUNW_ldynsym 放置在前面。这种放置方式可以使两个表看起来像是一个更大的连续符号表。此符号表遵从先前枚举的标准布局规则。

.SUNW_ldynsym 表可以通过使用链接编辑器的 -z noldynsym 选项进行消除。

符号排序节

由相邻的 .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 符号时会生成此节。

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

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

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

DYNSORT

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

NODYNSORT

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

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

$ elfdump -sN.symtab foo.so.1 | egrep "foo$|bar$"
      [37]  0x000004b0 0x0000001c  FUNC GLOB  D   0 .text      bar
      [38]  0x000004b0 0x0000001c  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]  0x000004b0 0x0000001c  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]  0x000004b0 0x0000001c  FUNC GLOB  D   0 .text      bar

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

寄存器符号

SPARC 体系结构支持寄存器符号,这些符号用于初始化全局寄存器。下表中列出了寄存器符号的符号表项包含的各项。

表 12-22 SPARC: ELF 符号表项:寄存器符号

字段
含义
st_name
符号名称的字符串表的索引;若其值为 0 则代表临时寄存器。
st_value
寄存器编号。有关整数寄存器赋值的信息,请参见 ABI 手册。
st_size
未使用 (0)。
st_info
绑定通常为 STB_GLOBAL,类型必须是 STT_SPARC_REGISTER
st_other
未使用 (0)。
st_shndx
如果该目标文件初始化此寄存器符号,则为 SHN_ABS,否则为 SHN_UNDEF

下表中列出了为 SPARC 定义的寄存器值。

表 12-23 SPARC: ELF 寄存器编号

名称
含义
STO_SPARC_REGISTER_G2
0x2
%g2
STO_SPARC_REGISTER_G3
0x3
%g3

如果缺少特定全局寄存器的项,则意味着目标文件根本没有使用特定全局寄存器。