Bug 21054 - [MIPS] Forced local symbol rearranging messes up GOT
Summary: [MIPS] Forced local symbol rearranging messes up GOT
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.29
: P2 normal
Target Milestone: ---
Assignee: Cary Coutant
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-01-16 17:58 UTC by James Cowgill
Modified: 2017-01-24 01:37 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
gold-mips-forced-local.c (210 bytes, text/x-csrc)
2017-01-16 17:58 UTC, James Cowgill
Details
testcase v2 (230 bytes, text/x-csrc)
2017-01-17 11:28 UTC, James Cowgill
Details

Note You need to log in before you can comment on or make changes to this bug.
Description James Cowgill 2017-01-16 17:58:30 UTC
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.
Comment 1 James Cowgill 2017-01-17 11:28:31 UTC
Created attachment 9757 [details]
testcase v2

Fix testcase to add missing section attribute.
Comment 2 Vladimir Radosavljevic 2017-01-18 18:27:32 UTC
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)
Comment 3 cvs-commit@gcc.gnu.org 2017-01-24 01:20:14 UTC
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.
Comment 4 cvs-commit@gcc.gnu.org 2017-01-24 01:23:10 UTC
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.
Comment 5 Cary Coutant 2017-01-24 01:37:50 UTC
Fixed on trunk and for binutils 2.28.