Description of problem: Linking a complex project with many shared objects failed with: /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld.gold: error: hidden symbol '_ZNSt12__sso_stringC1EPKcm' is not defined locally /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld.gold: error: hidden symbol '_ZNSt12__sso_stringC1EPKcm' is not defined locally I have boiled this down to a small reproduction. Version-Release number of selected component (if applicable): devtoolset-7-gcc-c++-7.2.1-1.el7.x86_64.rpm How reproducible: Every time. Steps to Reproduce: Run this reproduction script in a devtoolset-7 shell: --------- #!/bin/bash cat > bitset-user.cpp <<EOF #include <bitset> static std::bitset<1> bs; bool test_bit (size_t pos) { /* With DTS 7 this pulls in libstdc++_nonshared.a(sso_string.o), which * gives the sso string stuff default visibility. */ return bs.test(pos); } EOF cat > main.cpp <<EOF #include <bitset> #include <iostream> bool test_bit (size_t pos); int main () { test_bit(0); /* With DTS 7 this pulls in libstdc++_nonshared.a(system_error48.o), which * gives the sso string functions hidden visibility, overriding the default * visibility declared in sso_string.o. */ return bool(std::cout); } EOF GOLD="-fuse-ld=gold" #TRACE="-Wl,--trace" g++ $GOLD $TRACE -std=c++14 -shared -fPIC -o bitset-user.so bitset-user.cpp echo g++ $GOLD $TRACE -std=c++14 main.cpp bitset-user.so --------- Actual results: When using the gold linker it fails like: /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld.gold: error: hidden symbol '_ZNSt12__sso_stringC1EPKcm' is not defined locally /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld.gold: error: hidden symbol '_ZNSt12__sso_stringC1EPKcm' is not defined locally When using the binutils linker it fails like: /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a(cow-stdexcept.o): In function `std::__sso_string::__sso_string(std::string const&)': (.text._ZNSt12__sso_stringC2ERKSs+0x8): undefined reference to `std::__sso_string::__sso_string(char const*, unsigned long)' /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a(cow-stdexcept.o): In function `std::_V2::error_category::_M_message(int) const': (.text._ZNKSt3_V214error_category10_M_messageEi+0x30): undefined reference to `std::__sso_string::__sso_string(char const*, unsigned long)' /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: a.out: hidden symbol `_ZNSt12__sso_stringC2ERKS_' isn't defined /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: final link failed: Bad value collect2: error: ld returned 1 exit status Expected results: Should link with no errors. Works fine with DTS 4 and DTS 6. Additional info: Root cause seems to be that the sso string functions are declared to have default visiiblity in libstdc++_nonshared.a(sso_string.o) [and also libstdc++_nonshared.a(cow-stdexcept.o)] but hidden visibility in libstdc++_nonshared.a(system_error48.o). In DTS 6 there was a similar inconsistency, but the definition was "hidden" in system_error48.o (not sso_string.o as in DTS 7) which trumped the "default" declaration in cow-stdexcept.o every time. So despite the inconsistency, nothing broke.
In DTS 7.0, _ZNSt12__sso_stringC1EPKcm is defined in libstdc++_nonshared.a(sso_string.o), where it's GLOBAL DEFAULT. It is referenced in libstdc++_nonshared.a(cow-stdexcept.o) where it's GLOBAL DEFAULT. The symbol is also in libstdc++_nonshared.a(system_error48.o) where due to asm (".hidden _ZNSt12__sso_stringC1EPKcm"); it's GLOBAL HIDDEN. In the testcase, when creating bitset-user.so libstdc++_nonshared.a(sso_string.o) is pulled in, so the resulting bitset-user.so has GLOBAL DEFAULT _ZNSt12__sso_stringC1EPKcm. But then when linking "main.cpp bitset-user.so" these additional .o are pulled in: (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)ios-inst.o (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)ios.o (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)cxx11-ios_failure.o (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)cxx11-stdexcept.o (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)cow-stdexcept.o (/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a)system_error48.o But pulling in system_error48.o with the .hidden directive hides the _ZNSt12__sso_stringC1EPKcm symbol. In DTS 6.1 this does not happen because _ZNSt12__sso_stringC1EPKcm is defined in system_error48.o, where it's GLOBAL HIDDEN. It's only referenced in cow-stdexcept.o. When creating bitset-user.so, both cow-stdexcept.o and system_error48.o are pulled in. The resulting bitset-user.so has LOCAL DEFAULT _ZNSt12__sso_stringC1EPKcm. But when linking "main.cpp bitset-user.so", nothing that references that symbol is pulled in, so all is well.
I've distilled a C testcase: $ cat bar.c // system_error48.o. extern void foo (void); void baz (void) { foo (); } asm (".hidden foo"); $ cat foo.c // sso_string.o void foo (void) { __builtin_puts (__func__); } $ gcc -shared -fPIC -o libfoo.so foo.c $ gcc -c bar.c --save-temps $ ar crs libbar.a bar.o $ gcc main.c libfoo.so libbar.a -o r && LD_LIBRARY_PATH=. ./r
Since _ZNSt12__sso_stringC1EPKcm is no longer defined in system_error48.o asm (".hidden _ZNSt12__sso_stringC1EPKcm"); et al might be obsolete now?
Patch committed.
I encounter the similar error in the version 6.3.1-3.1.el7. Would it be fixed too ?
I encounter the similar problem in the version 7.2.1-1.el7.sc1. Would it be fixed too?
How to get devtoolset-7-gcc-7.2.1-6.el6? on RHN the lastest version is still devtoolset-7-gcc-7.2.1-1.el7.x86_64.rpm. Thanks!
@Marek Could you please attach the patch here? Thanks!
(In reply to Jiangdong Sun from comment #16) > @Marek Could you please attach the patch here? Thanks! This fix is currently scheduled for the next release of Red Hat Developer Toolset, v7.1, which will be announced when a public beta release is made available to Red Hat Enterprise Linux subscribers in the coming weeks. Red Hat engineering has concluded that earlier major releases of Red Hat Developer Toolset are not suitable to be patched for this issue and our recommendation to customers is to migrate projects to Red Hat Developer Toolset 7.1 where possible, on its release. We advise against customers patching and building their own binaries from patches as this produces unsupported toolchain binaries due to a number of differences in the build environment and dependencies.
@Matt Thanks for your reply. Hope the updated packages can be distributed early.
Tested with devtoolset-7-gcc-7.3.1-5.4, both linkers (where gold is available). Successfully reproduced with older DTS-7.0's detvoolset-7-gcc. VERIFIED.
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2018:1293