Bug 19073 - S/390: ld: Segmentation fault building Glibc
Summary: S/390: ld: Segmentation fault building Glibc
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.26
: P2 normal
Target Milestone: 2.26
Assignee: H.J. Lu
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-06 11:47 UTC by Andreas Krebbel
Modified: 2015-10-12 13:24 UTC (History)
1 user (show)

See Also:
Host: s390x-ibm-linux
Target: s390x-ibm-linux
Build: s390x-ibm-linux
Last reconfirmed: 2015-10-12 00:00:00


Attachments
Testcase - reduced input file from glibc (504.22 KB, application/x-object)
2015-10-09 19:38 UTC, Andreas Krebbel
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Krebbel 2015-10-06 11:47:43 UTC
Binutils cannot be used to build Glibc since this commit:

commit 422f11824b3abf6c71042e2ee3aed572f250fc89
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Aug 10 07:57:40 2015 -0700

    Replace hidden with versioned in elf_link_hash_entry
    
    This patch replaces the "hidden" field with the "versioned" field
    in
    elf_link_hash_entry so that we can avoid calling strchr and
    strrchr if
    the symbol is unversioned.
    
        * elf-bfd.h (elf_symbol_version): New enum.
        (elf_link_hash_entry): Replace hidden with versioned.
        * elflink.c (_bfd_elf_merge_symbol): Don't look for symbol
        version if the symbol is unversioned.  Initialize versioned.
        (_bfd_elf_add_default_symbol): Don't look for symbol version
        if the symbol is unversioned or hidden.  Initialize versioned.
        (elf_collect_hash_codes): Don't look for symbol version if the
        symbol is unversioned.
        (elf_collect_gnu_hash_codes): Likewise.
        (bfd_elf_gc_mark_dynamic_ref_symbol): Likewise.
        (_bfd_elf_link_hash_copy_indirect): Check versioned instead of
        hidden.
        (elf_link_output_extsym): Likewise.

gcc   -shared -static-libgcc -Wl,-O1  -Wl,-z,defs -Wl,-dynamic-linker=/lib/ld64.so.1  -B/home/andreas/glibc/glibc-06102015-build/csu/  -Wl,--version-script=/home/andreas/glibc/glibc-06102015-build/libc.map -Wl,-soname=libc.so.6 -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -nostdlib -nostartfiles -e __libc_main -L/home/andreas/glibc/glibc-06102015-build -L/home/andreas/glibc/glibc-06102015-build/math -L/home/andreas/glibc/glibc-06102015-build/elf -L/home/andreas/glibc/glibc-06102015-build/dlfcn -L/home/andreas/glibc/glibc-06102015-build/nss -L/home/andreas/glibc/glibc-06102015-build/nis -L/home/andreas/glibc/glibc-06102015-build/rt -L/home/andreas/glibc/glibc-06102015-build/resolv -L/home/andreas/glibc/glibc-06102015-build/crypt -L/home/andreas/glibc/glibc-06102015-build/mathvec -L/home/andreas/glibc/glibc-06102015-build/nptl -Wl,-rpath-link=/home/andreas/glibc/glibc-06102015-build:/home/andreas/glibc/glibc-06102015-build/math:/home/andreas/glibc/glibc-06102015-build/elf:/home/andreas/glibc/glibc-06102015-build/dlfcn:/home/andreas/glibc/glibc-06102015-build/nss:/home/andreas/glibc/glibc-06102015-build/nis:/home/andreas/glibc/glibc-06102015-build/rt:/home/andreas/glibc/glibc-06102015-build/resolv:/home/andreas/glibc/glibc-06102015-build/crypt:/home/andreas/glibc/glibc-06102015-build/mathvec:/home/andreas/glibc/glibc-06102015-build/nptl -o /home/andreas/glibc/glibc-06102015-build/libc.so -T /home/andreas/glibc/glibc-06102015-build/shlib.lds /home/andreas/glibc/glibc-06102015-build/csu/abi-note.o /home/andreas/glibc/glibc-06102015-build/elf/soinit.os /home/andreas/glibc/glibc-06102015-build/libc_pic.os /home/andreas/glibc/glibc-06102015-build/elf/sofini.os /home/andreas/glibc/glibc-06102015-build/elf/interp.os /home/andreas/glibc/glibc-06102015-build/elf/ld.so -lgcc
/bin/sh ../scripts/rellns-sh /home/andreas/glibc/glibc-06102015-build/elf/ld.so /home/andreas/glibc/glibc-06102015-build/elf/ld64.so.1.new
mv -f /home/andreas/glibc/glibc-06102015-build/elf/ld64.so.1.new /home/andreas/glibc/glibc-06102015-build/elf/ld64.so.1
collect2: error: ld terminated with signal 11 [Segmentation fault]
make[2]: *** [/home/andreas/glibc/glibc-06102015-build/libc.so] Error 1
make[2]: Leaving directory `/home/andreas/glibc/glibc/elf'
make[1]: *** [elf/subdir_lib] Error 2
make[1]: Leaving directory `/home/andreas/glibc/glibc'
make: *** [all] Error 2

