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

退出打印视图

更新时间: 2014 年 7 月
 
 

指定版本绑定

创建动态目标文件时,如果该动态目标文件基于包含版本定义的共享目标文件进行链接,则可以指示链接编辑器将绑定仅限于特定版本定义。实际上,使用链接编辑器可以控制目标文件到特定接口的绑定。

使用 DEPEND_VERSIONS mapfile 指令可以控制目标文件的绑定要求。此指令通过链接编辑器的 –M 选项和关联的 mapfile 来提供。DEPEND_VERSIONS 指令使用以下语法。

        $mapfile_version 2
        DEPEND_VERSIONS objname {
                ALLOW   = version_name;
                REQUIRE = version_name;
                ....
        };
  • objname 代表共享目标文件依赖项的名称。此名称应当与链接编辑器所使用的共享目标文件编译环境名称一致。请参见库命名约定

  • ALLOW 属性用于指定共享目标文件内应设为可用于绑定的版本定义名称。可以指定多个 ALLOW 属性。

  • REQUIRE 属性允许记录新增的版本定义。可以指定多个 REQUIRE 属性。

在以下情况中,版本绑定的控制非常实用。

  • 当共享目标文件定义了独立的、具有唯一性的版本时。在定义不同标准接口时可以使用这种版本控制方法。可以使用绑定控制生成目标文件,以确保目标文件仅绑定到特定的接口。

  • 当共享目标文件经过了若干软件发行版的版本化时。可以使用绑定控制生成目标文件,以将其绑定限定到之前的软件发行版中可用的接口。这样,目标文件在使用最新发行版的共享目标文件生成之后,仍可以与旧发行版的共享目标文件依赖项一起运行。

以下示例说明了版本控制机制的使用。此示例使用共享目标文件 libfoo.so.1,其中包含以下版本接口定义。

$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:
                foo1;
                foo2;
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;

版本定义 SUNW_1.1SUNW_1.2libfoo.so.1 中分别代表软件 Release X Release X+1 中设为可用的接口。

使用以下版本控制 mapfile 指令,可以将应用程序生成为仅绑定到 Release X 中可用的接口。

$ cat mapfile
$mapfile_version 2
DEPEND_VERSIONS libfoo.so {
        ALLOW = SUNW_1.1;
}

例如,假定您开发一个应用程序 prog,并希望确保该应用程序可以运行于 Release X。该应用程序必须仅使用 Release X 中可用的接口。如果应用程序错误地引用了符号 bar,则该应用程序将无法符合所要求的接口。发生这种情况时,链接编辑器会提示未定义的符号错误。

$ cat prog.c
extern void foo1();
extern void bar();

main()
{
        foo1();
        bar();
}
$ cc -o prog prog.c -M mapfile -L. -R. -lfoo
Undefined           first referenced
 symbol                 in file
bar                     prog.o  (symbol belongs to unavailable \
                        version ./libfoo.so (SUNW_1.2))
ld: fatal: symbol referencing errors

要符合 SUNW_1.1 接口,必须删除对 bar 的引用。您可以重新编写应用程序,删除对 bar 的要求,或向应用程序的创建添加一个 bar 的实现。


注 - 缺省情况下,还会对照任何文件控制指令验证在链接编辑过程中遇到的共享目标文件依赖项。使用环境变量 LD_NOVERSION 可以抑制对任何共享目标文件依赖项进行版本验证。

绑定到额外的版本定义

要记录目标文件的正常符号绑定可能生成的更多版本依赖项,可以将 REQUIRE 属性用于 DEPEND_VERSIONS mapfiile 指令。以下各节说明了可以使用这种额外绑定的情形。

重新定义接口

情形之一是,将特定于 ISV 的接口转换为公共标准接口。

在之前的 libfoo.so.1 示例中,假定在 Release X+2 中,版本定义 SUNW_1.1 细分为两个标准发行版:STAND_ASTAND_B。要保持兼容性,必须保留 SUNW_1.1 版本定义。在此示例中,该版本定义表现为继承两个标准定义。

$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:           {STAND_A, STAND_B}:
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;
        STAND_A:
                foo1;
                STAND_A;
        STAND_B:
                foo2;
                STAND_B;

如果应用程序 prog 的唯一要求是接口符号 foo1,则该应用程序将仅具有一个对版本定义 STAND_A 的依赖项。这将使 prog 无法运行在 libfoo.so.1 小于 Release X+2 的系统上。版本定义 STAND_A 在之前的发行版中不存在,尽管接口 foo1 在之前的发行版中存在。

通过创建对 SUNW_1.1 的依赖项,可以生成应用程序 prog,使其要求与之前的发行版一致。

$ cat mapfile
$mapfile_version 2
DEPEND_VERSIONS libfoo.so {
        ALLOW = SUNW_1.1;
        REQUIRE = SUNW_1.1;
};
$ cat prog
extern void foo1();

main()
{
        foo1();
}
$ cc -M mapfile -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (SUNW_1.1);

此显式依赖项足以封装真实的依赖项要求。此依赖项可以满足与旧发行板的兼容性。

绑定到弱版本

创建弱版本定义描述了如何使用弱版本定义标记内部实现更改。这些版本定义非常适合指示对目标文件所做的错误修复和性能改进。如果弱版本的存在是必需的,可以生成一个对此版本定义的显式依赖项。当某项错误修复或性能改进对于目标文件的正常工作至关重要时,创建这类依赖项是非常重要的。

在之前的 libfoo.so.1 示例中,假定一项错误修复作为弱版本定义 SUNW_1.2.1 纳入软件 Release X+3 中:

$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:           {STAND_A, STAND_B}:
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;
        STAND_A:
                foo1;
                STAND_A;
        STAND_B:
                foo2;
                STAND_B;
        SUNW_1.2.1 [WEAK]:  {SUNW_1.2}:
                SUNW_1.2.1;

通常,如果应用程序依据此 libfoo.so.1 进行生成,将记录一个对版本定义 SUNW_1.2.1 的弱依赖项。此依赖项仅用于提供信息。如果在运行时使用的 libfoo.so.1 的实现中不存在版本定义,此依赖项不会导致应用程序终止。

使用 DEPEND_VERSIONS mapfile 指令的 REQUIRE 属性可以生成对版本定义的显式依赖项。如果此定义是一个弱定义,则此显式引用同时也是要提升为强依赖项的版本定义。

使用以下文件控制指令,可以将应用程序 prog 生成为强制要求 SUNW_1.2.1 接口在运行时可用。

$ cat mapfile
$mapfile_version 2
DEPEND_VERSIONS libfoo.so {
        ALLOW = SUNW_1.1;
        REQUIRE = SUNW_1.2.1;
};
$ cat prog
extern void foo1();

main()
{
        foo1();
}
$ cc -M mapfile -o prog prog.c -L. -R. -lfoo
$ pvs -r prog
        libfoo.so.1 (SUNW_1.2.1);

prog 具有一个对接口 STAND_A 的显式依赖项。因为版本定义 SUNW_1.2.1 提升为强版本,所以版本 SUNW_1.2.1 使用依赖项 STAND_A 进行标准化。在运行时,如果无法找到版本定义 SUNW_1.2.1,将生成一条致命错误。


注 - 当处理的依赖项数量较少时,可以使用链接编辑器的 –u 选项显式绑定到版本定义。使用此选项可以引用版本定义符号。但是,符号引用是不可选择的。当处理多个包含类似命名的版本定义的依赖项时,使用此方法可能不足以创建显式绑定。