ZHCADC4A September 2011 – March 2014
GNU 符号版本控制允许用户为从 DSO 导出的符号指定版本名称。这允许 DSO 中同一符号定义有多个版本,其中之一标记为默认值。当链接到该符号定义时,始终使用默认版本来绑定符号引用。
例如,假设库实现方在 codec_1_0.dso 中定义了 API 函数 api_do_encode。最初只有一个版本,称为 VER1。应用程序链接到该 DSO 时,对 api_do_encode 的所有引用都由 api_do_encode 的 VER1 解析。后来,实现方通过添加更新但不兼容的 api_do_encode 版本来增强 API,但仍然希望支持以前使用旧 API 构建的应用程序。创建新的 codec_2_0.dso 时,实现方可使用原始 VER1 api_do_encode 和同一符号的新 VER2 定义,VER2 现在成为指定的默认版本。新应用程序链接到 codec_2_0.dso 时,对 api_do_encode 的引用将由 VER2 api_do_encode 解析。原始 VER1 api_do_encode 仍然可用于满足根据 codec_1_0.dso 构建的旧应用程序的引用。
有关指定符号版本的机制的详细信息,请参阅 Drepper 的论文。
GNU 符号版本控制信息记录在三个 ELF 段中:
该段定义与从该可执行文件导出的符号相关的版本名称。该段还定义文件的版本。
可通过动态段中的 DT_VERDEF 标签条目来定位该段。标签 DT_VERDEFNUM 包含该段所含版本定义的数量。版本定义段的段类型为 SHT_TI_verdef。请注意,该段类型值 0x6FFFFFFD 与 SHT_GNU_verdef 相同。本规范建议该段使用名称 .gnu.version_d。然而,仅应使用段类型来标识该段;不应使用名称。
该段记录该可执行文件中未定义符号引用需求的版本。每个条目都命名一个 DSO 并指向其需求版本的列表。动态链接器加载可执行文件时,将查找并加载所需的所有 DSO。在公开此类 DSO 之前,动态链接器将首先检查该 DSO 的版本定义是否满足可执行文件的版本需求。静态链接器将引用绑定到来自 DSO 的定义时,会记录该版本需求信息。
该段通过将版本号添加到动态符号条目来扩展动态符号表。该段所含条目数与动态符号表相同。符号 id 用于为该版本号表创建索引。如果符号未定义,则版本号与版本需求段中的版本需求条目匹配。如已定义符号,则版本号与版本定义段中的版本定义条目匹配。位 15 清零时,版本定义为默认值。
ELF 提供了一种机制,能够在 ELF 可执行文件中定位和标识这些符号版本段。这些段由动态段中的动态标签定位,并使用特殊段类型来标识。
例如,版本定义段由动态标签 DT_VERDEF 定位。DT_VERDEFNUM 标签包含版本定义段中的版本定义数。该段的段类型应为 SHT_GNU_verdef (0x6FFFFFFD)。该段的标称名称为 .gnu.version_d,但实现应依赖于段类型而不是名称。