ld: a.out: hidden symbol `__cpu_model' in /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a(cpuinfo.o) is referenced by DSO

Bug #1568899 reported by Dan Kegel
42
This bug affects 9 people
Affects Status Importance Assigned to Milestone
gcc
Fix Released
Medium
gcc-5 (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

On Ubuntu 16.04 beta 2, there is a regression in
g++ 4:5.3.1-1ubuntu1
g++ (Ubuntu 5.3.1-13ubuntu3) 5.3.1 20160330
relative to Ubuntu 15.10 and before.
This came to light while compiling an app that uses stb_image.h, see
https://github.com/nothings/stb/issues/280

In
https://<email address hidden>/thread/ZM2L65WIZEEQHHLFERZYD5FAG7QY2OGB/
Jakub Jelinek suggested a workaround (add -lgcc_s -lgcc at the end of the g++ command that links the shared library)
and a real fix
"on ppc32 I remember libgcc_s.so is a linker script which links in -lgcc_s -lgcc, perhaps we need it on x86_64/i686 too".
His workaround helped me.
I don't know if a gcc has been filed yet; I couldn't find one, but at least Jakub is aware of the problem.

To reproduce, use __builtin_cpu_supports from a shared library, and link with g++.
Example:

::::::::::::::
bugapp.c
::::::::::::::
#include <stdio.h>
extern int foo();

int main(int argc, char **argv) {
    printf("foo is %d\n", foo());
}
::::::::::::::
buglib.c
::::::::::::::
int foo(void) {
    return __builtin_cpu_supports("sse2");
}
::::::::::::::
bug.sh
::::::::::::::
#!/bin/sh
set -x
echo Demonstrate gotcha in __builtin_cpu_supports on Ubuntu 16.04 and rawhide / f24
echo See https://<email address hidden>/thread/ZM2L65WIZEEQHHLFERZYD5FAG7QY2OGB/
echo Maybe caused by https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61309

echo Linking with gcc works:
gcc -fPIC -shared buglib.c -o buglib.so
gcc bugapp.c buglib.so

echo Linking with g++ fails:
g++ -fPIC -shared buglib.c -o buglib.so
g++ bugapp.c buglib.so
# /usr/bin/ld: a.out: hidden symbol `__cpu_model' in /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a(cpuinfo.o) is referenced by DSO
# /usr/bin/ld: final link failed: Bad value
# collect2: error: ld returned 1 exit status
g++ --version

echo Rescue by linking libgcc explicitly into shared library:
g++ -fPIC -shared buglib.c -lgcc_s -lgcc -o buglib.so
g++ bugapp.c buglib.so

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

On Linux/x86, r221732 gave

FAIL: g++.dg/ext/mv14.C -std=gnu++11 execution test
FAIL: g++.dg/ext/mv14.C -std=gnu++14 execution test
FAIL: g++.dg/ext/mv14.C -std=gnu++98 execution test
FAIL: g++.dg/ext/mv15.C -std=gnu++11 execution test
FAIL: g++.dg/ext/mv15.C -std=gnu++14 execution test
FAIL: g++.dg/ext/mv15.C -std=gnu++98 execution test
FAIL: g++.dg/ext/mv1.C -std=gnu++11 execution test
FAIL: g++.dg/ext/mv1.C -std=gnu++14 execution test
FAIL: g++.dg/ext/mv1.C -std=gnu++98 execution test

when compiled with -fPIE -pie.

Revision history for this message
In , Ubizjak (ubizjak) wrote :

I don't think the compiler is at fault here.

Tracing the executable, I got:

Breakpoint 1, 0x0000555555554780 in __cpu_indicator_init@plt ()
(gdb) disass
Dump of assembler code for function __cpu_indicator_init@plt:
=> 0x0000555555554780 <+0>: jmpq *0x2018ba(%rip) # 0x555555756040 <email address hidden>
   0x0000555555554786 <+6>: pushq $0x4
   0x000055555555478b <+11>: jmpq 0x555555554720
End of assembler dump.
(gdb) p/x *0x555555756040
$1 = 0x786

(gdb) si
0x0000000000000786 in ?? ()

Some kind of fixup is missing for <email address hidden> value.

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

