Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / elf / dl-lookup.c
blob4d5d795ee5f1084dd698356081a9e661b5ec37a6
1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995 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. */
20 #include <stddef.h>
21 #include <libelf.h>
22 #include <link.h>
23 #include <assert.h>
25 /* Search loaded objects' symbol tables for a definition of
26 the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since
27 that is the object making the reference. */
29 Elf32_Addr
30 _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
31 struct link_map *symbol_scope,
32 const char *reference_name)
34 unsigned long int hash = elf_hash (undef_name);
35 struct link_map *map;
36 struct
38 Elf32_Addr a;
39 const Elf32_Sym *s;
40 } weak_value = { 0, NULL };
42 /* Search the relevant loaded objects for a definition. */
43 for (map = symbol_scope; map; map = map->l_next)
45 const Elf32_Sym *symtab;
46 const char *strtab;
47 Elf32_Word symidx;
49 symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
50 strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
52 /* Search the appropriate hash bucket in this object's symbol table
53 for a definition for the same symbol name. */
54 for (symidx = map->l_buckets[hash % map->l_nbuckets];
55 symidx != STN_UNDEF;
56 symidx = map->l_chain[symidx])
58 const Elf32_Sym *sym = &symtab[symidx];
60 if (sym->st_value == 0)
61 continue;
63 switch (ELF32_ST_TYPE (sym->st_info))
65 case STT_NOTYPE:
66 case STT_FUNC:
67 case STT_OBJECT:
68 break;
69 default:
70 /* Not a code/data definition. */
71 continue;
74 if (sym->st_shndx == SHN_UNDEF)
75 /* This is the same symbol we are looking for the value for.
76 If it is a PLT entry, it will have a value of its own;
77 but that is not what we are looking for. */
78 continue;
80 if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
81 /* Not the symbol we are looking for. */
82 continue;
84 switch (ELF32_ST_BIND (sym->st_info))
86 case STB_GLOBAL:
87 /* Global definition. Just what we need. */
88 *ref = sym;
89 return map->l_addr;
90 case STB_WEAK:
91 /* Weak definition. Use this value if we don't find another. */
92 if (weak_value.a == 0)
94 weak_value.s = sym;
95 weak_value.a = map->l_addr;
97 break;
98 default:
99 /* Local symbols are ignored. */
100 break;
105 if (weak_value.s == NULL)
107 const char msg[] = "undefined symbol: ";
108 char buf[sizeof msg + strlen (undef_name)];
109 memcpy (buf, msg, sizeof msg - 1);
110 memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
111 _dl_signal_error (0, reference_name, buf);
114 *ref = weak_value.s;
115 return weak_value.a;
119 /* Cache the location of MAP's hash table. */
121 void
122 _dl_setup_hash (struct link_map *map)
124 Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
125 Elf32_Word nchain;
126 map->l_nbuckets = *hash++;
127 nchain = *hash++;
128 map->l_buckets = hash;
129 hash += map->l_nbuckets;
130 map->l_chain = hash;