1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
25 /* Search loaded objects' symbol tables for a definition of the symbol
26 UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero,
27 then a PLT entry cannot satisfy the reference; some different binding
31 _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
32 struct link_map *symbol_scope,
33 const char *reference_name,
34 Elf32_Addr reloc_addr,
37 unsigned long int hash = elf_hash (undef_name);
43 } weak_value = { 0, NULL };
45 /* Search the relevant loaded objects for a definition. */
46 for (map = symbol_scope; map; map = map->l_next)
48 const Elf32_Sym *symtab;
52 symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
53 strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
55 /* Search the appropriate hash bucket in this object's symbol table
56 for a definition for the same symbol name. */
57 for (symidx = map->l_buckets[hash % map->l_nbuckets];
59 symidx = map->l_chain[symidx])
61 const Elf32_Sym *sym = &symtab[symidx];
63 if (sym->st_value == 0 || /* No value. */
64 reloc_addr == map->l_addr + sym->st_value || /* Self ref. */
65 (noplt && sym->st_shndx == SHN_UNDEF)) /* Unwanted PLT entry. */
68 switch (ELF32_ST_TYPE (sym->st_info))
75 /* Not a code/data definition. */
79 if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
80 /* Not the symbol we are looking for. */
83 switch (ELF32_ST_BIND (sym->st_info))
86 /* Global definition. Just what we need. */
90 /* Weak definition. Use this value if we don't find another. */
94 weak_value.a = map->l_addr;
98 /* Local symbols are ignored. */
104 if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK)
106 const char msg[] = "undefined symbol: ";
107 char buf[sizeof msg + strlen (undef_name)];
108 memcpy (buf, msg, sizeof msg - 1);
109 memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
110 _dl_signal_error (0, reference_name, buf);
118 /* Cache the location of MAP's hash table. */
121 _dl_setup_hash (struct link_map *map)
123 Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
125 map->l_nbuckets = *hash++;
127 map->l_buckets = hash;
128 hash += map->l_nbuckets;