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

退出打印视图

更新时间: 2014 年 7 月
 
 

定义显式插入

缺省搜索模型可能会导致同名符号的实例插入到同名的后续实例上。即使没有任何显式标签,仍然会发生插入,以便从所有引用绑定到同一个符号定义。发生该隐式插入是符号搜索的结果,而不是因为向运行时链接程序发出了任何显式指令。使用直接绑定可以禁用该隐式插入。

虽然直接绑定能够将符号引用直接解析到关联的符号定义,但是显式插入是在任何直接绑定搜索之前处理的。因此,即使是在直接绑定环境内,也可以对插入项进行设计并预期它在任意直接绑定关联上进行插入。可以使用下列技术显式定义插入项。

  • 使用 LD_PRELOAD 环境变量。

  • 使用链接编辑器 –z interpose 选项。

  • 使用 INTERPOSE mapfile 关键字。

  • singleton 符号定义产生的结果。

LD_PRELOAD 环境变量的插入功能和 –z interpose 选项已经使用了一段时间。请参见运行时插入。因为这些目标文件是显式定义为插入项的,因此运行时链接程序将在处理任何直接绑定之前检查这些目标文件。

为一个共享目标文件建立的插入将应用于该动态目标文件的所有接口。系统使用 LD_PRELOAD 环境变量装入目标文件时,会建立该目标文件插入。在装入已使用 –z interpose 选项生成的目标文件时,也会建立目标文件插入。当使用具有特殊句柄 RTLD_NEXTdlsym(3C) 等技术时,该目标文件模型很重要。插入目标文件应始终具有下一个目标文件的一致视图。

动态可执行文件具有额外的灵活性,因为该可执行文件可以使用 INTERPOSE mapfile 关键字定义单个插入符号。因为动态可执行文件是进程中装入的第一个目标文件,所以可执行文件的下一个目标文件视图始终是一致的。

以下示例显示了要显式插入到 exit() 函数的应用程序。

$ cat mapfile
$mapfile_version 2
SYMBOL_SCOPE {
        global:
                exit    { FLAGS = INTERPOSE };
};
$ cc -o prog -M mapfile exit.c a.c b.c ....
$ elfdump -y prog | fgrep exit
[6]  DI          <self>         exit

字母 "I" 表示该符号是插入符号。实现此 exit() 函数可以直接引用系统函数 _exit(),也可以使用带有 RTLD_NEXT 句柄的 dlsym() 调用系统函数 exit()

最初,您可能考虑使用 –z interpose 选项识别此目标文件。但是,此技术的开销相当大,因为应用程序导出的所有接口都将用作插入项。较好的替代方法是,结合使用 –z interpose 选项将应用程序提供的所有符号(插入项除外)本地化。

但是,使用 INTERPOSE mapfile 关键字会提供更大的灵活性。通过使用此关键字,应用程序可以导出多个接口,同时选择应当用作插入项的接口。

指定了 STV_SINGLETON 可见性的符号可以有效地提供一种插入形式。请参见Table 12–23。编译系统可将这些符号指定给一个实现,该实现可能会在进程内的多个目标文件中多次实例化。所有的单件符号引用都绑定到进程中第一次出现的单件符号。