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

退出打印视图

更新时间: 2014 年 7 月
 
 

记录共享目标文件名称

缺省情况下,动态可执行文件或共享目标文件中的依赖项记录将是链接编辑器所引用的关联共享目标文件的文件名。例如,根据同一共享目标文件 libfoo.so 生成的以下动态可执行文件会导致对同一依赖项具有不同的解释。

$ cc -o ../tmp/libfoo.so -G foo.o
$ cc -o prog main.o -L../tmp -lfoo
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         libfoo.so.1

$ cc -o prog main.o ../tmp/libfoo.so
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         ../tmp/libfoo.so

$ cc -o prog main.o /usr/tmp/libfoo.so
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         /usr/tmp/libfoo.so

如这些示例所示,这种记录依赖项机制会因编译技术的不同而出现不一致性。此外,在链接编辑过程中引用的共享目标文件的位置也可能会与已安装系统上的共享目标文件的最终位置有所不同。为了提供更一致的指定依赖项的方法,共享目标文件可以在自身中记录运行时据以引用共享目标文件的文件名。

在链接编辑共享目标文件过程中,可以使用 –h 选项在共享目标文件自身中记录其运行时名称。在以下示例中,将在文件自身中记录共享目标文件的运行时名称 libfoo.so.1。此标识称为 soname

$ cc -o ../tmp/libfoo.so -G -K pic -h libfoo.so.1 foo.c

以下示例说明如何使用 elfdump(1) 和引用具有 SONAME 标记的项来显示 soname 记录。

$ elfdump -d ../tmp/libfoo.so | grep SONAME
     [1]  SONAME        0x123         libfoo.so.1

链接编辑器处理包含 soname 的共享目标文件时,此名称便是作为要生成的输出文件中的依赖项记录的名称。

如果在上一示例的创建动态可执行文件 prog 的过程中使用此新版本的 libfoo.so,则所有三种创建可执行文件的方法都会记录同一依赖项。

$ cc -o prog main.o -L../tmp -lfoo
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         libfoo.so

$ cc -o prog main.o ../tmp/libfoo.so
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         libfoo.so

$ cc -o prog main.o /usr/tmp/libfoo.so
$ elfdump -d prog | grep NEEDED
     [1]  NEEDED        0x123         libfoo.so

在上述示例中,使用 –h 选项来指定不包含 "/" 的简单文件名。借助此约定,运行时链接程序可以使用一组规则来查找实际文件。有关更多详细信息,请参见查找共享目标文件依赖项

在归档中包含共享目标文件

如果共享目标文件始终通过归档库进行处理,则在共享目标文件中记录 soname 是基本的机制。

归档可以根据一个或多个共享目标文件生成,并可用于生成动态可执行文件或共享目标文件。可以从归档中提取共享目标文件来满足链接编辑的要求。与处理可重定位目标文件(串联成要创建的输出文件)不同,从归档中提取的任何共享目标文件都将记录为依赖项。有关归档提取条件的更多详细信息,请参见归档处理

归档成员的名称由链接编辑器构造,并且由归档名称和归档中的目标文件串联而成。例如:

$ cc -o libfoo.so.1 -G -K pic foo.c
$ ar -r libfoo.a libfoo.so.1
$ cc -o main main.o libfoo.a
$ elfdump -d main | grep NEEDED
     [1]  NEEDED        0x123         libfoo.a(libfoo.so.1)

由于具有此串联名称的文件无法在运行时存在,因此,在共享目标文件中提供 soname 是生成有意义的依赖项运行时文件名的唯一方法。


注 - 运行时链接程序不会从归档中提取目标文件。因此,在此示例中,必须从归档中提取所需的共享目标文件依赖项,并使其可用于运行时环境。

已记录名称冲突

使用共享目标文件创建动态可执行文件或其他共享目标文件时,链接编辑器会执行多项一致性检查。这些检查可确保输出文件中记录的任何依赖项名称都是唯一的。

如果在链接编辑过程中用作输入文件的两个共享目标文件包含相同的 soname,依赖项名称可能会发生冲突。例如:

$ cc -o libfoo.so -G -K pic -h libsame.so.1 foo.c
$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c
$ cc -o prog main.o -L. -lfoo -lbar
ld: fatal: recording name conflict: file './libfoo.so' and \
    file './libbar.so' provide identical dependency names: libsame.so.1

如果某个没有已记录 soname 的共享目标文件的文件名与同一链接编辑过程使用的其他共享目标文件的 soname 匹配,则也会出现类似的错误情况。

如果要生成的共享目标文件的运行时名称与它的某个依赖项匹配,则链接编辑器也会报告名称冲突。

$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c -L. -lfoo
ld: fatal: recording name conflict: file './libfoo.so' and \
    -h option provide identical dependency names: libsame.so.1