Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
755 views
in Technique[技术] by (71.8m points)

c - Moving to different Linux build system, getting error: undefined symbol: stat

This may just be an issue with the build system I am migrating to, but I'll include differences in the two systems and how I encountered the problem.

My old build system is a SLES 10 machine. The gcc/cpp/g++ version is 4.1.0

My new system is on SLES 11 SP4, and the gcc/cpp/g++ version is 4.3.4.

I am building a shared library; building and linking work fine on the new system. However, at load time on the new system, I get the following:

error ./mysharedlib.so: undefined symbol: stat

Since the stat() function is included from /usr/include/sys/stat.h, I looked at glibc on both systems. Old:

# rpm -q -f /usr/include/sys/stat.h
glibc-devel-2.4-31.2

and new:

# rpm -q -f /usr/include/sys/stat.h
glibc-devel-2.11.3-17.95.2

I also looked at objdump output related to stat() on the old system:

# 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

And the new system:

# 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

This tells me that on the old system, stat() was defined as a local function in the .text section of my actual shared object. Stat is undefined in mysharedlib on the new system.

I did find some information on feature_test_macros and thought that might resolve the issue, so I included features.h before stat.h and updated my makefile to define _XOPEN_SOURCE:

cc -D_XOPEN_SOURCE=500  

This didn't resolve the problem.

I also tried adding "-lc" to my ld flags to link in libc. This seemed like it should work, since that's where stat() is defined(I think), but it did not.

At this point, I found this StackOverflow question:

Why does -O to gcc cause "stat" to resolve?

So I tried adding -O to my makefile when invoking g++ on the file that calls stat(). This seems to resolve the problem. I probably don't know enough about resolving symbols; however, this seems a bit hack-ish to me. Am I way off base there? If not, what's the correct way to resolve the load time error on the new system?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem you are facing is most likely the result of building your shared library with ld. User-level code on UNIX systems should never use ld directly. You should use the compiler driver (g++ in your case) to perform the link instead.

Example:

// 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

Compare to correctly linked library:

gcc -shared -o t.so t.o
nm t.so | grep stat

0000000000000700 t stat
0000000000000700 t __stat
                 U __xstat@@GLIBC_2.2.5

To find where the above local stat symbol came from, you could do this:

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

Finally, the reason U stat disappears with optimization:

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

That's right: you get different preprocessed source depending on the optimization level.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...