We are facing various build issues on ARM, where we are hit with errors like: /usr/bin/ld: bin/makeconv: hidden symbol `__sync_val_compare_and_swap_4' in /usr/lib/gcc/armv5tel-redhat-linux-gnueabi/4.5.1/libgcc.a(linux-atomic.o) is referenced by DSO /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: ld returned 1 exit status Bug #733162 is one such case; we have since found others e.g. java. Time to fix this properly! This happens when compiling code that uses GCCs atomic builtin, using g++ (hence linking against libstdc++). Trivial test case: https://bugzilla.redhat.com/attachment.cgi?id=519738 The problem is that the static libgcc is not linked in such a situation. The atomic functions are only provided by the static libgcc, not the shared one. This matches exactly an old discussion I found: http://gcc.gnu.org/ml/gcc/2009-05/msg00039.html But there is one further complication. C++ shared libraries are linked with -shared-libgcc by default. The __sync_* functions on ARM and PA are in static libgcc only (and it looks like those on SH are always hidden, so effectively also static-only). So you can't actually link a C++ shared library that uses these functions. I consider this a compiler bug; even with -shared-libgcc I think the compiler needs to link with the static libgcc, after the shared one, so that undefined references to static-libgcc-only functions such as these can be resolved. That problem was fixed with http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40134 which solves the issue by replacing libgcc_s.so with a linker script to link in libgcc.a as well. However, gcc.spec does the following: mkdir -p %{buildroot}/%{_lib} mv -f %{buildroot}%{_prefix}/%{_lib}/libgcc_s.so.1 %{buildroot}/%{_lib}/libgcc_s-%{gcc_version}-%{DATE}.so.1 chmod 755 %{buildroot}/%{_lib}/libgcc_s-%{gcc_version}-%{DATE}.so.1 ln -sf libgcc_s-%{gcc_version}-%{DATE}.so.1 %{buildroot}/%{_lib}/libgcc_s.so.1 ln -sf /%{_lib}/libgcc_s.so.1 $FULLPATH/libgcc_s.so The final line pasted above causes the libgcc_s.so linker script that is installed by PR40134's resolution to be clobbered - it is replaced with a symbolic link, the linker script itself is lost. A few lines further down, this happens: %ifarch ppc rm -f $FULLPATH/libgcc_s.so echo '/* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf32-powerpc) GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so %endif That is exactly the linker script that was installed in the ARM case, but the above code only triggers for ppc. Could the above ppc code be made to trigger on ARM, or could the spec file be adjusted somehow to not clobber the linker script? Thanks for your help!
Actually, the linker script installed for ARM is slightly different to the one pasted above. I'm guessing the OUTPUT_FORMAT above line applying on ARM wouldn't bring good results. Here is the linker script installed for ARM by vanilla gcc: /* GNU ld script Use the shared library, but some functions are only in the static library. */ GROUP ( libgcc_s.so.1 libgcc.a )
diff --git a/gcc.spec b/gcc.spec index fb843e4..79d7022 100644 --- a/gcc.spec +++ b/gcc.spec @@ -1149,6 +1149,14 @@ echo '/* GNU ld script OUTPUT_FORMAT(elf32-powerpc) GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/32/libgcc_s.so %endif +%ifarch %{arm} +rm -f $FULLPATH/libgcc_s.so +echo '/* GNU ld script + Use the shared library, but some functions are only in + the static library, so try that secondarily. */ +OUTPUT_FORMAT(elf32-littlearm) +GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so +%endif mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.spec $FULLPATH/ @@ -2454,6 +2462,8 @@ fi %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_version}/plugin %changelog +- put libgcc.a into libgcc_s.so linker script also on arm (#733549) + * Wed Aug 24 2011 Jakub Jelinek <jakub> 4.6.1-8 - update from the 4.6 branch - PRs c++/46862, c++/48993, c++/49669, c++/49921, c++/49988, c++/50024, queued for next gcc build (gcc-4.6.1-9.{fc15,fc16}.
Thanks Jakub, I can confirm that fixes the issue.
This is in -9, pushed now as errata.