From patchwork Fri Apr 11 15:29:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Newton X-Patchwork-Id: 510 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx22.g.dreamhost.com (mx2.sub5.homie.mail.dreamhost.com [208.113.200.128]) by wilcox.dreamhost.com (Postfix) with ESMTP id AA969360072 for ; Fri, 11 Apr 2014 08:30:15 -0700 (PDT) Received: by homiemail-mx22.g.dreamhost.com (Postfix, from userid 14307373) id 5F6FB4982161; Fri, 11 Apr 2014 08:30:14 -0700 (PDT) X-Original-To: glibc@patchwork.siddhesh.in Delivered-To: x14307373@homiemail-mx22.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx22.g.dreamhost.com (Postfix) with ESMTPS id 5BDDC497AE7D for ; Fri, 11 Apr 2014 08:30:12 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; q=dns; s= default; b=pmrRoKYeBuKxXngjVTGs5rz5F1mDRs9W26zD4oCke0icI4achrcNw HvkLQ1/HEjeT/q/cEZlvV5q/tCvPjMyf9JkxS9upfXB18o0stjIXFW8pJnvYaLvK FN9QrsKY+yey3bXmpsPIluu1+HHQy1UFgr+Jq1H8FvbygGzyMUCzGg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; s=default; bh=IuxQVR7jfakV78IKp9B8q7G3hiA=; b=Acbyo3wSFLgl0qdCNiDIesVbC7ny GM9kDkslhicWb8HkfglBCUZl6V8qDijnegC/6Pm8ju9abdHsSZuhCVmTKgJZmVQC Ykp+VHhKzm2GEQZ/NIvBbBqwIi8R/ozzH8AYMOxBygsVjFiAp02v1CraHchDkanW aZZwSuq4wXvD7lU= Received: (qmail 2045 invoked by alias); 11 Apr 2014 15:30:01 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 2007 invoked by uid 89); 11 Apr 2014 15:29:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-we0-f176.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=1BV8nlMOgDeyXb9BVLN3sbdlFrAqsH1DONY5mYrpjAg=; b=LxZPnnTqO9zF+C3Q5tGWtjJXFzeEy9dv7Hqd1YCfZYhMOkpwh1PXo9mtJSnpAvGjDb 8RvMlSrp/97qkbT3QQzPdU+PyOYP/kOQcBFc3AJutaCUxj+e1hn71RwbqktPThao6ekH Rw2lkwllMhnVxeK2exJaE3iPYLNHPAMEbNvL06alGck0ccJBJIcPDtJRA/zgPVMC/iy9 il2/DY9QfgbIms4dDBadwBKviDGThwIqILNJz95HQ0yYdSbFgfLMOA2N5VHdJShORPHN pTrtJKk9exZw+2J/kCLHq5VuBdoLCrxku9BBP7DCWMK2HLvYltX9kjhV/K43upqMpbKz CQQg== X-Gm-Message-State: ALoCoQlPHILZbJqYHism2w35FTZkhYE82k7FU+6WdMU7GxaMPz00t5vHEs4aet4FZxXI+/C+Ckmp X-Received: by 10.180.149.143 with SMTP id ua15mr3993913wib.36.1397230193605; Fri, 11 Apr 2014 08:29:53 -0700 (PDT) From: Will Newton To: libc-alpha@sourceware.org Subject: [PATCH 1/3] elf/dl-lookup.c: Move STB_GNU_UNIQUE handling to a function Date: Fri, 11 Apr 2014 16:29:46 +0100 Message-Id: <1397230188-14581-1-git-send-email-will.newton@linaro.org> X-DH-Original-To: glibc@patchwork.siddhesh.in Move handling of STB_GNU_UNIQUE symbols to a separate function from do_lookup_x in order to make the code more readable. The new function gets inlined with gcc 4.8 on ARM and the do_lookup_x code becomes a few bytes smaller. ChangeLog: 2014-04-02 Will Newton * elf/dl-lookup.c (do_lookup_unique): New function. (do_lookup_x): Move STB_GNU_UNIQUE handling code to a separate function. --- elf/dl-lookup.c | 304 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 159 insertions(+), 145 deletions(-) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index be6f76f..896e1d2 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -186,6 +186,162 @@ check_match (const char *const undef_name, return sym; } +/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol + in the unique symbol table, creating a new entry if necessary. + Return the matching symbol in RESULT. */ +static void +do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + const struct link_map *map, struct sym_val *result, + int type_class, const ElfW(Sym) *sym, const char *strtab, + const ElfW(Sym) *ref, const struct link_map *undef_map) +{ + /* We have to determine whether we already found a + symbol with this name before. If not then we have to + add it to the search table. If we already found a + definition we have to use it. */ + void enter (struct unique_sym *table, size_t size, + unsigned int hash, const char *name, + const ElfW(Sym) *sym, const struct link_map *map) + { + size_t idx = hash % size; + size_t hash2 = 1 + hash % (size - 2); + while (table[idx].name != NULL) + { + idx += hash2; + if (idx >= size) + idx -= size; + } + + table[idx].hashval = hash; + table[idx].name = name; + table[idx].sym = sym; + table[idx].map = map; + } + + struct unique_sym_table *tab + = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table; + + __rtld_lock_lock_recursive (tab->lock); + + struct unique_sym *entries = tab->entries; + size_t size = tab->size; + if (entries != NULL) + { + size_t idx = new_hash % size; + size_t hash2 = 1 + new_hash % (size - 2); + while (1) + { + if (entries[idx].hashval == new_hash + && strcmp (entries[idx].name, undef_name) == 0) + { + if ((type_class & ELF_RTYPE_CLASS_COPY) != 0) + { + /* We possibly have to initialize the central + copy from the copy addressed through the + relocation. */ + result->s = sym; + result->m = (struct link_map *) map; + } + else + { + result->s = entries[idx].sym; + result->m = (struct link_map *) entries[idx].map; + } + __rtld_lock_unlock_recursive (tab->lock); + return; + } + + if (entries[idx].name == NULL) + break; + + idx += hash2; + if (idx >= size) + idx -= size; + } + + if (size * 3 <= tab->n_elements * 4) + { + /* Expand the table. */ +#ifdef RTLD_CHECK_FOREIGN_CALL + /* This must not happen during runtime relocations. */ + assert (!RTLD_CHECK_FOREIGN_CALL); +#endif + size_t newsize = _dl_higher_prime_number (size + 1); + struct unique_sym *newentries + = calloc (sizeof (struct unique_sym), newsize); + if (newentries == NULL) + { + nomem: + __rtld_lock_unlock_recursive (tab->lock); + _dl_fatal_printf ("out of memory\n"); + } + + for (idx = 0; idx < size; ++idx) + if (entries[idx].name != NULL) + enter (newentries, newsize, entries[idx].hashval, + entries[idx].name, entries[idx].sym, + entries[idx].map); + + tab->free (entries); + tab->size = newsize; + size = newsize; + entries = tab->entries = newentries; + tab->free = free; + } + } + else + { +#ifdef RTLD_CHECK_FOREIGN_CALL + /* This must not happen during runtime relocations. */ + assert (!RTLD_CHECK_FOREIGN_CALL); +#endif + +#ifdef SHARED + /* If tab->entries is NULL, but tab->size is not, it means + this is the second, conflict finding, lookup for + LD_TRACE_PRELINKING in _dl_debug_bindings. Don't + allocate anything and don't enter anything into the + hash table. */ + if (__glibc_unlikely (tab->size)) + { + assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK); + goto success; + } +#endif + +#define INITIAL_NUNIQUE_SYM_TABLE 31 + size = INITIAL_NUNIQUE_SYM_TABLE; + entries = calloc (sizeof (struct unique_sym), size); + if (entries == NULL) + goto nomem; + + tab->entries = entries; + tab->size = size; + tab->free = free; + } + + if ((type_class & ELF_RTYPE_CLASS_COPY) != 0) + enter (entries, size, new_hash, strtab + sym->st_name, ref, + undef_map); + else + { + enter (entries, size, new_hash, strtab + sym->st_name, sym, map); + + if (map->l_type == lt_loaded) + /* Make sure we don't unload this object by + setting the appropriate flag. */ + ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE; + } + ++tab->n_elements; + +#ifdef SHARED + success: +#endif + __rtld_lock_unlock_recursive (tab->lock); + + result->s = sym; + result->m = (struct link_map *) map; +} /* Inner part of the lookup functions. We return a value > 0 if we found the symbol, the value 0 if nothing is found and < 0 if @@ -323,157 +479,15 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, } /* FALLTHROUGH */ case STB_GLOBAL: - success: /* Global definition. Just what we need. */ result->s = sym; result->m = (struct link_map *) map; return 1; case STB_GNU_UNIQUE:; - /* We have to determine whether we already found a - symbol with this name before. If not then we have to - add it to the search table. If we already found a - definition we have to use it. */ - void enter (struct unique_sym *table, size_t size, - unsigned int hash, const char *name, - const ElfW(Sym) *sym, const struct link_map *map) - { - size_t idx = hash % size; - size_t hash2 = 1 + hash % (size - 2); - while (table[idx].name != NULL) - { - idx += hash2; - if (idx >= size) - idx -= size; - } - - table[idx].hashval = hash; - table[idx].name = name; - table[idx].sym = sym; - table[idx].map = map; - } - - struct unique_sym_table *tab - = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table; - - __rtld_lock_lock_recursive (tab->lock); - - struct unique_sym *entries = tab->entries; - size_t size = tab->size; - if (entries != NULL) - { - size_t idx = new_hash % size; - size_t hash2 = 1 + new_hash % (size - 2); - while (1) - { - if (entries[idx].hashval == new_hash - && strcmp (entries[idx].name, undef_name) == 0) - { - if ((type_class & ELF_RTYPE_CLASS_COPY) != 0) - { - /* We possibly have to initialize the central - copy from the copy addressed through the - relocation. */ - result->s = sym; - result->m = (struct link_map *) map; - } - else - { - result->s = entries[idx].sym; - result->m = (struct link_map *) entries[idx].map; - } - __rtld_lock_unlock_recursive (tab->lock); - return 1; - } - - if (entries[idx].name == NULL) - break; - - idx += hash2; - if (idx >= size) - idx -= size; - } - - if (size * 3 <= tab->n_elements * 4) - { - /* Expand the table. */ -#ifdef RTLD_CHECK_FOREIGN_CALL - /* This must not happen during runtime relocations. */ - assert (!RTLD_CHECK_FOREIGN_CALL); -#endif - size_t newsize = _dl_higher_prime_number (size + 1); - struct unique_sym *newentries - = calloc (sizeof (struct unique_sym), newsize); - if (newentries == NULL) - { - nomem: - __rtld_lock_unlock_recursive (tab->lock); - _dl_fatal_printf ("out of memory\n"); - } - - for (idx = 0; idx < size; ++idx) - if (entries[idx].name != NULL) - enter (newentries, newsize, entries[idx].hashval, - entries[idx].name, entries[idx].sym, - entries[idx].map); - - tab->free (entries); - tab->size = newsize; - size = newsize; - entries = tab->entries = newentries; - tab->free = free; - } - } - else - { -#ifdef RTLD_CHECK_FOREIGN_CALL - /* This must not happen during runtime relocations. */ - assert (!RTLD_CHECK_FOREIGN_CALL); -#endif - -#ifdef SHARED - /* If tab->entries is NULL, but tab->size is not, it means - this is the second, conflict finding, lookup for - LD_TRACE_PRELINKING in _dl_debug_bindings. Don't - allocate anything and don't enter anything into the - hash table. */ - if (__glibc_unlikely (tab->size)) - { - assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK); - __rtld_lock_unlock_recursive (tab->lock); - goto success; - } -#endif - -#define INITIAL_NUNIQUE_SYM_TABLE 31 - size = INITIAL_NUNIQUE_SYM_TABLE; - entries = calloc (sizeof (struct unique_sym), size); - if (entries == NULL) - goto nomem; - - tab->entries = entries; - tab->size = size; - tab->free = free; - } - - if ((type_class & ELF_RTYPE_CLASS_COPY) != 0) - enter (entries, size, new_hash, strtab + sym->st_name, ref, - undef_map); - else - { - enter (entries, size, new_hash, strtab + sym->st_name, sym, - map); - - if (map->l_type == lt_loaded) - /* Make sure we don't unload this object by - setting the appropriate flag. */ - ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE; - } - ++tab->n_elements; - - __rtld_lock_unlock_recursive (tab->lock); - - goto success; + do_lookup_unique (undef_name, new_hash, map, result, type_class, + sym, strtab, ref, undef_map); + return 1; default: /* Local symbols are ignored. */