链接程序和库指南

重定位处理

创建了输出文件后,将输入文件中的所有数据节复制到新的映像。将输入文件指定的所有重定位应用于输出映像。还要将必须生成的所有其他重定位信息写入新的映像。

重定位处理通常很容易,但可能会出现错误状态并伴随有特定错误消息。有两种状态需要进行详细地论述。第一种状态涉及位置相关代码产生的文本重定位。与位置无关的代码中对此状态进行了更详细的说明。第二种状态可以由位移重定位产生,下一小节中将对位移重定位进行更全面的说明。

位移重定位

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

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

尝试捕获这些类型的错误时要解决的问题包括:

为了帮助诊断这些问题,链接编辑器使用一个或多个动态 DT_FLAGS_1 标志指示动态库使用的位移重定位,如表 7–34 中所示。此外,可以使用链接编辑器的 -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 选项配合使用时,使用位移动态标志可生成类似的重定位警告。


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