我们有一个旧的 powerpc-elf 工具链,可以正确创建 .elf 文件。
编译器已经有 20 多年的历史了,在 Solaris 上运行,所以也许是时候升级了。
我们可以将我们的应用程序移植到在 Windows 上运行的最新 gcc 交叉编译器上,但必须更改链接器脚本。一切都完美链接,但是当尝试在我们的专用操作系统上运行应用程序时,我们得到
Symbol _GLOBAL_OFFSET_TABLE_ not found.
经过一番研究,这个符号是由链接器在
.got
部分设置的。
在运行的应用程序上,符号定义为“A”(绝对)。
nm
命令的输出:
01b64dbc A _GLOBAL_OFFSET_TABLE_
在使用新工具链构建的应用程序上,也定义了该符号,但为“t”(本地)。
nm
命令的输出:
01addfa8 t _GLOBAL_OFFSET_TABLE_
这可能是问题所在,但现在的挑战是欺骗链接器将此
t
符号转换为 A
符号。
我尝试在链接器脚本的
.got
属性中添加一些内容
.got : {
_GLOBAL_OFFSET_TABLE_FOO = .+4; // I added that, +4 because it seems to be required to match
*(.got.plt)
*(.got)
现在
nm
输出:
01aecc34 t _GLOBAL_OFFSET_TABLE_
01aecc34 T _GLOBAL_OFFSET_TABLE_FOO
看起来不错,除了符号类型是
T
而不是 A
,并且名称错误。现在,一旦我删除 FOO
以匹配符号名称(使用 _GLOBAL_OFFSET_TABLE_ = .+4;
),我就会收到链接器错误:
_GLOBAL_OFFSET_TABLE_ not defined in linker created .got
final link failed: bad value
我想链接器不喜欢我尝试覆盖存在的符号。
那么我怎样才能将这个
t
类型“转换”为 A
对于这个特定的符号?
专有操作系统一定有错误不接受
_GLOBAL_SYMBOL_TABLE_
,就像它生成的那样。
解决方法是使符号全局化:
powerpc-elf-objcopy --globalize-symbol _GLOBAL_OFFSET_TABLE_ main.elf
现在
nm
输出:
01b64dbc T _GLOBAL_OFFSET_TABLE_