From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1073 invoked by alias); 26 Jun 2006 12:32:46 -0000 Received: (qmail 1059 invoked by uid 22791); 26 Jun 2006 12:32:45 -0000 X-Spam-Check-By: sourceware.org Received: from sunsite.ms.mff.cuni.cz (HELO sunsite.mff.cuni.cz) (195.113.15.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 26 Jun 2006 12:32:42 +0000 Received: from sunsite.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.mff.cuni.cz (8.13.1/8.13.1) with ESMTP id k5QCWd40004817 for ; Mon, 26 Jun 2006 14:32:39 +0200 Received: (from jj@localhost) by sunsite.mff.cuni.cz (8.13.1/8.13.1/Submit) id k5QCWdIq004816 for binutils@sources.redhat.com; Mon, 26 Jun 2006 14:32:39 +0200 Date: Mon, 26 Jun 2006 13:02:00 -0000 From: Jakub Jelinek To: binutils@sources.redhat.com Subject: [RFC PATCH] Don't put local or undefined symbols into .hash Message-ID: <20060626123238.GU3823@sunsite.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2006-06/txt/msg00384.txt.bz2 Hi! It seems an average shared library has roughly 25% of undefined symbols in its .dynsym section. Currently, the linker puts all dynamic symbols (except the special ones like section symbols or symbol 0) into the .hash section, but the dynamic linker will always skip STB_LOCAL symbols or undefined symbols (except those with st_value != 0) - it is always looking for symbol definitions. Is there any reason why we put even the undefined or local symbols into .hash? It just makes the .hash buckets array larger and/or the hash chains longer than necessary. Or is there something that relies on all symbols being there? So far I have noticed just readelf -Ds (but in that case it is questionable if readelf -Ds would need to change or stay as is). 2006-06-26 Jakub Jelinek * elflink.c (elf_collect_hash_codes): Set u.elf_hash_value to ~0 for local or undefined symbols, don't include it into hashcodes array. (elf_link_output_extsym): Don't put symbols with u.elf_hash_value ~0 into the .hash section. --- bfd/elflink.c.jj 2006-06-20 18:34:53.000000000 +0200 +++ bfd/elflink.c 2006-06-26 14:04:49.000000000 +0200 @@ -4785,6 +4785,17 @@ elf_collect_hash_codes (struct elf_link_ if (h->dynindx == -1) return TRUE; + /* Ignore also local symbols and undefined symbols. */ + if (h->forced_local + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak) + { + /* bfd_elf_hash values never have topmost 4 bits set, + so ~0 don't collide with any valid hash value. */ + h->u.elf_hash_value = ~(unsigned long) 0; + return TRUE; + } + name = h->root.root.string; p = strchr (name, ELF_VER_CHR); if (p != NULL) @@ -6678,16 +6689,24 @@ elf_link_output_extsym (struct elf_link_ bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0); bucketcount = elf_hash_table (finfo->info)->bucketcount; - bucket = h->u.elf_hash_value % bucketcount; - hash_entry_size - = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; - bucketpos = ((bfd_byte *) finfo->hash_sec->contents - + (bucket + 2) * hash_entry_size); - chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, - ((bfd_byte *) finfo->hash_sec->contents - + (bucketcount + 2 + h->dynindx) * hash_entry_size)); + if (h->u.elf_hash_value == ~(unsigned long) 0) + BFD_ASSERT (h->forced_local + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak); + else + { + bucket = h->u.elf_hash_value % bucketcount; + hash_entry_size + = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; + bucketpos = ((bfd_byte *) finfo->hash_sec->contents + + (bucket + 2) * hash_entry_size); + chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); + bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, + bucketpos); + bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, + ((bfd_byte *) finfo->hash_sec->contents + + (bucketcount + 2 + h->dynindx) * hash_entry_size)); + } if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) { Jakub