(gdb) bt
#0 0x0000000000000706 in ?? ()
#1 0x0000555555554b69 in foo ()
    at /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/ext/mv1.C:32
#2 0x00007ffff7de76b8 in _dl_relocate_object ()
   from /lib64/ld-linux-x86-64.so.2
#3 0x00007ffff7ddea4a in dl_main () from /lib64/ld-linux-x86-64.so.2
#4 0x00007ffff7df28d5 in _dl_sysdep_start () from /lib64/ld-linux-x86-64.so.2
#5 0x00007ffff7ddfce1 in _dl_start () from /lib64/ld-linux-x86-64.so.2
#6 0x00007ffff7ddbcd8 in _start () from /lib64/ld-linux-x86-64.so.2
#7 0x0000000000000001 in ?? ()
#8 0x00007fffffffe18d in ?? ()
#9 0x0000000000000000 in ?? ()
(gdb) f 1
#1 0x0000555555554b69 in foo ()
    at /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/ext/mv1.C:32
32 int (*p)() = &foo;
(gdb) disass
Dump of assembler code for function _Z3foov.resolver(void):
   0x0000555555554b60 <+0>: sub $0x8,%rsp
   0x0000555555554b64 <+4>: callq 0x555555554700 <__cpu_indicator_init@plt>
=> 0x0000555555554b69 <+9>: mov 0x200740(%rip),%rsi # 0x5555557552b0
   0x0000555555554b70 <+16>: mov 0xc(%rsi),%edx
   0x0000555555554b73 <+19>: mov %edx,%eax
   0x0000555555554b75 <+21>: mov %edx,%ecx
   0x0000555555554b77 <+23>: and $0x400,%eax
   0x0000555555554b7c <+28>: and $0x40,%ecx
   0x0000555555554b7f <+31>: cmp %ecx,%eax
   0x0000555555554b81 <+33>: cmovg %ecx,%eax
   0x0000555555554b84 <+36>: test %eax,%eax
   0x0000555555554b86 <+38>: jle 0x555555554b98 <_Z3foov.resolver(void)+56>
   0x0000555555554b88 <+40>: lea -0xbf(%rip),%rax # 0x555555554ad0 <_Z3foov.avx2_ssse3>
   0x0000555555554b8f <+47>: add $0x8,%rsp
   0x0000555555554b93 <+51>: retq
   0x0000555555554b94 <+52>: nopl 0x0(%rax)
   0x0000555555554b98 <+56>: cmpl $0x8,0x8(%rsi)
   0x0000555555554b9c <+60>: jne 0x555555554bb0 <_Z3foov.resolver(void)+80---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) disass 0x0000555555554700,+16
Dump of assembler code from 0x555555554700 to 0x555555554710:
   0x0000555555554700 <__cpu_indicator_init@plt+0>: jmpq *0x200be2(%rip) # 0x5555557552e8 <email address hidden>
   0x0000555555554706 <__cpu_indicator_init@plt+6>: pushq $0x2
   0x000055555555470b <__cpu_indicator_init@plt+11>: jmpq 0x5555555546c0
End of assembler dump.
(gdb)

We can't call __cpu_indicator_init in PIE while PIE is being relocated.
Its .got.plt section hasn't been updated. It works for non-PIE since
no update on .got.plt section is required. Can we move __cpu_indicator_init
to main executable?

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

Created attachment 35173
A patch to move __cpu_indicator_init

This patch is incomplete. We need to handle backward compatibility
as well as versioned functions in shared library.

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

Created attachment 35175
A patch to add __cpu_indicator_init to libgcc.a

This patch adds _cpu_indicator_init to libgcc.a and hides
it from linker with backward binary compatibility.

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

Created attachment 35176
A testcase with DSO

[hjl@gnu-tools-1 pr65612]$ make
g++ -O2 -c -o main.o main.cc
g++ -shared -fPIC -O2 -o libmv20.so mv20.cc
g++ -O2 -o x main.o libmv20.so -Wl,-R,.
./x
Makefile:8: recipe for target 'all' failed
make: *** [all] Segmentation fault (core dumped)
[hjl@gnu-tools-1 pr65612]$

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :
Revision history for this message
In , Hjl-0 (hjl-0) wrote :

Author: hjl
Date: Fri Apr 17 12:58:07 2015
New Revision: 222178

