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

退出打印视图

更新时间: 2014 年 7 月
 
 

位移重定位

如果将位移重定位应用于可以在复制重定位中使用的数据项,可能会出现错误状态。复制重定位中介绍了有关复制重定位的详细信息。

已重定位的偏移和重定位目标保持分隔相同的位移时,位移重定位仍然有效。复制重定位是指将共享目标文件中的全局数据项复制到可执行文件的 .bss 中。此复制将保留可执行文件的只读文本段。如果对复制的数据应用了位移重定位,或者外部重定位是对复制的数据进行位移,位移重定位将变为无效。

有两个验证领域会尝试确定位移重定位问题。

  • 第一个发生在生成共享目标文件时。对在复制的数据与位移重定位有关时可能产生问题的任何潜在复制可重定位数据项进行标记。在构造共享目标文件期间,链接编辑器无法确定可能会对数据项生成哪些外部引用。因此,只能标记潜在问题。

  • 第二个发生在生成可执行文件时。对其数据已知与位移重定位有关的复制重定位的创建进行标记。

    然而,在链接编辑时创建共享目标文件期间,可能会完成应用于共享目标文件的位移重定位。这些位移重定位可能不会有标记。因此,对引用未标记共享目标文件的可执行文件进行的链接编辑将无法确定任何已复制重定位数据中的有效位移。

为了帮助诊断这些问题,链接编辑器使用一个或多个动态 DT_FLAGS_1 标志指示动态目标文件使用的位移重定位,如Table 13–10 中所示。此外,可以使用链接编辑器的 –z verbose 选项显示可疑重定位。

例如,假设将创建具有全局数据项 bar[] 的共享目标文件,并且将对该数据项应用位移重定位。如果从动态可执行文件引用,那么此项可能已进行了复制重定位。链接编辑器使用以下内容对此情况提出警告。

$ cc -G -o libfoo.so.1 -z verbose -K pic foo.o
ld: warning: relocation warning: R_SPARC_DISP32: file foo.o: symbol foo: \
    displacement relocation to be applied to the symbol bar: at 0x194: \
    displacement relocation will be visible in output image

现在,如果创建一个引用数据项 bar[] 的应用程序,那么将创建复制重定位。此复制将导致位移重定位无效。由于链接编辑器可以清楚地发现此情况,所以不论是否使用 –z verbose 选项都将生成错误消息。

$ cc -o prog prog.o -L. -lfoo
ld: warning: relocation error: R_SPARC_DISP32: file foo.so: symbol foo: \
    displacement relocation applied to the symbol bar at: 0x194: \
    the symbol bar is a copy relocated symbol

注 -  ldd(1)–d–r 选项配合使用时,使用位移动态标志可生成类似的重定位警告。

通过确保要重定位(偏移)的符号定义和重定位的符号目标都是局部的,可以避免这些错误状态。使用静态定义或链接编辑器的作用域设置方法。请参见缩减符号作用域。通过使用功能接口访问共享目标文件中的数据可以避免此类型的重定位问题。