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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With