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.  使用动态字符串标记建立依赖性

特定于功能的共享目标文件

减少 filtee 搜索

特定于指令集的共享目标文件

减少 filtee 搜索

特定于系统的共享目标文件

查找关联的依赖项

非绑定产品之间的依赖性

安全性

第 2 部分快速参考

7.  链接编辑器快速参考

8.  版本控制快速参考

第 3 部分高级主题

9.  直接绑定

10.  Mapfile

11.  可扩展性机制

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

12.  目标文件格式

13.  程序装入和动态链接

14.  线程局部存储

第 5 部分附录

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

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

索引

查找关联的依赖项

通常,非绑定产品用于在唯一的位置上安装。此产品由二进制文件、共享目标文件依赖项和关联的配置文件组成。例如,非绑定产品 ABC 可能具有下图所示的布局。

图 6-1 非绑定依赖项

image:非绑定依赖项示例。

假定此产品适用于安装在 /opt 下。通常,您会向 PATH 中增加 /opt/ABC/bin,以定位产品的二进制代码。每个二进制代码均使用硬编码的运行路径在二进制代码内查找其依赖项。对于应用程序 abc,此运行路径将如下所示:

$ cc -o abc abc.c -R/opt/ABC/lib -L/opt/ABC/lib -lA
$ elfdump -d abc | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x1b5               libA.so.1
       ....
       [4]  RUNPATH           0x1bf               /opt/ABC/lib

类似地,对于依赖项 libA.so.1,此运行路径将如下所示:

$ cc -o libA.so.1 -G -Kpic A.c -R/opt/ABC/lib -L/opt/ABC/lib -lB
$ elfdump -d libA.so.1 | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x96                libB.so.1
       [4]  RUNPATH           0xa0                /opt/ABC/lib

此依赖项表示法将一直有效,直到将产品安装到除建议的缺省目录之外的某个目录中。

动态标记 $ORIGIN 扩展到目标文件的原始目录中。此标记可用于过滤器、运行路径或依赖项定义。可以使用此技术重新定义非绑定应用程序,根据 $ORIGIN 查找其依赖项:

$ cc -o abc abc.c '-R$ORIGIN/../lib' -L/opt/ABC/lib -lA
$ elfdump -d abc | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x1b5               libA.so.1
       ....
       [4]  RUNPATH           0x1bf               $ORIGIN/../lib

而依赖项 libA.so.1 也可以根据 $ORIGIN 进行定义:

$ cc -o libA.so.1 -G -Kpic A.c '-R$ORIGIN' -L/opt/ABC/lib -lB
$ elfdump -d lib/libA.so.1 | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x96                libB.so.1
       [4]  RUNPATH           0xa0                $ORIGIN

如果此产品目前安装在 /usr/local/ABC 下,并在您的 PATH 中增加 /usr/local/ABC/bin,则调用应用程序 abc 将产生如下所示的路径名查询,以查找其依赖项:

$ ldd -s abc
....
  find object=libA.so.1; required by abc
    search path=$ORIGIN/../lib  (RUNPATH/RPATH from file abc) 
      trying path=/usr/local/ABC/lib/libA.so.1
        libA.so.1 =>     /usr/local/ABC/lib/libA.so.1
 
  find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1
    search path=$ORIGIN  (RUNPATH/RPATH from file /usr/local/ABC/lib/libA.so.1)
      trying path=/usr/local/ABC/lib/libB.so.1
        libB.so.1 =>     /usr/local/ABC/lib/libB.so.1

注 - 包含 $ORIGIN 标记的目标文件可使用符号链接进行引用。在这种情况下,符号链接完全解析以确定目标文件的真正来源。


非绑定产品之间的依赖性

另一个与依赖项位置相关的问题是如何建立非绑定产品能借以表达相互之间依赖性的模型。

例如,非绑定产品 XYZ 可能依赖于产品 ABC。可以通过主机软件包安装脚本来建立此依赖性。此脚本生成一个指向 ABC 产品安装点的符号链接,如下图所示:

图 6-2 非绑定共同依赖项

image:非绑定共同依赖项示例。

XYZ 产品的二进制代码和共享目标文件可使用符号链接来表示其对于 ABC 产品的依赖性。此链接现在是一个稳定的参照点。对于应用程序 xyz,此运行路径将如下所示:

