New: unresolved symbols in libstdc++, shared lib link strategy of libgcc.a
7 answers - 3019 bytes -

These are two related problems. The most obvious one is that when building
libstdcso (don't mind the renaming, I want to isolate our gcc installation
from other tools that have their own libstdcso and set LD_LIBRARY_PATH,
because they are too stupid to use -rpath in their software) and I run
ldd -r -v /libstdcso I get these unresolved symbols:
symbol not found: _Unwind_Resume (/)
symbol not found: __ctzsi2 (/)
symbol not found: __eprintf (/)
symbol not found: __umoddi3 (/)
symbol not found: __udivdi3 (/)
symbol not found: _Unwind_DeleteException
(/)
symbol not found: _Unwind_GetTextRelBase
(/)
symbol not found: _Unwind_GetRegionStart
(/)
symbol not found: _Unwind_GetDataRelBase
(/)
symbol not found: _Unwind_SetGR (/)
symbol not found: _Unwind_SetIP (/)
symbol not found:
(/)
symbol not found: _Unwind_GetIP (/)
symbol not found: _Unwind_RaiseException
(/)
symbol not found: _Unwind_Resume_or_Rethrow
(/)
These symbols are obviously not part of libgcc_s.so, but some of them can be
found in:
nm / | ggrep
-E '_Unwind_|__ctzsi2|__eprintf|__umoddi3|__udivdi3'
[12] | 8| 228|FUNC |GLB |0 |5 |__ctzsi2
[14] | 8| 72|FUNC |GLB |0 |5 |__eprintf
[13] | 8| 916|FUNC |GLB |0 |5 |__udivdi3
[13] | 8| 948|FUNC |GLB |0 |5 |__umoddi3
and the _Unwind in libsupca. So far it is clear - but is this allowed? When
I build a C++ executable, which is linked against -lstdc++, how is this
executable supposed to find the missing symbols? My belief is up to now that a
shared object can only have unresolved symbols agaist other shared libs (which
it depends on) - but not against static ones.
The other (but related) problem is this: when I compile source code with
assert.h, I requently get errors at runtime that __eprintf is not found. This
does not happen when the executable is linked with gcc, since this passes
"-lgcc_s -lgcc" to the linker. But when building shared libraries (gcc
-shared), then only -lgcc_s is supplied (see the "specs" file:
%{static|static-libgcc:-lgcc
-lgcc_eh}%{!static:%{!static-libgcc:%{!shared:%{!shared-libgcc:-lgcc
-lgcc_eh}%{shared-libgcc:-lgcc_s-IFX -lgcc}}%{shared:-lgcc_s-IFX}}}
) and the shared lib has unresolved dependencies on __eprintf. So basically
this could be the root cause of the libstdc++ trouble above - wouldn't it be
correct to link shared libs with "-lgcc_s -lgcc" as well, to avoid that the
shared object will have the unresolved dependency on __eprintf?
I looked at Bug 15253 and Bug 15527, but that did not seem to give an answer to
the questions above.
Linux (RedHat Enterprise Linux 3.0) this looks totally different: All the
symbols above (__ctzsi2 __udivdi3 __umoddi3) are in libgcc_s.so, __eprintf is
in libgcc.a, and the libstdcso only has the unresolved symbols _Unwind_*,
but no others.
Let me know if you need more information.
-Marek
No.1 | | 224 bytes |
| 
Comment #1 from rguenth at gcc dot gnu dot org 2006-07-14 08:55
g++ links against libsupca and the required static parts of libgcc_s.
, a testcase would be nice because it is hard to see what exactly you
are doing.
No.2 | | 1456 bytes |
| 
Comment #2 from marek dot rouchal at infineon dot com 2006-07-14 09:08
The test case is the build of gcc 4.0.3 on Solaris 8, including the
libstdcso build. When done, run
env LD_LIBRARY_PATH=<path-where-libgcc_s.so-isldd -r -v /libstdcIFX.so
and you will see __eprintf unresolved.
I will try to put together a test case to build a shared lib from C source code
that contains #include <assert.hand some assertion to demonstrate the the
resulting libXXX.so has an unresolved reference to __eprintf.
more comment: The libstdc++ on Solaris does not have the RUNPATH compiled
in to find the libgcc_s.so, so that is why the _umoddi etc. symbols are not
found. So when running
env ldd -r -v
/
I only get the __eprintf unresolved symbol. So the difference between Solaris
and Linux is really that on Solaris there is __eprintf unresolved in
libstdcso.
And I noticed another difference: Solaris, my gcc is using the Solaris ld
linker, and the collect2 call contains (gcc -shared) only -lgcc_s,
whereas on Linux (where GNU ld is used) it contains:
-lgcc -lgcc_s-IFX -lc -lgcc -lgcc_s-IFX
so link first with the static libgcc.a, then with the shared gcc_s.
I failed to figure out where and how the link lib list is constructed within
gcc (i.e., how the collect2 command line is put together), so I do not know how
to compare that between Solaris and Linux.
-Marek
No.3 | | 765 bytes |
| 
Comment #3 from ebotcazou at gcc dot gnu dot org 2006-07-14 09:14
The test case is the build of gcc 4.0.3 on Solaris 8, including the
libstdcso build.
This is known to work, e.g.
env LD_LIBRARY_PATH=<path-where-libgcc_s.so-isldd -r -v /libstdcIFX.so
and you will see __eprintf unresolved.
I will try to put together a test case to build a shared lib from C source
code that contains #include <assert.hand some assertion to demonstrate the
the resulting libXXX.so has an unresolved reference to __eprintf.
This one is more annoying. You should make sure that you don't have an "old"
<assert.hlying around somewhere. Which compiler do you start from? Do you
bootstrap or only build the new compiler?
No.4 | | 587 bytes |
| 
Comment #4 from marek dot rouchal at infineon dot com 2006-07-14 11:03
I think I have found the root cause - there is indeed a
/usr/local/include/assert.h on my system. However, I was not aware that
/usr/local/include is being searched by default! So I will recompile
(bootstrap) gcc-4.0.3 again, and make sure that LCAL_INCLUDE_DIR is undefined
(if some user wants the &@#&$ in there, she can always add
-I/usr/local/include).
Please do not close this ticket now, I will update it with the outcome of the
new build. Stay tuned, and many thanks so far!
-Marek
No.5 | | 1192 bytes |
| 
Comment #5 from marek dot rouchal at infineon dot com 2006-07-14 14:01
, the compile is done. In gcc/Makefile.in, I changed
-DLCAL_INCLUDE_DIR=\"$(local_includedir)\" \
to
-ULCAL_INCLUDE_DIR \
so that /usr/local/include is NT searched by default by the preprocessor.
This way I do not source the evil assert.h in that path, and everything now
works smoothly - the __eprintf is gone from libstdcso, and I do not see this
popping up in any other compiles - as I do not search /usr/local/include any
more. So all is fine now.
Suggestions:
- make the assert.h/__eprintf trouble a FAQ:
"Whenever you see an unresolved symbol __eprintf, this most likely means that
you have an old and buggy assert.h in some of your include directories. Note
that cpp has some built-in search paths that you may need to consider as well,
like /usr/local/include"
- remove /usr/local/include from the standard include file search path; only
the _real_ standard locations for the platform (/usr/include) should be
considered, anything else should be up to the user - and it is easy
(-I/usr/local/include)
Thanks for your quick help,
Marek
No.6 | | 1193 bytes |
| 
Comment #6 from ebotcazou at gcc dot gnu dot org 2006-07-14 14:08
, the compile is done. In gcc/Makefile.in, I changed
-DLCAL_INCLUDE_DIR=\"$(local_includedir)\" \
to
-ULCAL_INCLUDE_DIR \
so that /usr/local/include is NT searched by default by the preprocessor.
The preferred method is to pass on the configure line.
Suggestions:
- make the assert.h/__eprintf trouble a FAQ:
"Whenever you see an unresolved symbol __eprintf, this most likely means that
you have an old and buggy assert.h in some of your include directories. Note
that cpp has some built-in search paths that you may need to consider as well,
like /usr/local/include"
I thought this was already documented somewhere, but may be not after all.
- remove /usr/local/include from the standard include file search path; only
the _real_ standard locations for the platform (/usr/include) should be
considered, anything else should be up to the user - and it is easy
(-I/usr/local/include)
I think this one has already be discussed at length. This is probably not
going to be changed since it can be overridden by
Thanks for reporting the final success.
No.7 | | 820 bytes |
| 
Comment #7 from marek dot rouchal at infineon dot com 2006-07-17 07:56
Subject: RE: unresolved symbols in libstdc++, shared lib link strategy of
libgcc.a
Using "something" may work ok, but what I
want is , and that does not work as I
expect (just tried with gcc-4.0.3); the expected behaviour would
be the one achieved with the patch below: no additional
"local" search directory for includes.
Thanks for your patience,
Marek
Comment #6 from ebotcazou at gcc dot gnu dot org
2006-07-14 14:08
, the compile is done. In gcc/Makefile.in, I changed
-DLCAL_INCLUDE_DIR=\"$(local_includedir)\" \
to
-ULCAL_INCLUDE_DIR \
so that /usr/local/include is NT searched by default by
the preprocessor.
The preferred method is to pass on the
configure line.