Bug 733549 - gcc.spec clobbers libgcc_s.so linker script
Summary: gcc.spec clobbers libgcc_s.so linker script
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 14
Hardware: Unspecified
OS: Unspecified
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
Depends On:
Blocks: ARMTracker
TreeView+ depends on / blocked
Reported: 2011-08-26 00:53 UTC by Daniel Drake
Modified: 2011-10-03 15:41 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2011-10-03 15:41:09 UTC
Type: ---

Attachments (Terms of Use)

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:

  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.  */
  GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so

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
 GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/32/libgcc_s.so
+%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.  */
+GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so
 mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.spec $FULLPATH/
@@ -2454,6 +2462,8 @@ fi
+- put libgcc.a into libgcc_s.so linker script also on arm (#733549)
 * Wed Aug 24 2011 Jakub Jelinek <jakub@redhat.com> 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.

Note You need to log in before you can comment on or make changes to this bug.