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.  直接绑定

观察符号绑定

启用直接绑定

使用 -B direct 选项

使用 -z direct 选项

使用 DIRECT mapfile 关键字

直接绑定和插入

本地化符号实例

删除多次定义的同名符号

定义显式插入

阻止直接绑定到某个符号

使用 -B nodirect 选项

使用 NODIRECT mapfile 关键字

10.  Mapfile

11.  可扩展性机制

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

12.  目标文件格式

13.  程序装入和动态链接

14.  线程局部存储

第 5 部分附录

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

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

索引

启用直接绑定

使用直接绑定的目标文件维护符号引用与提供定义的依赖项之间的关系。运行时链接程序使用该信息直接在关联目标文件中搜索符号,而不执行缺省符号搜索模型。

动态目标文件的直接绑定信息是在链接编辑时记录的。只能为通过该目标文件的链接编辑指定的依赖项建立该信息。可使用 -z defs 选项来确保所有必需的依赖项都提供为链接编辑的一部分。

使用直接绑定的目标文件可以与不使用直接绑定的目标文件共存于同一进程中。那些不使用直接绑定的目标文件将使用缺省的符号搜索模型。

可以使用下列链接编辑机制之一来建立符号引用到符号定义的直接绑定。


注 - 通过将环境变量 LD_NODIRECT 设置为非空值,可在运行时禁用直接绑定。通过设置该环境变量,进程内的所有符号绑定都将通过缺省搜索模型来执行。


以下几节介绍了每种直接绑定机制的使用方法。

使用 -B direct 选项

-B direct 选项提供了为任何动态目标文件启用直接绑定的最简单机制。此选项可在要生成的目标文件内建立到任何依赖项的直接绑定。

从前面的示例中使用的组件,可以生成一个直接绑定的目标文件 W.so.2

$ cc -o W.so.2 -G -Kpic W.c -R. -Bdirect w.so.1
$ cc -o prog2 -R. main.c W.so.2 X.so.1

直接绑定信息是在 W.so.2 中的符号信息部分 .SUNW_syminfo 中维护的。可以使用 elfdump(1) 查看该部分。

$ elfdump -y W.so.2
    [6]  DB          <self>         a
    [7]  DBL     [1] w.so.1         b

字母 "DB" 表示已经为关联符号记录了直接绑定 (direct binding)。函数 a() 已绑定到包含目标文件 W.so.2。函数 b() 已直接绑定到依赖项 w.so.1。字母 "L" 表示依赖项 w.so.1 也应当延迟装载。

可以使用 LD_DEBUG 环境变量观察为 W.so.2 建立的直接绑定。detail 标记用于向绑定诊断信息添加额外的信息。对于 W.so.2,该标记指明绑定是直接绑定这一特性。detail 标记还提供有关绑定地址的额外信息。为简化起见,在以下示例生成的输出中已省略了该地址信息。

$ LD_DEBUG=symbols,bindings,detail prog2
.....
18452: symbol=a;  lookup in file=./W.so.2  [ ELF ]
18452: binding file=./W.so.2 to file=./W.so.2: symbol `a'  (direct)
18452: symbol=b;  lookup in file=./w.so.1  [ ELF ]
18452: binding file=./W.so.2 to file=./w.so.1: symbol `b'  (direct)

lari(1) 实用程序也可以揭示直接绑定信息。

$ lari prog2
[2:2ESD]: a(): ./W.so.2
[2:0]: a(): ./X.so.1
[2:2ED]: b(): ./w.so.1
[2:0]: b(): ./x.so.1

字母 "D" 表示由 W.so.2 定义的函数 a() 已被直接绑定。同样,在 w.so.1 中定义的函数 b() 也已被直接绑定。


注 - 对于函数a()W.so.2W.so.2 的直接绑定产生的效果与使用 -B symbolic 选项生成 W.so.2 时产生的效果类似。不过,-B symbolic 选项能够在链接编辑时完成可以内部解析的引用(例如 a())。该符号解析不会将任何绑定留到运行时进行解析。

-B symbolic 绑定不同,-B direct 绑定留到运行时进行解析。因此,可以使用显式插入覆盖该绑定,或者通过将环境变量 LD_NODIRECT 的值设置为一个非空值来禁用该绑定。

符号绑定通常用来降低在装入复杂目标文件时产生的运行时重定位开销。直接绑定可用来建立完全相同的符号绑定。不过,在创建每个直接绑定时仍然需要进行运行时重定向。直接绑定需要的开销比符号绑定大,但能够提供更强的灵活性。


使用 -z direct 选项