Program received signal SIGSEGV, Segmentation fault.
0x000003fffdeb323c in __memcpy_mvcle () from /lib64/libc.so.6
(gdb) bt
#0  0x000003fffdeb323c in __memcpy_mvcle () from /lib64/libc.so.6
#1  0x000000008009ae06 in _bfd_elf_add_default_symbol (abfd=0x8022f050, info=0x801be990 <link_info>, h=0x802b02f8, name=0x8024bab7 "setjmp", sym=0x3fff78d22d0, sec=0x80230320, value=86064, 
    poldbfd=0x3ffffffddd0, dynsym=0x3ffffffddc0) at /home/andreas/binutils/binutils/bfd/elflink.c:1724
#2  0x00000000800a1752 in elf_link_add_object_symbols (abfd=0x8022f050, info=0x801be990 <link_info>) at /home/andreas/binutils/binutils/bfd/elflink.c:4375
#3  0x00000000800a3918 in bfd_elf_link_add_symbols (abfd=0x8022f050, info=0x801be990 <link_info>) at /home/andreas/binutils/binutils/bfd/elflink.c:5241
#4  0x0000000080015580 in load_symbols (entry=0x801c0328, place=0x3ffffffe438) at /home/andreas/binutils/binutils/ld/ldlang.c:2854
#5  0x0000000080016790 in open_input_bfds (s=0x801c0328, mode=OPEN_BFD_NORMAL) at /home/andreas/binutils/binutils/ld/ldlang.c:3311
#6  0x000000008001ebe4 in lang_process () at /home/andreas/binutils/binutils/ld/ldlang.c:6677
#7  0x0000000080024c06 in main (argc=50, argv=0x3ffffffe898) at /home/andreas/binutils/binutils/ld/ldmain.c:419
Comment 1 H.J. Lu 2015-10-06 12:25:02 UTC
I can build glibc master branch with binutils 2.25.51.20151006 on
x86 and x86-64. What target were you building for?
Comment 2 Andreas Krebbel 2015-10-06 13:06:41 UTC
(In reply to H.J. Lu from comment #1)
> I can build glibc master branch with binutils 2.25.51.20151006 on
> x86 and x86-64. What target were you building for?

s390x - I definitely should have mentioned this - sorry
Comment 3 H.J. Lu 2015-10-06 13:11:35 UTC
What went wrong?
Comment 4 Andreas Krebbel 2015-10-08 09:20:31 UTC
(gdb) p name
$1 = 0x8024eab7 "setjmp"
(gdb) p shortname
$2 = 0x3ff77b15020 "setjmp"
(gdb) p shortlen
$3 = 18446744071559648585
(gdb) l
1722
1723      shortlen = p - name;
1724      shortname = (char *) bfd_hash_allocate (&info->hash->table, shortlen + 1);
1725      if (shortname == NULL)
1726        return FALSE;
1727      memcpy (shortname, name, shortlen);
1728      shortname[shortlen] = '\0';
1729
1730      /* We are going to create a new symbol.  Merge it with any existing
1731         symbol with this name.  For the purposes of the merge, act as
(gdb) p p
$4 = 0x0
(gdb) p name
$5 = 0x8024eab7 "setjmp"
(gdb) p h->versioned
$6 = versioned

The problem is that there might be symbols marked as versioned but without having @ in its names. p is NULL then.

We have that with setjmp in Glibc:
234157: 0000000000015030     8 FUNC    WEAK   DEFAULT    2 setjmp@@GLIBC_2.2
234509: 0000000000015030     8 FUNC    WEAK   DEFAULT    2 setjmp
Comment 5 H.J. Lu 2015-10-08 10:47:56 UTC
(In reply to Andreas Krebbel from comment #4)
> 
> The problem is that there might be symbols marked as versioned but without
> having @ in its names. p is NULL then.
> 
> We have that with setjmp in Glibc:
> 234157: 0000000000015030     8 FUNC    WEAK   DEFAULT    2 setjmp@@GLIBC_2.2
> 234509: 0000000000015030     8 FUNC    WEAK   DEFAULT    2 setjmp

Please provide a testcase.
Comment 6 Andreas Krebbel 2015-10-09 19:38:22 UTC
Created attachment 8701 [details]
Testcase - reduced input file from glibc

With this testcase the failing symbol is getcontext:

 16488: 0000000000000000   106 FUNC    WEAK   DEFAULT    2 __v1__getcontext
 16534: 0000000000000000   106 FUNC    GLOBAL DEFAULT    2 __getcontext
 16562: 0000000000000000   106 FUNC    WEAK   DEFAULT    2 getcontext@@GLIBC_2.2
 16570: 0000000000000000   106 FUNC    WEAK   DEFAULT    2 getcontext@GLIBC_2.19
 16589: 0000000000000000   106 FUNC    WEAK   DEFAULT    2 __v2__getcontext
 16660: 0000000000000000   106 FUNC    WEAK   DEFAULT    2 getcontext

getcontext (as well as setjmp and others) on S/390 default to an older symbol version in order to avoid the buggy versions in Glibc 2.19.
Comment 7 H.J. Lu 2015-10-09 21:00:24 UTC
Please provide a testcase I can reproduce it on x86-64 with
only cross binutils.
Comment 8 Andreas Krebbel 2015-10-12 06:39:16 UTC
(In reply to H.J. Lu from comment #7)
> Please provide a testcase I can reproduce it on x86-64 with
> only cross binutils.

The testcase I've attached fails the same way with cross binutils:

install-s390x/bin/s390x-ibm-linux-ld -melf64_s390 b.os
Segmentation fault (core dumped)
Comment 9 Andreas Krebbel 2015-10-12 07:25:33 UTC
The problem is that when processing "getcontext" in elf_link_add_object_symbols it is matched by the hash entry for "getcontext@@GLIBC_2.2" here:

      /* We need to make sure that indirect symbol dynamic flags are
	 updated.  */
      hi = h;
      while (h->root.type == bfd_link_hash_indirect
	     || h->root.type == bfd_link_hash_warning)
	h = (struct elf_link_hash_entry *) h->root.u.i.link;

While the name stays "getcontext" the new `h' has the `versioned' flag set. That's what confuses _bfd_elf_add_default_symbol.

This hack mimics the old behavior of exiting for all symbols not having @ in their name and fixes the problem for me:

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 94bb710..2a56fd6 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4374,8 +4374,9 @@ error_free_dyn:
 
          /* Check to see if we need to add an indirect symbol for
             the default name.  */
-         if (definition
-             || (!override && h->root.type == bfd_link_hash_common))
+         if (strchr (name, ELF_VER_CHR) != NULL
+             && (definition
+                 || (!override && h->root.type == bfd_link_hash_common)))
            if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
                                              sec, value, &old_bfd, &dynsym))
              goto error_free_vers;
