]> sourceware.org Git - glibc.git/blame - elf/dl-lookup.c
Sat May 6 11:06:47 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>
23
24/* Search loaded objects' symbol tables for a definition of
25 the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since
26 that is the object making the reference. */
27
28Elf32_Addr
29_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
421f82e5
RM
30 struct link_map *symbol_scope,
31 const char *reference_name)
d66e34cd
RM
32{
33 unsigned long int hash = elf_hash (undef_name);
34 struct link_map *map;
35 struct
36 {
37 Elf32_Addr a;
38 const Elf32_Sym *s;
39 } weak_value = { 0, NULL };
40
41 /* Search the relevant loaded objects for a definition. */
42 for (map = symbol_scope; map; map = map->l_next)
43 {
44 const Elf32_Sym *symtab;
45 const char *strtab;
46 Elf32_Word symidx;
47
48 symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
49 strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
50
51 /* Search the appropriate hash bucket in this object's symbol table
52 for a definition for the same symbol name. */
53 for (symidx = map->l_buckets[hash % map->l_nbuckets];
54 symidx != STN_UNDEF;
55 symidx = map->l_chain[symidx])
56 {
57 const Elf32_Sym *sym = &symtab[symidx];
58
59 if (sym->st_value == 0)
60 continue;
61
62 switch (ELF32_ST_TYPE (sym->st_info))
63 {
64 case STT_NOTYPE:
65 case STT_FUNC:
66 case STT_OBJECT:
67 break;
68 default:
69 /* Not a code/data definition. */
70 continue;
71 }
72
73 if (sym == *ref)
74 /* This is the same symbol we are looking for the value for.
75 If it is a PLT entry, it will have a value of its own;
76 but that is not what we are looking for. */
77 continue;
78
79 if (strcmp (strtab + sym->st_name, undef_name))
80 /* Not the symbol we are looking for. */
81 continue;
82
83 switch (ELF32_ST_BIND (sym->st_info))
84 {
85 case STB_GLOBAL:
86 /* Global definition. Just what we need. */
87 *ref = sym;
88 return map->l_addr;
89 case STB_WEAK:
90 /* Weak definition. Use this value if we don't find another. */
91 if (weak_value.a == 0)
92 {
93 weak_value.s = sym;
94 weak_value.a = map->l_addr;
95 }
96 break;
97 default:
98 /* Local symbols are ignored. */
99 break;
100 }
101 }
102 }
103
104 if (weak_value.s == NULL)
105 {
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);
421f82e5 110 _dl_signal_error (0, reference_name, msg);
d66e34cd
RM
111 }
112
113 *ref = weak_value.s;
114 return weak_value.a;
115}
116
117
118/* Cache the location of MAP's hash table. */
119
120void
121_dl_setup_hash (struct link_map *map)
122{
123 Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
124 Elf32_Word nchain;
125 map->l_nbuckets = *hash++;
126 nchain = *hash++;
127 map->l_buckets = hash;
128 hash += map->l_nbuckets;
129 map->l_chain = hash;
130}
This page took 0.036836 seconds and 5 git commands to generate.