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 not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
33 /* This is the hashing function specified by the ELF ABI. */
34 static inline unsigned
35 _dl_elf_hash (const char *name
)
37 unsigned long int hash
= 0;
41 hash
= (hash
<< 4) + *name
++;
42 hi
= hash
& 0xf0000000;
46 /* The ELF ABI says `hash &= ~hi', but this is equivalent
47 in this case and on some machines one insn instead of two. */
55 /* Inner part of the lookup functions. */
56 static inline ElfW(Addr
)
57 do_lookup (const char *undef_name
, unsigned long int hash
,
58 const ElfW(Sym
) **ref
, struct sym_val
*result
,
59 struct link_map
*list
[], size_t i
, size_t n
,
60 const char *reference_name
, struct link_map
*skip
, int flags
)
66 const ElfW(Sym
) *symtab
;
72 /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
73 if (skip
!= NULL
&& map
== skip
)
76 /* Don't search the executable when resolving a copy reloc. */
77 if (flags
& DL_LOOKUP_NOEXEC
&& map
->l_type
== lt_executable
)
80 symtab
= ((void *) map
->l_addr
+ map
->l_info
[DT_SYMTAB
]->d_un
.d_ptr
);
81 strtab
= ((void *) map
->l_addr
+ map
->l_info
[DT_STRTAB
]->d_un
.d_ptr
);
83 /* Search the appropriate hash bucket in this object's symbol table
84 for a definition for the same symbol name. */
85 for (symidx
= map
->l_buckets
[hash
% map
->l_nbuckets
];
87 symidx
= map
->l_chain
[symidx
])
89 const ElfW(Sym
) *sym
= &symtab
[symidx
];
91 if (sym
->st_value
== 0 || /* No value. */
92 ((flags
& DL_LOOKUP_NOPLT
) != 0 /* Reject PLT entry. */
93 && sym
->st_shndx
== SHN_UNDEF
))
96 switch (ELFW(ST_TYPE
) (sym
->st_info
))
103 /* Not a code/data definition. */
107 if (sym
!= *ref
&& strcmp (strtab
+ sym
->st_name
, undef_name
))
108 /* Not the symbol we are looking for. */
111 switch (ELFW(ST_BIND
) (sym
->st_info
))
114 /* Global definition. Just what we need. */
116 result
->a
= map
->l_addr
;
119 /* Weak definition. Use this value if we don't find
124 result
->a
= map
->l_addr
;
128 /* Local symbols are ignored. */
134 /* We have not found anything until now. */
138 /* Search loaded objects' symbol tables for a definition of the symbol
139 UNDEF_NAME. FLAGS is a set of flags. If DL_LOOKUP_NOEXEC is set,
140 then don't search the executable for a definition; this used for
141 copy relocs. If DL_LOOKUP_NOPLT is set, then a PLT entry cannot
142 satisfy the reference; some different binding must be found. */
145 _dl_lookup_symbol (const char *undef_name
, const ElfW(Sym
) **ref
,
146 struct link_map
*symbol_scope
[],
147 const char *reference_name
,
150 const unsigned long int hash
= _dl_elf_hash (undef_name
);
151 struct sym_val current_value
= { 0, NULL
};
152 struct link_map
**scope
;
154 /* Search the relevant loaded objects for a definition. */
155 for (scope
= symbol_scope
; *scope
; ++scope
)
156 if (do_lookup (undef_name
, hash
, ref
, ¤t_value
,
157 (*scope
)->l_searchlist
, 0, (*scope
)->l_nsearchlist
,
158 reference_name
, NULL
, flags
))
161 if (current_value
.s
== NULL
&&
162 (*ref
== NULL
|| ELFW(ST_BIND
) ((*ref
)->st_info
) != STB_WEAK
))
164 /* We could find no value for a strong reference. */
165 const char msg
[] = "undefined symbol: ";
166 const size_t len
= strlen (undef_name
);
167 char buf
[sizeof msg
+ len
];
168 memcpy (buf
, msg
, sizeof msg
- 1);
169 memcpy (&buf
[sizeof msg
- 1], undef_name
, len
+ 1);
170 _dl_signal_error (0, reference_name
, buf
);
173 *ref
= current_value
.s
;
174 return current_value
.a
;
178 /* This function is nearly the same as `_dl_lookup_symbol' but it
179 skips in the first list all objects until SKIP_MAP is found. I.e.,
180 it only considers objects which were loaded after the described
181 object. If there are more search lists the object described by
182 SKIP_MAP is only skipped. */
184 _dl_lookup_symbol_skip (const char *undef_name
, const ElfW(Sym
) **ref
,
185 struct link_map
*symbol_scope
[],
186 const char *reference_name
,
187 struct link_map
*skip_map
,
190 const unsigned long int hash
= _dl_elf_hash (undef_name
);
191 struct sym_val current_value
= { 0, NULL
};
192 struct link_map
**scope
;
195 /* Search the relevant loaded objects for a definition. */
196 scope
= symbol_scope
;
197 for (i
= 0; (*scope
)->l_dupsearchlist
[i
] != skip_map
; ++i
)
198 assert (i
< (*scope
)->l_ndupsearchlist
);
200 if (! do_lookup (undef_name
, hash
, ref
, ¤t_value
,
201 (*scope
)->l_dupsearchlist
, i
, (*scope
)->l_ndupsearchlist
,
202 reference_name
, skip_map
, flags
))
204 if (do_lookup (undef_name
, hash
, ref
, ¤t_value
,
205 (*scope
)->l_dupsearchlist
, 0, (*scope
)->l_ndupsearchlist
,
206 reference_name
, skip_map
, flags
))
209 *ref
= current_value
.s
;
210 return current_value
.a
;
214 /* Cache the location of MAP's hash table. */
217 _dl_setup_hash (struct link_map
*map
)
219 ElfW(Symndx
) *hash
= (void *)(map
->l_addr
+ map
->l_info
[DT_HASH
]->d_un
.d_ptr
);
221 map
->l_nbuckets
= *hash
++;
223 map
->l_buckets
= hash
;
224 hash
+= map
->l_nbuckets
;