我使用的是 GCC 4.7.2开发工具集CentOS 5 上的软件包(CentOS 5 是因为我们需要与旧版 Linux 兼容,GCC 4.7 是因为它比 4.4 优化得更好)。
有一个符号阻止我的二进制文件在 RHEL4 上运行:__stack_chk_fail@GLIBC_2.4
。它仅包含在某些 C++ 程序中,并且该-fno-stack-protector
标志没有帮助。
这是重现问题的最小程序(但使用相同的stdio.h
方法):
#include <iostream>
int main(int argc, char *argv[]) {
for(int i=0; i < argc; i++)
std::cout << " " << argv[i];
return 0;
}
当使用优化 ( -O
/ -O2
) 编译时,它会引用__stack_chk_fail
。
$ g++ -fno-stack-protector -O2 foo.cc
$ readelf -s a.out | grep chk
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (5)
105: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2
知道为什么这个符号出现在这里以及如何摆脱它吗?
以防万一,完整readelf
输出并且gcc -v
是这里。
编辑:此问题可能特定于 Red Hat Developer Toolset 1.1。默认 CentOS 编译器__stack_chk_fail
不被引用。
答案1
这个符号来自libstdc++_nonshared.a
.
与发行版中的 GCC 不同,devtoolset 中的 GCC 具有 libstdc++ 的非共享部分。 GCC 4.7 中的 libstdc++.so 是一个链接器脚本,它使用 GCC 4.1 中的 libstdc++ 和静态链接的额外函数:
$ cat /opt/centos/devtoolset-1.1/root/usr/lib/gcc/i386-CentOS-linux/4.7.2/libstdc++.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
INPUT ( /usr/lib/libstdc++.so.6 -lstdc++_nonshared )
使用禁用的堆栈保护器重新编译后,libstdc++_nonshared.a
最终程序可以在 RHEL4 上运行。
答案2
它与 GLibC 一起提供。针对较旧的 GLibC 进行构建。
您可以告诉 GCC 4.7 发出优化的汇编代码,然后在旧系统上汇编和链接它