Created attachment 7342 [details] output of `cave info` I'm using gentoo w/ my custom compilation flags. I've found that simple program being compiled and linked w/ gold segfaults w/ the following backtrace: Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () (gdb) bt #0 0x0000000000000000 in ?? () #1 0x00007ffff7f2a1e1 in __gthread_once (__func=0x7ffff7f2a180 <std::locale::_S_initialize_once()>, __once=<optimized out>) at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:699 #2 std::locale::_S_initialize () at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/gcc-4.8.2/libstdc++-v3/src/c++98/locale_init.cc:276 #3 0x00007ffff7f2a223 in std::locale::locale (this=0x7ffff7fbffb8 <__gnu_internal::buf_cout_sync+56>) at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/gcc-4.8.2/libstdc++-v3/src/c++98/locale_init.cc:210 #4 0x00007ffff7f2710c in basic_streambuf (this=<optimized out>) at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/streambuf:466 #5 stdio_sync_filebuf (__f=0x7ffff7dd62a0 <_IO_2_1_stdout_>, this=<optimized out>) at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/ext/stdio_sync_filebuf.h:77 #6 std::ios_base::Init::Init (this=<optimized out>) at /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/gcc-4.8.2/libstdc++-v3/src/c++98/ios_init.cc:85 #7 0x0000000000400dce in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/include/g++-v4/iostream:74 #8 _GLOBAL__sub_I_main () at print_exports.cc:33 #9 0x0000000000400f2d in __libc_csu_init (argc=argc@entry=1, argv=argv@entry=0x7fffffffcc98, envp=0x7fffffffcca8) at elf-init.c:83 #10 0x00007ffff7a55905 in __libc_start_main (main=0x400be0 <main()>, argc=1, ubp_av=0x7fffffffcc98, init=0x400ee0 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffcc88) at libc-start.c:217 #11 0x0000000000400e11 in _start () at ../sysdeps/x86_64/start.S:123 the source code is: #include <string> #include <iostream> extern char ** environ; int main() { for (char ** it = environ; nullptr != *it; ++it) { std::string str(*it); std::cout << "export " << str.substr(0, str.find('=')) << std::endl; } } compile commands: x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -minline-stringops-dynamically -mtls-dialect=gnu2 -floop-block -floop-interchange -ftree-loop-distribution -floop-strip-mine -ftree-vectorize -fmerge-all-constants -fira-loop-pressure -pedantic -c -o print_exports.o print_exports.cc x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -minline-stringops-dynamically -mtls-dialect=gnu2 -floop-block -floop-interchange -ftree-loop-distribution -floop-strip-mine -ftree-vectorize -fmerge-all-constants -fira-loop-pressure -pedantic -Wl,-O1 -Wl,--sort-common -Wl,--enable-new-dtags -Wl,--gc-sections -Wl,--hash-style=gnu -o print_exports print_exports.o -Wl,--as-needed -pthread -Wl,-fuse-ld=gold GCC info: /home/zaufi〉 g++ -v Using built-in specs. COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.2/g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.2/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /storage/tmp/paludis/sys-devel-gcc-4.8.2/work/gcc-4.8.2/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.2 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/include/g++-v4 --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.8.2/python --enable-languages=c,c++ --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --disable-nls --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.8.2 p1.2, pie-0.5.8' --enable-libstdcxx-time --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-altivec --disable-fixed-point --enable-targets=all --disable-libgcj --enable-libgomp --enable-libmudflap --disable-libssp --disable-libquadmath --enable-lto --with-cloog --disable-isl-version-check Thread model: posix gcc version 4.8.2 (Gentoo 4.8.2 p1.2, pie-0.5.8)
I tried compiling with a 4.9.0 compiler, but my copy doesn't have the -floop-* options implemented. Compiling without those options does not reproduce the problem. Can you attach your .o file?
Created attachment 7358 [details] compiled object file
I investigated this bug a more further and this is only triggered when gold is used in combination with -Wl,--as-needed. I'm on Exherbo and will attach cave info. Anyway, take a look: x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -pedantic -c -o print_exports.o print_exports.cc x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -pedantic -o print_exports print_exports.o -Wl,--as-needed -pthread -Wl,-fuse-ld=gold ./print_exports -->(segfault) x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -pedantic -o print_exports print_exports.o -Wl,--as-needed -pthread -Wl,-fuse-ld=bfd ./print_exports --> works x86_64-pc-linux-gnu-g++ -pthread -std=gnu++0x -pedantic -ggdb -O2 -pipe -march=native -pedantic -o print_exports print_exports.o -pthread -Wl,-fuse-ld=gold (Pay attention... as-needed is missing here) ./print_exports --> works
Created attachment 7472 [details] cave info
Maybe this is useful too g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.2/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /var/tmp/paludis/build/sys-devel-gcc-4.8.2-r2/work/gcc-4.8.2/configure --prefix=/usr --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --disable-silent-rules --enable-fast-install --libdir=/usr/lib64 --cache-file=config.cache --libdir=/usr/lib64 --with-pkgversion='exherbo gcc-4.8.2-r2' --program-suffix=-4.8 --disable-bootstrap --enable-clocale=gnu --enable-languages=c,c++,fortran --enable-lto --enable-multilib --enable-nls --enable-serial-configure --enable-libquadmath --enable-libquadmath-support --with-cloog --enable-libgomp --disable-libobjc --disable-libssp --with-as=x86_64-pc-linux-gnu-as --with-ld=x86_64-pc-linux-gnu-ld --with-system-zlib Thread model: posix gcc version 4.8.2 (exherbo gcc-4.8.2-r2)
markus@x4 tmp % cat print_exports.ii static __typeof 0 a __attribute__ ((__weakref__ ("__pthread_key_create"))); void *b = &a; namespace std { class A { public: A (void *); }; class ios_base { public: class Init { public: Init (); }; }; ios_base::Init c; } int main () { for (int d; 0;) std::A e (&d); } markus@x4 tmp % g++ -pthread -O2 print_exports.ii -Wl,--as-needed markus@x4 tmp % ./a.out [1] 8353 segmentation fault ./a.out markus@x4 tmp % nm a.out | grep pthread w __pthread_key_create markus@x4 tmp % ldd ./a.out linux-vdso.so.1 (0x00007fff709ff000) libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/libstdc++.so.6 (0x00007fb001be9000) libc.so.6 => /lib/libc.so.6 (0x00007fb0017a1000) libm.so.6 => /lib/libm.so.6 (0x00007fb001512000) /lib64/ld-linux-x86-64.so.2 (0x00007fb001b18000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fb001bd0000) markus@x4 tmp % g++ -pthread -O2 print_exports.ii -Wl,--as-needed -Wl,-fuse-ld=bfd markus@x4 tmp % ./a.out markus@x4 tmp % nm a.out | grep pthread w __pthread_key_create@@GLIBC_2.2.5 markus@x4 tmp % ldd ./a.out linux-vdso.so.1 (0x00007fff599ff000) libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.0/libstdc++.so.6 (0x00007f25053ac000) libpthread.so.0 => /lib/libpthread.so.0 (0x00007f25050bd000) libc.so.6 => /lib/libc.so.6 (0x00007f2504d46000) libm.so.6 => /lib/libm.so.6 (0x00007f2504ab7000) /lib64/ld-linux-x86-64.so.2 (0x00007f25052db000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f2505393000) markus@x4 tmp %
The ld documentation says: --as-needed --no-as-needed This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. --as-needed causes a DT_NEEDED tag to only be emitted for a library that at that point in the link satisfies a non-weak undefined symbol reference from a regular object file or, if the library is not found in the DT_NEEDED lists of other libraries, a non-weak undefined symbol reference from another dynamic library. Object files or libraries appearing on the command line after the library in question do not affect whether the library is seen as needed. This is similar to the rules for extraction of object files from archives. --no-as-needed restores the default behaviour. Note where it says *non-weak*. It seems to me that gold is doing the right thing here and BFD ld is not.
bfd ld behaviour with the testcase in comment #6 is a little weird, but I think correct given the description of --as-needed. On my x86_64 Ubuntu 12.04 box, it isn't __pthread_key_create that causes libpthread to be seen as needed. libpthread.so.0 is being included in the link due to a strong reference in libstdc++.so.6 to write@GLIBC_2.2.5. libpthread.so.0 defines a weak write@@GLIBC_2.2.5 so satisfies the --as-needed requirement. The order in which the libraries are linked, -lstdc++, -lpthread, -lc, means we haven't seen the definition in libc.so.6 for "write" at the time we're checking whether libpthread.so.6 is needed.. If I modify the order to -lstdc++, -lc, -lpthread, -lc then libpthread is seen as not needed, and the resulting a.out does not crash. So I think Cary was a little hasty in closing this bug.
"Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. --as-needed causes a DT_NEEDED tag to only be emitted for a library that at that point in the link [a] satisfies a non-weak undefined symbol reference from a regular object file or, [b] if the library is not found in the DT_NEEDED lists of other libraries, a non-weak undefined symbol reference from another dynamic library." Case [a] is not satisfied here, since there is no reference to libpthread from a regular object file. Case [b] is related to one of the major differences between BFD ld and gold: gold does not track DT_NEEDED lists from shared libraries, so it does not check for this case. I'm still a bit puzzled as to why there's a weak reference to libpthread in the first place. And if there's a weak references, why isn't the code prepared to deal with it remaining unresolved? This seems like an artificial test case to me.
I was also puzzled as to why libpthread.so is exporting symbols defined in libc.so, and vice versa, but on looking at the code there is some justification for some of the duplication. The libc versions have extra code (testing for multple threads) before taking locks. So the libc versions would be a tiny bit slower than libpthread versions, when you know for sure that multiple threads are running. Now if you're linking against libpthread you probably do have multiple threads, but clearly the testcase in comment #6 does not have multiple threads but manages to pull in libpthread. Note that this is *not* via the weak reference to __pthread_key_create but due to the duplicate symbols! And if libpthread is pulled in accidentally, then single-threaded code will run slower.. Another thing I just found is that the testcase in comment #6 does not segfault when linked by mainline gold on my x86_64 system. (My g++ reports (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3) I guess I should have checked gold before reopening this bug. I think it likely that newer versions of libstdc++ are at fault here.