Bug 733549

Summary: gcc.spec clobbers libgcc_s.so linker script
Product: [Fedora] Fedora Reporter: Daniel Drake <dsd>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 14CC: jakub
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-10-03 15:41:09 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 245418    

Description Daniel Drake 2011-08-26 00:53:14 UTC
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!

Comment 1 Daniel Drake 2011-08-26 01:07:06 UTC
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 )

Comment 2 Jakub Jelinek 2011-08-26 09:02:02 UTC
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}.

Comment 3 Daniel Drake 2011-08-30 14:48:10 UTC
Thanks Jakub, I can confirm that fixes the issue.

Comment 4 Jakub Jelinek 2011-10-03 15:41:09 UTC
This is in -9, pushed now as errata.