Note: shared libraries that use stb_image.h fail on Ubuntu 16.04 with "/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" #280

Closed
dankegel opened this Issue Apr 8, 2016 · 4 comments

Comments

Projects
None yet
4 participants
@dankegel

dankegel commented Apr 8, 2016

This is a doc issue at most, but worth noting because it may confuse some users.

Apps that use stb_image.h inside a shared library fail with Ubuntu 16.04 beta 2 (with gcc-5.3).
Symptom is the main executable fails to link to that shared library, with error
/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

A workaround is to link the shared library with -lgcc_s -lgcc.

To reproduce:

::::::::::::::
bug.sh
::::::::::::::

!/bin/sh

echo Demonstrate gotcha in __builtin_cpu_supports on Ubuntu 16.04 and rawhide / f24
echo See https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/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 -lm -o buglib.so
gcc bugapp.c buglib.so

echo Linking with g++ fails:
g++ -fPIC -shared buglib.c -lm -o buglib.so
g++ bugapp.c buglib.so

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

::::::::::::::
buglib.c
::::::::::::::

define STB_IMAGE_IMPLEMENTATION

include "stb_image.h"

::::::::::::::
bugapp.c
::::::::::::::

include <stdio.h>

include "stb_image.h"

int main(int argc, char **argv) {
int width, height, n;
stbi_load("foo.jpg", &width, &height, &n, 4);
}

@dankegel dankegel changed the title from Building app that uses stb_image.h fails on Ubuntu 16.04 with "/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" to Note: shared libraries that use stb_image.h fail on Ubuntu 16.04 with "/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" Apr 8, 2016

@dankegel

This comment has been minimized.

Show comment
Hide comment
@dankegel

dankegel Apr 11, 2016

When I say "not a bug", I mean "not a bug in stb".
It's probably a g++ bug.
I filed a simplified test case at https://bugs.launchpad.net/ubuntu/+source/gcc-5/+bug/1568899 as a first step. There should (already?) be a bug at gcc.gnu.org, too.

When I say "not a bug", I mean "not a bug in stb".
It's probably a g++ bug.
I filed a simplified test case at https://bugs.launchpad.net/ubuntu/+source/gcc-5/+bug/1568899 as a first step. There should (already?) be a bug at gcc.gnu.org, too.

@baldurk

This comment has been minimized.

Show comment
Hide comment
@baldurk

baldurk Sep 20, 2016

Contributor

FWIW since it doesn't seem like this will be fixed upstream by GCC any time soon, my solution to this was just to be slightly more conservative and avoid the use of __builtin_cpu_supports. x64 is guaranteed to have SSE2 and for my application people using x86 processors will be pretty rare or non-existant, so losing a little perf on SSE2-capable x86 processors is not a big problem.

I'm not suggesting this is a fix for upstream but I'm posting it here just in case it's useful for anyone else who wants a fix to commit that doesn't involve linking explicitly against libgcc:

diff --git a/renderdoc/3rdparty/stb/stb_image.h b/renderdoc/3rdparty/stb/stb_image.h
index 5ea802b..1292b24 100644
--- a/renderdoc/3rdparty/stb/stb_image.h
+++ b/renderdoc/3rdparty/stb/stb_image.h
@@ -712,12 +712,15 @@ static int stbi__sse2_available()

 static int stbi__sse2_available()
 {
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later
-   // GCC 4.8+ has a nice way to do this
-   return __builtin_cpu_supports("sse2");
+#if defined(STBI__X64_TARGET)
+   // on x64, SSE2 can be assumed to be available.
+   return 1;
 #else
-   // portable way to do this, preferably without using GCC inline ASM?
-   // just bail for now.
+   // __builtin_cpu_supports is buggy on GCC 5 and above, causing problems if
+   // referenced in a shared object, giving missing __cpu_model hidden symbol errors.
+   // To get around that, just assume that SSE2 is not available on x86.
+   //
+   // See https://github.com/nothings/stb/issues/280 for more information.
    return 0;
 #endif
 }
Contributor

baldurk commented Sep 20, 2016

FWIW since it doesn't seem like this will be fixed upstream by GCC any time soon, my solution to this was just to be slightly more conservative and avoid the use of __builtin_cpu_supports. x64 is guaranteed to have SSE2 and for my application people using x86 processors will be pretty rare or non-existant, so losing a little perf on SSE2-capable x86 processors is not a big problem.

I'm not suggesting this is a fix for upstream but I'm posting it here just in case it's useful for anyone else who wants a fix to commit that doesn't involve linking explicitly against libgcc:

diff --git a/renderdoc/3rdparty/stb/stb_image.h b/renderdoc/3rdparty/stb/stb_image.h
index 5ea802b..1292b24 100644
--- a/renderdoc/3rdparty/stb/stb_image.h
+++ b/renderdoc/3rdparty/stb/stb_image.h
@@ -712,12 +712,15 @@ static int stbi__sse2_available()

 static int stbi__sse2_available()
 {
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later
-   // GCC 4.8+ has a nice way to do this
-   return __builtin_cpu_supports("sse2");
+#if defined(STBI__X64_TARGET)
+   // on x64, SSE2 can be assumed to be available.
+   return 1;
 #else
-   // portable way to do this, preferably without using GCC inline ASM?
-   // just bail for now.
+   // __builtin_cpu_supports is buggy on GCC 5 and above, causing problems if
+   // referenced in a shared object, giving missing __cpu_model hidden symbol errors.
+   // To get around that, just assume that SSE2 is not available on x86.
+   //
+   // See https://github.com/nothings/stb/issues/280 for more information.
    return 0;
 #endif
 }
@nothings

This comment has been minimized.

Show comment
Hide comment
@nothings

nothings Dec 27, 2016

Owner

Anybody know what the status of the gcc bug is?

Owner

nothings commented Dec 27, 2016

Anybody know what the status of the gcc bug is?

redxdev pushed a commit to redxdev/imquery that referenced this issue Jan 25, 2017

redxdev pushed a commit to redxdev/imquery that referenced this issue Jan 26, 2017

Sam Bloomberg
move imq from a static library to a shared library (#38)
* move imq from a static library to a shared library

* enable -fPIC on linux

* pic

* bug in GCC 5 workaround, see nothings/stb#280

* update travis to use antlr shared library

@nothings nothings added the stb_image label Feb 12, 2017

pmp-p added a commit to pmp-p/panda3d that referenced this issue Mar 2, 2017

rygorous added a commit to rygorous/stb that referenced this issue Mar 5, 2017

stb_image: Give up trying to runtime-detect SSE2 on GCC.
We tried but it was nothing but trouble. New rule: with
GCC/Clang, if you're compiling with -msse2, you get always-on
SSE2 code, otherwise you don't get any. Trying to ship
anything with proper runtime dispatch requires both working
around certain bugs and some fiddling with build settings,
which runs contrary to the intent of a one-file library,
so bail on it entirely.

Fixes issue #280.
Fixes issue #410.
@rygorous

This comment has been minimized.

Show comment
Hide comment
@rygorous

rygorous Jun 28, 2017

Collaborator

Closing this, should be fixed.

Collaborator

rygorous commented Jun 28, 2017

Closing this, should be fixed.

@rygorous rygorous closed this Jun 28, 2017

@extrowerk extrowerk referenced this issue in haikuports/haikuports Jun 6, 2018

Closed

GCC / Gfortran broken #2651

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment