diff --git a/elf/Makefile b/elf/Makefile index c6c4710e16..692a65b061 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -74,6 +74,7 @@ dl-routines = \ dl-reloc \ dl-runtime \ dl-scope \ + dl-setup_hash \ dl-sort-maps \ dl-thread_gscope_wait \ dl-tls \ @@ -169,6 +170,7 @@ CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines)) # Add the requested compiler flags to the early startup code. CFLAGS-dl-printf.os += $(rtld-early-cflags) +CFLAGS-dl-setup_hash.os += $(rtld-early-cflags) CFLAGS-dl-sysdep.os += $(rtld-early-cflags) CFLAGS-dl-tunables.os += $(rtld-early-cflags) CFLAGS-dl-write.os += $(rtld-early-cflags) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index f43ae150b7..cbf46fda62 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -953,51 +953,6 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, } -/* Cache the location of MAP's hash table. */ - -void -_dl_setup_hash (struct link_map *map) -{ - Elf_Symndx *hash; - - if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL)) - { - Elf32_Word *hash32 - = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]); - map->l_nbuckets = *hash32++; - Elf32_Word symbias = *hash32++; - Elf32_Word bitmask_nwords = *hash32++; - /* Must be a power of two. */ - assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); - map->l_gnu_bitmask_idxbits = bitmask_nwords - 1; - map->l_gnu_shift = *hash32++; - - map->l_gnu_bitmask = (ElfW(Addr) *) hash32; - hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; - - map->l_gnu_buckets = hash32; - hash32 += map->l_nbuckets; - map->l_gnu_chain_zero = hash32 - symbias; - - /* Initialize MIPS xhash translation table. */ - ELF_MACHINE_XHASH_SETUP (hash32, symbias, map); - - return; - } - - if (!map->l_info[DT_HASH]) - return; - hash = (void *) D_PTR (map, l_info[DT_HASH]); - - map->l_nbuckets = *hash++; - /* Skip nchain. */ - hash++; - map->l_buckets = hash; - hash += map->l_nbuckets; - map->l_chain = hash; -} - - static void _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, const ElfW(Sym) **ref, struct sym_val *value, diff --git a/elf/dl-setup_hash.c b/elf/dl-setup_hash.c new file mode 100644 index 0000000000..6dd57c5c94 --- /dev/null +++ b/elf/dl-setup_hash.c @@ -0,0 +1,63 @@ +/* Cache the location of a link map hash table. + Copyright (C) 1995-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +void +_dl_setup_hash (struct link_map *map) +{ + Elf_Symndx *hash; + + if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL)) + { + Elf32_Word *hash32 + = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]); + map->l_nbuckets = *hash32++; + Elf32_Word symbias = *hash32++; + Elf32_Word bitmask_nwords = *hash32++; + /* Must be a power of two. */ + assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); + map->l_gnu_bitmask_idxbits = bitmask_nwords - 1; + map->l_gnu_shift = *hash32++; + + map->l_gnu_bitmask = (ElfW(Addr) *) hash32; + hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; + + map->l_gnu_buckets = hash32; + hash32 += map->l_nbuckets; + map->l_gnu_chain_zero = hash32 - symbias; + + /* Initialize MIPS xhash translation table. */ + ELF_MACHINE_XHASH_SETUP (hash32, symbias, map); + + return; + } + + if (!map->l_info[DT_HASH]) + return; + hash = (void *) D_PTR (map, l_info[DT_HASH]); + + map->l_nbuckets = *hash++; + /* Skip nchain. */ + hash++; + map->l_buckets = hash; + hash += map->l_nbuckets; + map->l_chain = hash; +}