转到不同的Linux构建系统,得到错误:未定义的符号:stat

时间:2017-05-31 20:32:12

标签: c linux gcc glibc libc

这可能只是我迁移到的构建系统的一个问题,但我将在两个系统中包含差异以及我是如何遇到问题的。

我的旧构建系统是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中。这似乎解决了这个问题。我可能对解析符号知之甚少;然而,这对我来说似乎有些黑客攻击。我离开基地了吗?如果没有,解决新系统上的加载时间错误的正确方法是什么?

1 个答案:

答案 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);

没错:根据优化级别,您会得到不同的预处理来源。