Bug 1519073
| Summary: | Cannot link shared object that uses std::bitset with code that does bool(std::basic_ios). hidden symbol '_ZNSt12__sso_stringC1EPKcm' is not defined. | ||
|---|---|---|---|
| Product: | Red Hat Developer Toolset | Reporter: | John Steele Scott <toojays> | 
| Component: | gcc | Assignee: | Marek Polacek <mpolacek> | 
| Status: | CLOSED ERRATA | QA Contact: | Michael Petlan <mpetlan> | 
| Severity: | unspecified | Docs Contact: | Vladimír Slávik <vslavik> | 
| Priority: | unspecified | ||
| Version: | DTS 7.0 RHEL 7 | CC: | alanm, bgollahe, darrin, fweimer, jakub, kanderso, law, mcermak, mnewsome, ohudlick, sunjdong, thomas, vslavik, zhengzhejun19891021 | 
| Target Milestone: | alpha | ||
| Target Release: | 7.1 | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | |||
| Fixed In Version: | devtoolset-7-gcc-7.2.1-6.el6 | Doc Type: | Bug Fix | 
| Doc Text: | Previously, some symbols in the "libstdc++_nonshared.a" static library file used incorrect visibility. As a consequence, linking some C++ programs failed. This bug has been fixed and no longer occurs. | Story Points: | --- | 
| Clone Of: | Environment: | ||
| Last Closed: | 2018-05-03 05:13:47 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: | |||
| 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 | 
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.