From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32667 invoked by alias); 22 Dec 2004 03:55:53 -0000 Mailing-List: contact binutils-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sources.redhat.com Received: (qmail 32641 invoked from network); 22 Dec 2004 03:55:45 -0000 Received: from unknown (HELO gizmo05bw.bigpond.com) (144.140.70.40) by sourceware.org with SMTP; 22 Dec 2004 03:55:45 -0000 Received: (qmail 22857 invoked from network); 22 Dec 2004 03:55:43 -0000 Received: from unknown (HELO bwmam12.bigpond.com) (144.135.24.103) by gizmo05bw.bigpond.com with SMTP; 22 Dec 2004 03:55:43 -0000 Received: from cpe-144-136-221-26.sa.bigpond.net.au ([144.136.221.26]) by bwmam12.bigpond.com(MAM REL_3_4_2a 189/18176389) with SMTP id 18176389; Wed, 22 Dec 2004 13:55:43 +1000 Received: by bubble.modra.org (Postfix, from userid 500) id CAB0654C6C; Wed, 22 Dec 2004 14:25:42 +1030 Date: Wed, 22 Dec 2004 03:55:00 -0000 From: Alan Modra To: binutils@sources.redhat.com Subject: Fix an --as-needed linker problem Message-ID: <20041222035542.GA18274@bubble.modra.org> Mail-Followup-To: binutils@sources.redhat.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-12/txt/msg00272.txt.bz2 This is a fix for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17608 Quoting from the PR: When linking we use: -lgcc --as-needed -lgcc_s --no-as-needed -lc_p -lgcc --as-needed -lgcc_s --no-as-needed. During the first scan of libgcc_s.so, the linker finds no reason to mark libgcc_s.so as needed, because no symbols in libgcc_s.so are referenced at that point. After linking libc_p.a, the second scan of libgcc_s.so does find referenced symbols. However, the linker sees that these symbols have already been defined, thus the "new" definitions found in the second scan of libgcc_s.so aren't used. (If a symbol is defined in two shared libs, the one from the lib first encountered by the linker is used. As far as the linker is concerned the first libgcc_s.so is a different shared lib from the second libgcc_s.so). Thus the linker decides that the second libgcc_s.so isn't needed, and so doesn't emit a DT_NEEDED tag for libgcc_s.so. With older glibc ld.so, this resulted in segfaults. Current ld.so complains with Inconsistency detected by ld.so: dl-version.c: 230: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed! * elflink.c (_bfd_elf_merge_symbol): Treat old definitions from as-needed dynamic libs as undefined. (elf_link_add_object_symbols): Remove DYN_AS_NEEDED from as-needed libs when finding they are needed. Index: bfd/elflink.c =================================================================== RCS file: /cvs/src/src/bfd/elflink.c,v retrieving revision 1.121 diff -u -p -r1.121 elflink.c --- bfd/elflink.c 10 Dec 2004 14:04:58 -0000 1.121 +++ bfd/elflink.c 22 Dec 2004 03:42:50 -0000 @@ -719,7 +719,7 @@ _bfd_elf_merge_symbol (bfd *abfd, int bind; bfd *oldbfd; bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; - bfd_boolean newweak, oldweak; + bfd_boolean newweak, oldweak, old_asneeded; *skip = FALSE; *override = FALSE; @@ -849,6 +849,14 @@ _bfd_elf_merge_symbol (bfd *abfd, else olddef = TRUE; + /* If the old definition came from an as-needed dynamic library which + wasn't found to be needed, treat the sym as undefined. */ + old_asneeded = FALSE; + if (newdyn + && olddyn + && (elf_dyn_lib_class (oldbfd) & DYN_AS_NEEDED) != 0) + old_asneeded = TRUE; + /* Check TLS symbol. */ if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS) && ELF_ST_TYPE (sym->st_info) != h->type) @@ -1051,6 +1059,7 @@ _bfd_elf_merge_symbol (bfd *abfd, if (olddyn && olddef + && !old_asneeded && h->root.type == bfd_link_hash_defined && h->def_dynamic && (h->root.u.def.section->flags & SEC_ALLOC) != 0 @@ -1102,7 +1111,7 @@ _bfd_elf_merge_symbol (bfd *abfd, if (newdyn && newdef - && (olddef + && ((olddef && !old_asneeded) || (h->root.type == bfd_link_hash_common && (newweak || ELF_ST_TYPE (sym->st_info) == STT_FUNC)))) @@ -1152,7 +1161,7 @@ _bfd_elf_merge_symbol (bfd *abfd, symbol is a function or is weak. */ flip = NULL; - if (! newdyn + if ((!newdyn || old_asneeded) && (newdef || (bfd_is_com_section (sec) && (oldweak @@ -3937,6 +3946,8 @@ elf_link_add_object_symbols (bfd *abfd, goto error_free_vers; } + elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED; + add_needed = TRUE; ret = elf_add_dt_needed_tag (info, soname, add_needed); if (ret < 0) -- Alan Modra IBM OzLabs - Linux Technology Centre