$ cc -o xyz xyz.c '-R$ORIGIN/../lib:$ORIGIN/../ABC/lib' \ -L/opt/ABC/lib -lX -lA
$ elfdump -d xyz | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x1b5               libX.so.1
       [1]  NEEDED            0x1bf               libA.so.1
       ....
       [2]  NEEDED            0x18f               libc.so.1
       [5]  RUNPATH           0x1c9               $ORIGIN/../lib:$ORIGIN/../ABC/lib

类似地,对于依赖项 libX.so.1,此运行路径将如下所示:

$ cc -o libX.so.1 -G -Kpic X.c '-R$ORIGIN:$ORIGIN/../ABC/lib' \ -L/opt/ABC/lib -lY -lC
$ elfdump -d libX.so.1 | egrep 'NEEDED|RUNPATH'
       [0]  NEEDED            0x96                libY.so.1
       [1]  NEEDED            0xa0                libC.so.1
       [5]  RUNPATH           0xaa                $ORIGIN:$ORIGIN/../ABC/lib

如果此产品目前安装在 /usr/local/XYZ 下,则需要使用其后安装脚本来建立以下内容的符号链接:

$ ln -s ../ABC /usr/local/XYZ/ABC

如果在您的 PATH 中增加 /usr/local/XYZ/bin,则调用应用程序 xyz 将产生如下所示的路径名查询,以查找其依赖项:

$ ldd -s xyz
....
  find object=libX.so.1; required by xyz
    search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib  (RUNPATH/RPATH from file xyz)
      trying path=/usr/local/XYZ/lib/libX.so.1
        libX.so.1 =>     /usr/local/XYZ/lib/libX.so.1
 
  find object=libA.so.1; required by xyz
    search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib  (RUNPATH/RPATH from file xyz)
      trying path=/usr/local/XYZ/lib/libA.so.1
      trying path=/usr/local/ABC/lib/libA.so.1
        libA.so.1 =>     /usr/local/ABC/lib/libA.so.1
 
  find object=libY.so.1; required by /usr/local/XYZ/lib/libX.so.1
     search path=$ORIGIN:$ORIGIN/../ABC/lib \
                (RUNPATH/RPATH from file /usr/local/XYZ/lib/libX.so.1)
      trying path=/usr/local/XYZ/lib/libY.so.1
        libY.so.1 =>     /usr/local/XYZ/lib/libY.so.1
 
  find object=libC.so.1; required by /usr/local/XYZ/lib/libX.so.1
     search path=$ORIGIN:$ORIGIN/../ABC/lib \
                (RUNPATH/RPATH from file /usr/local/XYZ/lib/libX.so.1)
      trying path=/usr/local/XYZ/lib/libC.so.1
      trying path=/usr/local/ABC/lib/libC.so.1
        libC.so.1 =>     /usr/local/ABC/lib/libC.so.1
 
  find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1
     search path=$ORIGIN  (RUNPATH/RPATH from file /usr/local/ABC/lib/libA.so.1)
       trying path=/usr/local/ABC/lib/libB.so.1
        libB.so.1 =>     /usr/local/ABC/lib/libB.so.1

注 - 在运行时,目标文件来源可以通过结合使用 dlinfo(3C)RTLD_DI_ORIGIN 标志来获取。该来源路径可用于访问关联的产品分层结构中的其他文件。


安全性

在安全的进程中,只有将 $ORIGIN 字符串扩展到可信目录时才允许对其进行扩展。出现其他相对路径名将产生安全风险。

$ORIGIN/../lib 之类的路径明显指向由可执行文件的位置决定的固定位置。但是,此位置实际上并不固定。相同文件系统上的可写入目录可能会利用使用 $ORIGIN 的安全程序。

以下示例显示,如果在安全进程中随意扩展 $ORIGIN,可能会发生这种安全违规。

$ cd /worldwritable/dir/in/same/fs
$ mkdir bin lib
$ ln $ORIGIN/bin/program bin/program
$ cp ~/crooked-libc.so.1 lib/libc.so.1
$ bin/program
.... using crooked-libc.so.1

可以使用实用程序 crle(1) 指定让安全应用程序能够使用 $ORIGIN 的可信目录。使用此技术的管理员应确保已对目标目录进行了适当的保护,以防受到恶意入侵。