使用直接绑定的目标文件维护符号引用与提供定义的依赖项之间的关系。运行时链接程序使用该信息直接在关联目标文件中搜索符号,而不执行缺省符号搜索模型。
动态目标文件的直接绑定信息是在链接编辑时记录的。只能为通过该目标文件的链接编辑指定的依赖项建立该信息。可使用 -z defs 选项来确保所有必需的依赖项都提供为链接编辑的一部分。
使用直接绑定的目标文件可以与不使用直接绑定的目标文件共存于同一进程中。那些不使用直接绑定的目标文件将使用缺省的符号搜索模型。
可以使用下列链接编辑机制之一来建立符号引用到符号定义的直接绑定。
使用 -B direct 选项。此选项可在要生成的目标文件与所有目标文件依赖项之间建立直接绑定。此选项还可在要生成的目标文件中的任何符号引用与符号定义之间建立直接绑定。
使用 -B direct 选项还会启用延迟装载。该启用行为等效于在链接编辑命令行的前面添加 -z lazyload 选项。延迟装入动态依赖项中介绍了该属性。
使用 -z direct 选项。此选项可在要生成的目标文件与命令行中该选项之后的任何依赖项之间建立直接绑定。可将此选项与 -z nodirect 选项配合使用,以切换依赖项之间直接绑定的使用。此选项不在要生成的目标文件中的任何符号引用与符号定义之间建立直接绑定。
使用 DIRECT mapfile 关键字。此关键字用于直接绑定各个符号。SYMBOL_SCOPE / SYMBOL_VERSION 指令中描述了此关键字。
以下几节介绍了每种直接绑定机制的使用方法。
-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.2 到 W.so.2 的直接绑定产生的效果与使用 -B symbolic 选项生成 W.so.2 时产生的效果类似。不过,-B symbolic 选项能够在链接编辑时完成可以内部解析的引用(例如 a())。该符号解析不会将任何绑定留到运行时进行解析。
与 -B symbolic 绑定不同,-B direct 绑定留到运行时进行解析。因此,可以使用显式插入覆盖该绑定,或者通过将环境变量 LD_NODIRECT 的值设置为一个非空值来禁用该绑定。
符号绑定通常用来降低在装入复杂目标文件时产生的运行时重定位开销。直接绑定可用来建立完全相同的符号绑定。不过,在创建每个直接绑定时仍然需要进行运行时重定向。直接绑定需要的开销比符号绑定大,但能够提供更强的灵活性。
-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 关键字提供了一种为各个符号建立直接绑定的方法。该机制用于特定的链接编辑情况。
在之前示例使用的组件中,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.2 和 X.so.1 的相同直接绑定。本示例的目的只是为了说明如何使用 mapfile 关键字。