这可能只是我迁移到的构建系统的一个问题,但我将在两个系统中包含差异以及我是如何遇到问题的。
我的旧构建系统是SLES 10机器。 gcc / cpp / g ++版本是4.1.0
我的新系统在SLES 11 SP4上,gcc / cpp / g ++版本是4.3.4。
我正在构建一个共享库;建立和连接新系统的工作正常。但是,在新系统的加载时间,我得到以下内容:
error ./mysharedlib.so: undefined symbol: stat
由于stat()函数包含在/usr/include/sys/stat.h中,我在两个系统上查看了glibc。老:
# rpm -q -f /usr/include/sys/stat.h
glibc-devel-2.4-31.2
和新:
# rpm -q -f /usr/include/sys/stat.h
glibc-devel-2.11.3-17.95.2
我还查看了旧系统上与stat()相关的objdump输出:
# objdump -T mysharedlib.so | grep stat
0000000000000000 D *UND* 0000000000000000 __xstat
# objdump -x mysharedlib.so | grep stat
00000000000e3f8a l F .text 0000000000000024 stat
0000000000000000 *UND* 0000000000000000 __xstat
新系统:
# objdump -T mysharedlib.so | grep stat
0000000000000000 D *UND* 0000000000000000 stat
0000000000000000 D *UND* 0000000000000000 lstat
# objdump -x mysharedlib.so | grep stat
0000000000000000 *UND* 0000000000000000 stat
0000000000000000 *UND* 0000000000000000 lstat
这告诉我在旧系统上,stat()被定义为我实际共享对象的.text部分中的本地函数。在新系统的mysharedlib中未定义Stat。
我确实找到了一些关于feature_test_macros的信息,并认为可以解决这个问题,所以我在stat.h之前包含了features.h并更新了我的makefile来定义_XOPEN_SOURCE:
cc -D_XOPEN_SOURCE=500
这并没有解决问题。
我也尝试将“-lc”添加到我的ld标志中以链接到libc。这似乎应该可以工作,因为那是定义stat()的地方(我认为),但事实并非如此。
此时,我发现了这个StackOverflow问题:
Why does -O to gcc cause "stat" to resolve?
所以当我在调用stat()的文件上调用g ++时,我尝试将-O添加到我的makefile中。这似乎解决了这个问题。我可能对解析符号知之甚少;然而,这对我来说似乎有些黑客攻击。我离开基地了吗?如果没有,解决新系统上的加载时间错误的正确方法是什么?
答案 0 :(得分:6)
您遇到的问题很可能是使用ld
构建共享库的结果。 UNIX系统上的用户级代码应永远不直接使用ld
。您应该使用编译器驱动程序(在您的情况下为g++
)来代替执行链接。
示例:
// t.c
#include <sys/stat.h>
void fn(const char *p)
{
struct stat st;
stat(p, &st);
}
gcc -fPIC -c t.c
ld -shared -o t.so t.o
nm t.so | grep stat
U stat ## problem: this library is not linked correctly
与正确链接的库比较:
gcc -shared -o t.so t.o
nm t.so | grep stat
0000000000000700 t stat
0000000000000700 t __stat
U __xstat@@GLIBC_2.2.5
要查找上述本地stat
符号的来源,您可以执行以下操作:
gcc -shared -o t.so t.o -Wl,-y,stat
t.o: reference to stat
/usr/lib/x86_64-linux-gnu/libc_nonshared.a(stat.oS): definition of stat
最后,U stat
因优化而消失的原因是:
gcc -E t.c | grep -A2 ' stat '
extern int stat (const char *__restrict __file,
struct stat *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
gcc -E t.c -O | grep -A2 ' stat '
__attribute__ ((__nothrow__ , __leaf__)) stat (const char *__path, struct stat *__statbuf)
{
return __xstat (1, __path, __statbuf);
没错:根据优化级别,您会得到不同的预处理来源。