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. */
26 /* This is the hashing function specified by the ELF ABI. */
27 static inline unsigned
28 _dl_elf_hash (const char *name
)
30 unsigned long int hash
= 0;
34 hash
= (hash
<< 4) + *name
++;
35 hi
= hash
& 0xf0000000;
39 /* The ELF ABI says `hash &= ~hi', but this is equivalent
40 in this case and on some machines one insn instead of two. */
47 /* Search loaded objects' symbol tables for a definition of the symbol
48 UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero,
49 then a PLT entry cannot satisfy the reference; some different binding
53 _dl_lookup_symbol (const char *undef_name
, const ElfW(Sym
) **ref
,
54 struct link_map
*symbol_scope
[],
55 const char *reference_name
,
56 ElfW(Addr
) reloc_addr
,
59 const unsigned long int hash
= _dl_elf_hash (undef_name
);
64 } weak_value
= { 0, NULL
};
66 struct link_map
**scope
, *map
;
68 /* Search the relevant loaded objects for a definition. */
69 for (scope
= symbol_scope
; *scope
; ++scope
)
70 for (i
= 0; i
< (*scope
)->l_nsearchlist
; ++i
)
72 const ElfW(Sym
) *symtab
;
76 map
= (*scope
)->l_searchlist
[i
];
78 symtab
= ((void *) map
->l_addr
+ map
->l_info
[DT_SYMTAB
]->d_un
.d_ptr
);
79 strtab
= ((void *) map
->l_addr
+ map
->l_info
[DT_STRTAB
]->d_un
.d_ptr
);
81 /* Search the appropriate hash bucket in this object's symbol table
82 for a definition for the same symbol name. */
83 for (symidx
= map
->l_buckets
[hash
% map
->l_nbuckets
];
85 symidx
= map
->l_chain
[symidx
])
87 const ElfW(Sym
) *sym
= &symtab
[symidx
];
89 if (sym
->st_value
== 0 || /* No value. */
90 /* Cannot resolve to the location being filled in. */
91 reloc_addr
== map
->l_addr
+ sym
->st_value
||
92 (noplt
&& sym
->st_shndx
== SHN_UNDEF
)) /* Reject PLT. */
95 switch (ELFW(ST_TYPE
) (sym
->st_info
))
102 /* Not a code/data definition. */
106 if (sym
!= *ref
&& strcmp (strtab
+ sym
->st_name
, undef_name
))
107 /* Not the symbol we are looking for. */
110 switch (ELFW(ST_BIND
) (sym
->st_info
))
113 /* Global definition. Just what we need. */
117 /* Weak definition. Use this value if we don't find
122 weak_value
.a
= map
->l_addr
;
126 /* Local symbols are ignored. */
132 if (weak_value
.s
== NULL
&&
133 (*ref
== NULL
|| ELFW(ST_BIND
) ((*ref
)->st_info
) != STB_WEAK
))
135 /* We could find no value for a strong reference. */
136 const char msg
[] = "undefined symbol: ";
137 const size_t len
= strlen (undef_name
);
138 char buf
[sizeof msg
+ len
];
139 memcpy (buf
, msg
, sizeof msg
- 1);
140 memcpy (&buf
[sizeof msg
- 1], undef_name
, len
+ 1);
141 _dl_signal_error (0, reference_name
, buf
);
149 /* Cache the location of MAP's hash table. */
152 _dl_setup_hash (struct link_map
*map
)
154 ElfW(Symndx
) *hash
= (void *)(map
->l_addr
+ map
->l_info
[DT_HASH
]->d_un
.d_ptr
);
156 map
->l_nbuckets
= *hash
++;
158 map
->l_buckets
= hash
;
159 hash
+= map
->l_nbuckets
;