-z direct 选项提供的机制用来建立与链接编辑命令行中该选项后的所有依赖项的直接绑定。与 -B direct 选项不同,这不会在将要生成的目标文件内建立直接绑定。

此选项适用于生成作为插入基础的目标文件。例如,共享目标文件有时会设计包含许多缺省或回退接口。应用程序可以本着在运行时将应用程序定义绑定到这些接口的目的,自由地定义这些接口的定义。要允许应用程序插入到共享目标文件的接口,请使用 -z direct 选项而不是 -B direct 选项来生成共享目标文件。

如果您希望有选择地直接绑定到一个或多个依赖项,-z direct 选项也比较有用。-z nodirect 选项用于在通过链接编辑提供的依赖项之间切换直接绑定的使用。

从之前示例中使用的组件,可以生成一个直接绑定的目标文件 X.so.2

$ cc -o X.so.2 -G -Kpic X.c -R. -zdirect x.so.1
$ cc -o prog3 -R. main.c W.so.2 X.so.2

可以通过 elfdump(1) 查看直接绑定信息。

$ elfdump -y X.so.2
    [6]  D           <self>         a
    [7]  DB      [1] x.so.1         b

函数 b() 已直接绑定到依赖项 x.so.1。函数 a() 被定义为与目标文件 X.so.2 之间有一个可能的直接绑定 "D",但没有建立直接绑定。

可以使用 LD_DEBUG 环境变量来观察运行时绑定。

$ LD_DEBUG=symbols,bindings,detail prog3
.....
06177: symbol=a;  lookup in file=prog3  [ ELF ]
06177: symbol=a;  lookup in file=./W.so.2  [ ELF ]
06177: binding file=./X.so.2 to file=./W.so.2: symbol `a'
06177: symbol=b;  lookup in file=./x.so.1  [ ELF ]
06177: binding file=./X.so.2 to file=./x.so.1: symbol `b'  (direct)

lari(1) 实用程序也可以揭示直接绑定信息。

$ lari prog3
[2:2ESD]: a(): ./W.so.2
[2:0]: a(): ./X.so.2
[2:1ED]: b(): ./w.so.1
[2:1ED]: b(): ./x.so.1

W.so.2 定义的函数 a() 继续服务于 X.so.2 执行的缺省符号引用。但是,在 x.so.1 中定义的函数 b() 已被从 X.so.2 执行的引用直接绑定。

使用 DIRECT mapfile 关键字

DIRECT mapfile 关键字提供了一种为各个符号建立直接绑定的方法。该机制用于特定的链接编辑情况。

在之前示例使用的组件中,main() 函数引用了外部函数 W()X()。这些函数的绑定遵循缺省的搜索模型。

$ LD_DEBUG=symbols,bindings prog3
.....
18754: symbol=W;  lookup in file=prog3  [ ELF ]
18754: symbol=W;  lookup in file=./W.so.2  [ ELF ]
18754: binding file=prog3 to file=./W.so.2: symbol `W'
.....
18754: symbol=X;  lookup in file=prog3  [ ELF ]
18754: symbol=X;  lookup in file=./W.so.2  [ ELF ]
18754: symbol=X;  lookup in file=./X.so.2  [ ELF ]
18754: binding file=prog3 to file=./X.so.2: symbol `X'

可以使用 DIRECT mapfile 关键字来重新生成 prog3,以便建立到函数 W()X() 的直接绑定。

$ cat mapfile
$mapfile_version 2
SYMBOL_SCOPE {
        global:
                W       { FLAGS = EXTERN DIRECT };
                X       { FLAGS = EXTERN DIRECT };
};
$ cc -o prog4 -R. main.c W.so.2 X.so.2 -Mmapfile

可以使用 LD_DEBUG 环境变量来观察运行时绑定。

$ LD_DEBUG=symbols,bindings,detail prog4
.....
23432: symbol=W;  lookup in file=./W.so.2  [ ELF ]
23432: binding file=prog4 to file=./W.so.2: symbol `W'  (direct)
23432: symbol=X;  lookup in file=./X.so.2  [ ELF ]
23432: binding file=prog4 to file=./x.so.2: symbol `X'  (direct)

lari(1) 实用程序也可以揭示直接绑定信息。然而,在本例中没有多次定义 W()X() 函数。因此,缺省情况下,lari 不会发现这些函数受关注。必须使用 -a 选项才能显示所有符号信息。

$ lari -a prog4
....
[1:1ED]: W(): ./W.so.2
.....
[2:1ED]: X(): ./X.so.2
.....

注 - 通过使用 -B direct 选项或 -z direct 选项生成 prog4,可以生成到 W.so.2X.so.1 的相同直接绑定。本示例的目的只是为了说明如何使用 mapfile 关键字。