]> sourceware.org Git - glibc.git/blame - elf/dl-lookup.c
Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / elf / dl-lookup.c
CommitLineData
d66e34cd
RM
1/* Look up a symbol in the loaded objects.
2Copyright (C) 1995 Free Software Foundation, Inc.
3This file is part of the GNU C Library.
4
5The GNU C Library is free software; you can redistribute it and/or
6modify it under the terms of the GNU Library General Public License as
7published by the Free Software Foundation; either version 2 of the
8License, or (at your option) any later version.
9
10The GNU C Library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13Library General Public License for more details.
14
15You should have received a copy of the GNU Library General Public
16License along with the GNU C Library; see the file COPYING.LIB. If
17not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18Cambridge, MA 02139, USA. */
19
20#include <stddef.h>
21#include <libelf.h>
22#include <link.h>
a1a9d215 23#include <assert.h>
d66e34cd
RM
24
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. */
28
29Elf32_Addr
30_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
421f82e5
RM
31 struct link_map *symbol_scope,
32 const char *reference_name)
d66e34cd
RM
33{
34 unsigned long int hash = elf_hash (undef_name);
35 struct link_map *map;
36 struct
37 {
38 Elf32_Addr a;
39 const Elf32_Sym *s;
40 } weak_value = { 0, NULL };
41
42 /* Search the relevant loaded objects for a definition. */
43 for (map = symbol_scope; map; map = map->l_next)
44 {
45 const Elf32_Sym *symtab;
46 const char *strtab;
47 Elf32_Word symidx;
48
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);
51
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])
57 {
58 const Elf32_Sym *sym = &symtab[symidx];
59
60 if (sym->st_value == 0)
61 continue;
62
63 switch (ELF32_ST_TYPE (sym->st_info))
64 {
65 case STT_NOTYPE:
66 case STT_FUNC:
67 case STT_OBJECT:
68 break;
69 default:
70 /* Not a code/data definition. */
71 continue;
72 }
73
a1a9d215 74 if (sym->st_shndx == SHN_UNDEF)
d66e34cd
RM
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. */
a1a9d215 78 continue;
d66e34cd 79
a1a9d215 80 if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
d66e34cd
RM
81 /* Not the symbol we are looking for. */
82 continue;
83
84 switch (ELF32_ST_BIND (sym->st_info))
85 {
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)
93 {
94 weak_value.s = sym;
95 weak_value.a = map->l_addr;
96 }
97 break;
98 default:
99 /* Local symbols are ignored. */
100 break;
101 }
102 }
103 }
104
105 if (weak_value.s == NULL)
106 {
107 const char msg[] = "undefined symbol: ";
108 char buf[sizeof msg + strlen (undef_name)];
109 memcpy (buf, msg, sizeof msg - 1);
a1a9d215
RM
110 memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
111 _dl_signal_error (0, reference_name, buf);
d66e34cd
RM
112 }
113
114 *ref = weak_value.s;
115 return weak_value.a;
116}
117
118
119/* Cache the location of MAP's hash table. */
120
121void
122_dl_setup_hash (struct link_map *map)
123{
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;
131}
This page took 0.038931 seconds and 5 git commands to generate.