I know my problem is an old question but, even searching with google,
I've not resolved yet.
I'm trying to compile an application with gcc 3.1, have all gcc
libraries and headers as well as binutils.
Now compilation break out with : libaudiofile.so.0: undefined reference
to `__eprintf'
I know that __eprintf is in libgcc.a as shown with a simple `nm
libgcc.a|grep eprintf" but how can I tell gcc that symbol is in libgcc.a
? I've tried to pass -lgcc as option but... it doesn't seem to work.
Have any idea ?
byez
darko
--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG
> I'm trying to compile an application with gcc 3.1, have all gcc
> libraries and headers as well as binutils.
> Now compilation break out with : libaudiofile.so.0: undefined reference
> to `__eprintf'
>
> I know that __eprintf is in libgcc.a as shown with a simple `nm
> libgcc.a|grep eprintf" but how can I tell gcc that symbol is in libgcc.a
> ? I've tried to pass -lgcc as option but... it doesn't seem to work.
Probably libaudiofile.so.0 was compiled with an old version of gcc
(2.95.x ?) that does not build proper self contained shared libraries.
Recompile libaudiofile.so.0 with gcc 3.1
And make sure "libtool" uses "gcc -shared" to build shared libraries;
for some strange reason it prefers to call "ld" directly with results
in "broken" shared libraries.
The shared library dependacies for a gcc compiled libaudiofile should
look like this (note the libgcc_s.so.1 line):
% ldd /opt/gnome12/lib/libaudiofile.so
libm.so.1 => /usr/lib/libm.so.1
libc.so.1 => /usr/lib/libc.so.1
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1
libdl.so.1 => /usr/lib/libdl.so.1
> Probably libaudiofile.so.0 was compiled with an old version of gcc
> (2.95.x ?) that does not build proper self contained shared libraries.
Could you explain the problem?
> And make sure "libtool" uses "gcc -shared" to build shared libraries;
> for some strange reason it prefers to call "ld" directly with results
> in "broken" shared libraries.
Libtool sucks.
--
.-. .-. I don't work here. I'm a consultant.
(_ \ / _)
| da...@willfork.com
|
> Juergen Keil wrote:
>
> > Probably libaudiofile.so.0 was compiled with an old version of gcc
Btw: The OP emailed me that this libaudiofile.so.0 is the one from the
Solaris companion CD, /opt/sfw/lib/libaudiofile.so
> > (2.95.x ?) that does not build proper self contained shared libraries.
>
> Could you explain the problem?
I just unpacked a fresh copy of audiofile-0.1.9 I've downloaded some
time ago and ran "configure" & "make". I have the "Software
Companion" CD installed and the configure script picks up the
"gcc-2.95.3" compiler from /opt/sfw/bin.
The shared library is built with this command:
/bin/sh ../libtool --mode=link gcc -Wall -g -o libaudiofile.la
-rpath /usr/local/lib audiofile.lo error.lo write.lo bread.lo
bwrite.lo byteorder.lo util.lo aupv.lo aes.lo instrument.lo loop.lo
marker.lo misc.lo track.lo query.lo compression.lo aiff.lo
aiffwrite.lo extended.lo au.lo auwrite.lo wave.lo wavewrite.lo
ulaw.lo g711.lo af_vfs.lo -lm
which expands to
/usr/ccs/bin/ld -G -h libaudiofile.so.0 -o
.libs/libaudiofile.so.0.0.0 audiofile.lo error.lo write.lo bread.lo
bwrite.lo byteorder.lo util.lo aupv.lo aes.lo instrument.lo loop.lo
marker.lo misc.lo track.lo query.lo compression.lo aiff.lo
aiffwrite.lo extended.lo au.lo auwrite.lo wave.lo wavewrite.lo
ulaw.lo g711.lo af_vfs.lo -lm -lc
Something inside libaudiofile is using assert() which calls the
external subroutine __eprintf() when the code is compiled with gcc.
__eprintf is defined in libgcc but libaudiofile.so is not linked
against it.
libaudiofile.so is not self contained. There are cases when you
cannot use this library because the needed __eprintf() is not there:
__________
Example 1: You compile a program with Sun's Forte C (which uses a
different mechanism for asserts and does not offer the __eprintf()
subroutine). Result is, you cannot build a program with Forte C that
uses the above libaudiofile.so (e.g. the one in /opt/sfw/lib)
% cat > main.c
main(){}
% cc -o main main.c -L/opt/sfw/lib -R/opt/sfw/lib -laudiofile
Undefined first referenced
symbol in file
__eprintf /opt/sfw/lib/libaudiofile.so
ld: fatal: Symbol referencing errors. No output written to main
% gcc -o main main.c -L/opt/sfw/lib -R/opt/sfw/lib -laudiofile
[
With the self contained libaudiofile I compiled using gcc-3.XX and a
hacked "libtool" this is not a problem, because the version of
libaudiofile.so I compiled knows where it can find the missing
__eprintf():
% cc -o main main.c -L/opt/gnome12/lib -R/opt/gnome12/lib -laudiofile
% ldd main
libaudiofile.so.0 => /opt/gnome12/lib/libaudiofile.so.0
libc.so.1 => /usr/lib/libc.so.1
libm.so.1 => /usr/lib/libm.so.1
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1
libdl.so.1 => /usr/lib/libdl.so.1
/usr/platform/SUNW,Ultra-60/lib/libc_psr.so.1
% env LD_BIND_NOW=YES main
%
]
__________
Example 2: The unresolved __eprintf in libaudiofile.so can even be a
problem for code compiled with gcc 2.95! In this second example a gcc
compiled program which does not use assert uses dlopen to dynamically
load the libaudiofile.so shared library. It does not work:
% cat dyn.c
#include <dlfcn.h>
main()
{
char *lib = "/opt/sfw/lib/libaudiofile.so";
void *lib_handle;
lib_handle = dlopen(lib, RTLD_NOW);
if (!lib_handle) {
printf("cannot open %s: %s\n", lib, dlerror());
}
}
% gcc -o dyn dyn.c -ldl
% nm -p dyn|grep eprintf
% dyn
cannot open /opt/sfw/lib/libaudiofile.so: ld.so.1: dyn: fatal: relocation
error: file /opt/sfw/lib/libaudiofile.so: symbol __eprintf: referenced
symbol not found
[ again, this is not a problem with my libaudiofile.so which was
compiled with gcc-3.x and linked against gcc-3.x's libgcc_s.so ]
__________
You can try to build shared libraries on solaris with gcc-2.95.x by
linking the library using the static (!) version of libgcc.a - for
example by using "gcc -shared -o libXXX.so ....". Problem is, gcc-2.95
has no shared library version of the gcc support library libgcc (this
was added starting with gcc-3.0). And linking the shared library against
the static libgcc.a can cause other problems:
- it might add non-position-independant code from libgcc.a to the
shared library
- with multiple "gcc -shared" compiled shared libraries you'll get
multiple versions of the same code from libgcc.a pulled into a process
- If you build a hierarchy of shared libraries, compiled with gcc 2.95
and linked with the static libgcc.a it gets messy with shared libs
pulling stuff from libgcc.a and re-exporting them as a global symbols.
Example 3: Lets consider a program "main" linked against shared lib
"lib2". Shared library "lib2" itself uses stuff from another shared
lib, "lib1".
main -> lib2 -> lib1
% cat lib1.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void lib1(void)
{
assert(malloc(1));
printf("hello, world\n");
}
% gcc -fPIC -shared -o liblib1.so lib1.c
% nm -p liblib1.so | grep eprintf
0000001424 T __eprintf
% cat lib2.c
#include <stdlib.h>
#include <assert.h>
void lib2(void)
{
assert(malloc(2));
lib1();
}
% gcc -fPIC -shared -o liblib2.so lib2.c -L. -R. -llib1
% nm -p liblib2.so|grep eprintf
0000000000 U __eprintf
Note how lib1.so has pulled __eprintf from libgcc.a, but the linker
has left __eprintf as an undefined reference in lib2 because it was
satisfied by dynamically linking it to the __eprintf symbol from
lib1!
% cat main.c
int main(int argc, char **argv)
{
lib2();
}
% cc -o main main.c -L. -R. -llib2
"main.c", line 3: warning: implicit function declaration: lib2
% env LD_BIND_NOW=1 main
hello, world
OK, upto now. Forte "cc" compiled program can use "gcc" shared libs.
Now recompile lib1 using a different compiler:
% cc -KPIC -G -o liblib1.so lib1.c
% env LD_BIND_NOW=1 main
ld.so.1: main: fatal: relocation error: file ./liblib2.so: symbol
__eprintf: referenced symbol not found Killed
Program does not work any more.
____________________
All of these problems can be avoided by using gcc-3.0 or newer and
building shared libraries compiled with gcc with "gcc -shared", dynmically
linking them to the new libgcc_s.so
> > And make sure "libtool" uses "gcc -shared" to build shared libraries;
> > for some strange reason it prefers to call "ld" directly with results
> > in "broken" shared libraries.
>
> Libtool sucks.
Yes.
To work around some problem with shared libraries built from C++ code
when no shared libstdc++ is available, the libtool guys decided to run
the system linker /usr/ccs/bin/ld directly.
In my opinion this causes more problems than it solves: shared library
initialization code does not work, and stuff from the libgcc support
library remains undefined. And the C++ shared library problem with
libstdc++ - which triggered the use of the linker instead of the
compiler - can be avoided by installing the shared library version of
libstdc++.so
I've used something like the following change to work around these
problems caused by libtool, when building shared libraries on solaris
(note: I've not checked the ``archive_expsym_cmds'' stuff, it probably
needs to use $CC instead of $LD, too)
% gdiff -u ltconfig-orig ltconfig
--- ltconfig-orig Tue Sep 21 00:05:02 1999
+++ ltconfig Fri Jun 14 11:47:17 2002
@@ -1295,9 +1295,11 @@
solaris*)
no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ if test "$with_gcc" = yes; then
+ archive_cmds='$CC -shared${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ else
+ archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ fi
archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
$LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
hardcode_libdir_flag_spec='-R$libdir'
> > Could you explain the problem?
> The shared library is built with this command:
>
> /bin/sh ../libtool --mode=link gcc -Wall -g -o libaudiofile.la
> -rpath /usr/local/lib audiofile.lo error.lo write.lo bread.lo
> bwrite.lo byteorder.lo util.lo aupv.lo aes.lo instrument.lo loop.lo
> marker.lo misc.lo track.lo query.lo compression.lo aiff.lo
> aiffwrite.lo extended.lo au.lo auwrite.lo wave.lo wavewrite.lo
> ulaw.lo g711.lo af_vfs.lo -lm
>
> which expands to
>
> /usr/ccs/bin/ld -G -h libaudiofile.so.0 -o
> .libs/libaudiofile.so.0.0.0 audiofile.lo error.lo write.lo bread.lo
> bwrite.lo byteorder.lo util.lo aupv.lo aes.lo instrument.lo loop.lo
> marker.lo misc.lo track.lo query.lo compression.lo aiff.lo
> aiffwrite.lo extended.lo au.lo auwrite.lo wave.lo wavewrite.lo
> ulaw.lo g711.lo af_vfs.lo -lm -lc
[...]
> Example 1:
[...]
> Example 2:
[...]
I knew about those things, but they happen because libtool decided to
drive ld directly in an extremely stupid way, not because gcc is buggy.
With gcc one is supposed to use -shared (-G is buggy, at least on 2.95.x)
and those things should not happen.
> And linking the shared library against the static libgcc.a can cause
> other problems:
>
> - it might add non-position-independant code from libgcc.a to the
> shared library
I don't think so. I've just tried:
gcc -shared -o libgcc.so -Wl,-zallextract \
/usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/libgcc.a \
-Wl,-zdefaultextract
and "dump -Lv libgcc.so | grep TEXTREL" doesn't return anything, ie. the
archive contains PIC code.
> - with multiple "gcc -shared" compiled shared libraries you'll get
> multiple versions of the same code from libgcc.a pulled into a process
Technically yes, but everything will use the same version.
> - If you build a hierarchy of shared libraries, compiled with gcc 2.95
> and linked with the static libgcc.a it gets messy with shared libs
> pulling stuff from libgcc.a and re-exporting them as a global symbols.
>
> Example 3: Lets consider a program "main" linked against shared lib
> "lib2". Shared library "lib2" itself uses stuff from another shared
> lib, "lib1".
[...]
> % nm -p liblib2.so|grep eprintf
> 0000000000 U __eprintf
>
> Note how lib1.so has pulled __eprintf from libgcc.a, but the linker
> has left __eprintf as an undefined reference in lib2 because it was
> satisfied by dynamically linking it to the __eprintf symbol from
> lib1!
Yes, that's a genuine problem.
[...]
> Program does not work any more.
Yep, that's what follows.
> All of these problems can be avoided by using gcc-3.0 or newer and
> building shared libraries compiled with gcc with "gcc -shared", dynmically
> linking them to the new libgcc_s.so
Well, I haven't been using gcc for anything serious for years, so my
experience has a few holes, but wouldn't it be possible to create libgcc.so
from libgcc.a and then use the shared version? In theory, at least.
> To work around some problem with shared libraries built from C++ code
> when no shared libstdc++ is available, the libtool guys decided to run
> the system linker /usr/ccs/bin/ld directly.
That's the reason? Amazing.
> I've used something like the following change to work around these
> problems caused by libtool, when building shared libraries on solaris
> (note: I've not checked the ``archive_expsym_cmds'' stuff, it probably
> needs to use $CC instead of $LD, too)
I've been using LD=cc (Sun's cc) in environment and that made me happier, but
it wasn't enough to prevent linking everything by hand after libtool did
whatever it does.