URL: https://gcc.gnu.org/viewcvs?rev=222178&root=gcc&view=rev
Log:
Hide __cpu_indicator_init/__cpu_model from linker

We shouldn't call external function, __cpu_indicator_init, while an object
is being relocated since its .got.plt section hasn't been updated. It
works for non-PIE since no update on .got.plt section is required. This
patch creates libgcc.so as a linker script, hides __cpu_indicator_init
and __cpu_model in libgcc.so.1 from linker, forces linker to resolve
__cpu_indicator_init and __cpu_model to their hidden definitions in
libgcc.a while providing backward binary compatibility.

gcc/testsuite/

 PR target/65612
 * g++.dg/ext/mv18.C: New test.
 * g++.dg/ext/mv19.C: Likewise.
 * g++.dg/ext/mv20.C: Likewise.
 * g++.dg/ext/mv21.C: Likewise.
 * g++.dg/ext/mv22.C: Likewise.
 * g++.dg/ext/mv23.C: Likewise.

libgcc/

 PR target/65612
 * config.host (tmake_file): Add t-slibgcc-libgcc for Linux/x86.
 * config/i386/cpuinfo.c (__cpu_model): Initialize.
 (__cpu_indicator_init@GCC_4.8.0): New.
 (__cpu_model@GCC_4.8.0): Likewise.
 * config/i386/t-linux (HOST_LIBGCC2_CFLAGS): Add
 -DUSE_ELF_SYMVER.

Added:
    trunk/gcc/testsuite/g++.dg/ext/mv18.C
    trunk/gcc/testsuite/g++.dg/ext/mv19.C
    trunk/gcc/testsuite/g++.dg/ext/mv20.C
    trunk/gcc/testsuite/g++.dg/ext/mv21.C
    trunk/gcc/testsuite/g++.dg/ext/mv22.C
    trunk/gcc/testsuite/g++.dg/ext/mv23.C
Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/libgcc/ChangeLog
    trunk/libgcc/config.host
    trunk/libgcc/config/i386/cpuinfo.c
    trunk/libgcc/config/i386/t-linux

Revision history for this message
In , Hjl-tools (hjl-tools) wrote :

Fixed for 6.0.

Revision history for this message
Matthias Klose (doko) wrote :

fixed upstream. however it looks like backporting this patch to the gcc-5-branch will add a dependency on new symbols, which are not found on other GCC 5 builds.

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in gcc-5 (Ubuntu):
status: New → Confirmed
Revision history for this message
Valentin Crone (va-crone) wrote :

I want to compile my library (using SFML), all works on Ubuntu 14.04 LTS, but on Ubuntu 16.04 LTS (after recompile all libs) I have this bug.

Note that: If you use versions compiled on Ubuntu 14.04 and try to run it, it works.
If you use versions compiled on Ubuntu 14.04 to compile a new executable, it fail (with many errors of linking in libstdc++)
If you recompile all your libs for Ubuntu 16.04 and compile a new executable, the libs will be built but for the executable, you will have this bug.

Please, fix this, it's a problem again to recompile our code on this new distribution....
Thank you

Revision history for this message
David Yip (dwyip-1) wrote :

I too have encountered this problem when updating build images to use Ubuntu 16.04. The build images are used to build an application built on SFML.

I have been able to work around the problem with a privately patched clone of SFML that incorporates Jakub Jelinek's and Dan Kegel's suggestions (see http://web.archive.org/web/20160509014317/https://gitlab.peach-bun.com/pinion/SFML/commit/3383b4a472f0bd16a8161fb8760cd3e6333f1782.patch for a patch against SFML 2.3.2), but maintaining a private clone is overhead that I'd prefer to eliminate.

Revision history for this message
Gerry Boland (gerboland) wrote :

Ditto, hit me compiling the Ogre 3d engine. Resorted to above workaround

Revision history for this message
Derek (dereklesho52) wrote :

Same problem, there is a patch I found that fixes an issue with SFML, so I need to recompile it, but I get this error. I have tried both g++ 5.4 and g++ 6.2

Revision history for this message
KFJ (kfj) wrote :

Same problem here compiling recent checkout of SFML

patch above fixed the problem

Changed in gcc:
importance: Unknown → Medium
status: Unknown → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.