nothings / stb

stb single-file public domain libraries for C/C++

Home Page:https://twitter.com/nothings

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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"

dankegel opened this issue · comments

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);
}

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.

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
 }

Anybody know what the status of the gcc bug is?

Closing this, should be fixed.