Created attachment 9754 [details] gold-mips-forced-local.c Originally this systemd bug in Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=851412 The attached testcase immediately segfaults when run after being compiled by gold on mips. It works fine when the bfd linker is used. Compile with: gcc -Wl,-version-script=blank.ver -fuse-ld=gold gold-mips-forced-local.c With blank.ver hiding all symbols: { local: *; }; The segfault occurs in __start when it tries to call __libc_start_main. It instead calls a NULL pointer. Looking in GDB the GOT has definitely been initialized but the pointer to __libc_start_main occurs 8 bytes (2 words) before the GOT entry actually accessed in __start. In Debian, the bug manifested in any executable which loaded libsystemd.so by segfaulting on exit. The segfault occured in __do_global_dtors_aux when it tried to call __cxa_finalize but instead called some other random function from libsystemd. Aurélien Jarno bisected this bug to commit c4d5a76223f74930add9014f2a77339eb80b737c: Author: Cary Coutant <ccoutant@gmail.com> Date: Thu Dec 22 14:06:24 2016 -0800 Fix placement of forced local symbols in the dynamic symbol table. Gold was not placing forced-local symbols (e.g., hidden visibility) at the front of the dynamic symbol table, or including them in the count of local symbols recorded in the .dynsym section's sh_info field. In my testcase I expect the __start_ASECTION and __stop_ASECTION symbols are forced local and were affected by this (also fits the GOT being offset by 2 words). On MIPS they will require GOT entries as they are used by num_ptrs, but presumably moving them around the dynamic symbol table screwed the GOT up on MIPS. I know that on MIPS, the dynamic symbol table is used as an index into the GOT but I don't have a lot of in depth knowledge on it.
Created attachment 9757 [details] testcase v2 Fix testcase to add missing section attribute.
I have submitted patch that fixes this issue (https://sourceware.org/ml/binutils/2017-01/msg00289.html). With this patch, we have run tests for systemd package on Debian. Results of two tests that failed with segmentation fault: PASS test-libsystemd-sym (exit status: 0) SKIP test-bus-marshal (exit status: 77)
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c1f59f8ff9462ce45a3287ea06382a97e561fed3 commit c1f59f8ff9462ce45a3287ea06382a97e561fed3 Author: Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com> Date: Mon Jan 23 17:12:10 2017 -0800 Fix MIPS GOT when global symbols are forced to local visibility. gold/ PR gold/21054 * mips.cc (Mips_got_info::record_global_got_symbol): Don't add symbol to the dynamic symbol table if it is forced to local visibility. (Target_mips::do_finalize_sections): Don't add __RLD_MAP symbol to the dynamic symbol table if it is forced to local visibility.
The binutils-2_28-branch branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=961798ea2ba2f41892ece3695e681bf71df08eba commit 961798ea2ba2f41892ece3695e681bf71df08eba Author: Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com> Date: Mon Jan 23 17:12:10 2017 -0800 Fix MIPS GOT when global symbols are forced to local visibility. gold/ PR gold/21054 * mips.cc (Mips_got_info::record_global_got_symbol): Don't add symbol to the dynamic symbol table if it is forced to local visibility. (Target_mips::do_finalize_sections): Don't add __RLD_MAP symbol to the dynamic symbol table if it is forced to local visibility.
Fixed on trunk and for binutils 2.28.