Comment 10 H.J. Lu 2015-10-12 11:02:33 UTC
(In reply to Andreas Krebbel from comment #8)
> (In reply to H.J. Lu from comment #7)
> > Please provide a testcase I can reproduce it on x86-64 with
> > only cross binutils.
> 
> The testcase I've attached fails the same way with cross binutils:
> 
> install-s390x/bin/s390x-ibm-linux-ld -melf64_s390 b.os
> Segmentation fault (core dumped)

[hjl@gnu-6 pr19073]$ cat xxx.c
void
__foo ()
{
}

asm (".weak foo_v1");
asm (".globl foo_v1");
asm (".set foo_v1, __foo");
asm (".weak foo_v2");
asm (".globl foo_v2");
asm (".set foo_v2, __foo");
asm (".symver foo_v2,foo@VERS.2");
asm (".symver foo_v1,foo@@VERS.1");
asm (".globl foo");
asm (".weak foo");
asm (".set foo, __foo");
[hjl@gnu-6 pr19073]$ make libfoo.so
gcc -B./ -fPIC   -c -o xxx.o xxx.c
./ld -o foo.o -r xxx.o
./ld -o libfoo.so -shared foo.o --version-script foo.v
Makefile:12: recipe for target 'libfoo.so' failed
make: *** [libfoo.so] Segmentation fault
make: *** Deleting file 'libfoo.so'
[hjl@gnu-6 pr19073]$ 

There is a bug in sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
which defines both getcontext@@GLIBC_2.2 and getcontext.  But linker
shouldn't crash.
Comment 11 cvs-commit@gcc.gnu.org 2015-10-12 11:58:20 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4373f8af3ddbc301227e883d5cbed8302c107e59

commit 4373f8af3ddbc301227e883d5cbed8302c107e59
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Oct 12 04:55:24 2015 -0700

    Skip the unversioned definition after the default version
    
    We may see an unversioned definition after the default version.  We
    should skip the unversioned definition in this case.
    
    bfd/
    
    	PR ld/19073
    	* elflink.c (_bfd_elf_add_default_symbol): Skip the unversioned
    	definition after the default version.
    
    ld/testsuite/
    
    	PR ld/19073
    	* ld-elf/pr19073.map: New file.
    	* ld-elf/pr19073.rd: Likewise.
    	* ld-elf/pr19073.s: Likewise.
    	* ld-elf/shared.exp (build_tests): Add tests for PR ld/19073.
Comment 12 H.J. Lu 2015-10-12 12:00:37 UTC
Fixed.
Comment 13 Andreas Krebbel 2015-10-12 13:16:42 UTC
(In reply to H.J. Lu from comment #10)
> (In reply to Andreas Krebbel from comment #8)
> > (In reply to H.J. Lu from comment #7)
> > > Please provide a testcase I can reproduce it on x86-64 with
> > > only cross binutils.
> > 
> > The testcase I've attached fails the same way with cross binutils:
> > 
> > install-s390x/bin/s390x-ibm-linux-ld -melf64_s390 b.os
> > Segmentation fault (core dumped)
> 
> [hjl@gnu-6 pr19073]$ cat xxx.c
> void
> __foo ()
> {
> }
> 
> asm (".weak foo_v1");
> asm (".globl foo_v1");
> asm (".set foo_v1, __foo");
> asm (".weak foo_v2");
> asm (".globl foo_v2");
> asm (".set foo_v2, __foo");
> asm (".symver foo_v2,foo@VERS.2");
> asm (".symver foo_v1,foo@@VERS.1");
> asm (".globl foo");
> asm (".weak foo");
> asm (".set foo, __foo");
> [hjl@gnu-6 pr19073]$ make libfoo.so
> gcc -B./ -fPIC   -c -o xxx.o xxx.c
> ./ld -o foo.o -r xxx.o
> ./ld -o libfoo.so -shared foo.o --version-script foo.v
> Makefile:12: recipe for target 'libfoo.so' failed
> make: *** [libfoo.so] Segmentation fault
> make: *** Deleting file 'libfoo.so'
> [hjl@gnu-6 pr19073]$ 
> 
> There is a bug in sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
> which defines both getcontext@@GLIBC_2.2 and getcontext.  But linker
> shouldn't crash.

I agree that this does not look correct but it is similiar to e.g. setjmp on x86_64:

readelf -s libc.so.6 | grep " setjmp"
   622: 0000000000032ce0    10 FUNC    GLOBAL DEFAULT   13 setjmp@@GLIBC_2.2.5
  6015: 0000000000032ce0    10 FUNC    GLOBAL DEFAULT   13 setjmp

One difference appears to be that the symbol without version information is weak on s390.
Comment 14 H.J. Lu 2015-10-12 13:24:01 UTC
(In reply to Andreas Krebbel from comment #13)
> > There is a bug in sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
> > which defines both getcontext@@GLIBC_2.2 and getcontext.  But linker
> > shouldn't crash.
> 
> I agree that this does not look correct but it is similiar to e.g. setjmp on
> x86_64:
> 
> readelf -s libc.so.6 | grep " setjmp"
>    622: 0000000000032ce0    10 FUNC    GLOBAL DEFAULT   13
> setjmp@@GLIBC_2.2.5
>   6015: 0000000000032ce0    10 FUNC    GLOBAL DEFAULT   13 setjmp

This is expected.

> One difference appears to be that the symbol without version information is
> weak on s390.

I was referring to the input object files, not output shared libraries.
There is no need to define both getcontext@@GLIBC_2.2 and getcontext in
sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S.