Bug 1688766

Summary: gcc: Linking against libgcc_s should imply linking with libgcc
Product: [Fedora] Fedora Reporter: Florian Weimer <fweimer>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 29CC: aoliva, davejohansen, dmalcolm, dominik, fweimer, jakub, jwakely, law, mpolacek, msebor, nickc, nicolas, sergio, tim
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: gcc-9.0.1-0.11.fc30 gcc-9.1.1-1.fc30 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-05-07 05:41:43 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Florian Weimer 2019-03-14 11:53:55 UTC
When a g++-compiled shared object is linked, __builtin_cpu_init and __builtin_cpu_supports result in undefined symbol errors __cpu_indicator_init, __cpu_model.

Reproducer:

static int
implementation_avx2 (void)
{
  return 1;
}

static int
implementation (void)
{
  return 0;
}

static __typeof__ (implementation) * resolver (void) __asm__ ("resolver");

static __typeof__ (implementation) *
resolver (void)
{
  __builtin_cpu_init ();
  if (__builtin_cpu_supports ("avx2"))
    return implementation_avx2;
  else
    return implementation;
}

int magic (void) __attribute__ ((ifunc ("resolver")));

Compile with:

g++ -O2 -fpic -shared

The assembler output contains a reference to __cpu_model:

resolver:
	subq	$8, %rsp
	call	__cpu_indicator_init
	movl	$_ZL19implementation_avx2v, %eax
	movl	$_ZL14implementationv, %edx
	testb	$4, __cpu_model+13(%rip)
	cmove	%rdx, %rax
	addq	$8, %rsp
	ret

__cpu_model is a compat symbol in libgcc_s.so.1 (with a single @ in the version):

$ eu-readelf -s /usr/lib64/libgcc_s.so.1  | grep cpu_model
  151: 000000000001a190     16 OBJECT  GLOBAL DEFAULT       27 __cpu_model.0

This means that the link editor will not use this symbol and leave it unversioned and undefined:

$ eu-readelf -s a.out | grep cpu_model
    3: 0000000000000000      0 NOTYPE  GLOBAL DEFAULT    UNDEF __cpu_model
   49: 0000000000000000      0 NOTYPE  GLOBAL DEFAULT    UNDEF __cpu_model

I think the expectation is that the definition from libgcc.a is used instead: A local definition has to be used because relocations in IFUNC resolvers are invalid.

But g++ does not link against libgcc.a.

gcc links against libgcc.a and does not have this problem:

$ eu-readelf -s a.out | grep cpu_model
   44: 0000000000004030     16 OBJECT  LOCAL  DEFAULT       22 __cpu_model

Comment 1 Florian Weimer 2019-03-14 11:54:19 UTC
Jakub said this on the upstream bug:

That is a Fedora/RHEL gcc.spec bug rather than upstream bug.
r222178 has added t-slibgcc-libgcc to i?86/x86_64, from the usual Fedora/RHEL targets also arm and powerpc* have that in libgcc/configure.host.
Fedora spec file reshuffles/changes lots of stuff, e.g. because I do not want the lib*.{so,a} files in /usr/lib{,64}/, but in gcc versioned directories, and does this (somewhat extended) libgcc_s.so stuff only for ppc (32-bit only) and arm:
%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
%ifarch ppc64 ppc64p7
rm -f $FULLPATH/32/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/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

The extension from upstream is in the OUTPUT_FORMAT, that helps linker to ignore it if it is looking for some other ABI.

So, clearly I need to add this also for ppc64 (64-bit), ppc64le, x86_64 (both 32-bit and 64-bit) and i?86.

Comment 2 Florian Weimer 2019-03-14 11:56:09 UTC
Maybe it's possible to use “ld --print-output-format” to avoid special-casing all these architectures?

Comment 4 Sergio Basto 2019-03-22 00:23:18 UTC
Build of libprojectM with gcc-9.0.1-0.11.fc31, on i686 seems fixed [1] Thanks

[1]
https://koji.fedoraproject.org/koji/buildinfo?buildID=1237679

Comment 5 Jakub Jelinek 2019-04-12 16:28:46 UTC
Fixed for FC30/31.

Comment 6 Sergio Basto 2019-04-23 21:56:18 UTC
Please update gcc in Fedora 30 the current version is 9.0.1-0.10.fc30 [1] and btw this bug still exist in F29 .  


[1]
https://copr-be.cloud.fedoraproject.org/results/sergiomb/builds_for_Stable_Releases/fedora-30-i386/00887045-libprojectM/
gcc                        i686   9.0.1-0.10.fc30

Comment 7 Sergio Basto 2019-05-01 03:31:15 UTC
and this only fixed on gcc-9.0.1-0.11.fc30

Reopen it , to not be lost

Comment 8 Fedora Update System 2019-05-04 13:01:14 UTC
gcc-9.1.1-1.fc30 has been submitted as an update to Fedora 30. https://bodhi.fedoraproject.org/updates/FEDORA-2019-007851f216

Comment 9 Fedora Update System 2019-05-05 00:53:55 UTC
gcc-9.1.1-1.fc30 has been pushed to the Fedora 30 testing repository. If problems still persist, please make note of it in this bug report.
See https://fedoraproject.org/wiki/QA:Updates_Testing for
instructions on how to install test updates.
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2019-007851f216

Comment 10 Nicolas Dufresne 2019-05-06 18:02:23 UTC
It looks like it's working for x86_64, but on aarch64 I still get an absolute link:

ls -l /srv/nfs/nicolas/rk3399/usr/lib/gcc/aarch64-redhat-linux/9/libgcc_s.so
lrwxrwxrwx 1 root root 20  3 mai 14:07 /srv/nfs/nicolas/rk3399/usr/lib/gcc/aarch64-redhat-linux/9/libgcc_s.so -> /lib64/libgcc_s.so.1

So as a rootfs for cross-build it breaks.

rpm -qf /usr/lib/gcc/aarch64-redhat-linux/9/libgcc_s.so
gcc-9.1.1-1.fc30.aarch64

Comment 11 Fedora Update System 2019-05-07 05:41:43 UTC
gcc-9.1.1-1.fc30 has been pushed to the Fedora 30 stable repository. If problems still persist, please make note of it in this bug report.