1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: static int
25: __attribute_noinline__
26: do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
27: unsigned long int *old_hash, const ElfW(Sym) *ref,
28: struct sym_val *result, struct r_scope_elem *scope, size_t i,
29: const struct r_found_version *const version, int flags,
30: struct link_map *skip, int type_class)
31: {
32: size_t n = scope->r_nlist;
33:
34:
35:
36:
37: __asm volatile ("" : "+r" (n), "+m" (scope->r_list));
38: struct link_map **list = scope->r_list;
39:
40: do
41: {
42:
43: Elf_Symndx symidx;
44: int num_versions = 0;
45: const ElfW(Sym) *versioned_sym = NULL;
46:
47: const struct link_map *map = list[i]->l_real;
48:
49:
50: if (map == skip)
51: continue;
52:
53:
54: if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
55: continue;
56:
57:
58: if (map->l_removed)
59: continue;
60:
61:
62: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0))
63: _dl_debug_printf ("symbol=%s; lookup in file=%s [%lu]\n",
64: undef_name,
65: map->l_name[0] ? map->l_name : rtld_progname,
66: map->l_ns);
67:
68:
69: if (map->l_nbuckets == 0)
70: continue;
71:
72:
73: const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
74: const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
75:
76:
77:
78: const ElfW(Sym) *
79: __attribute_noinline__
80: check_match (const ElfW(Sym) *sym)
81: {
82: assert (ELF_RTYPE_CLASS_PLT == 1);
83: if (__builtin_expect ((sym->st_value == 0
84: && ELFW(ST_TYPE) (sym->st_info) != STT_TLS)
85: || (type_class & (sym->st_shndx == SHN_UNDEF)),
86: 0))
87: return NULL;
88:
89: if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC
90: && ELFW(ST_TYPE) (sym->st_info) != STT_COMMON
91: && ELFW(ST_TYPE) (sym->st_info) != STT_TLS, 0))
92:
93:
94:
95: return NULL;
96:
97: if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
98:
99: return NULL;
100:
101: const ElfW(Half) *verstab = map->l_versyms;
102: if (version != NULL)
103: {
104: if (__builtin_expect (verstab == NULL, 0))
105: {
106:
107:
108:
109:
110:
111:
112:
113:
114: assert (version->filename == NULL
115: || ! _dl_name_match_p (version->filename, map));
116:
117:
118: }
119: else
120: {
121:
122:
123: ElfW(Half) ndx = verstab[symidx] & 0x7fff;
124: if ((map->l_versions[ndx].hash != version->hash
125: || strcmp (map->l_versions[ndx].name, version->name))
126: && (version->hidden || map->l_versions[ndx].hash
127: || (verstab[symidx] & 0x8000)))
128:
129: return NULL;
130: }
131: }
132: else
133: {
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152: if (verstab != NULL)
153: {
154: if ((verstab[symidx] & 0x7fff)
155: >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
156: {
157:
158: if ((verstab[symidx] & 0x8000) == 0
159: && num_versions++ == 0)
160:
161: versioned_sym = sym;
162:
163: return NULL;
164: }
165: }
166: }
167:
168:
169: return sym;
170: }
171:
172: const ElfW(Sym) *sym;
173: const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
174: if (__builtin_expect (bitmask != NULL, 1))
175: {
176: ElfW(Addr) bitmask_word
177: = bitmask[(new_hash / __ELF_NATIVE_CLASS)
178: & map->l_gnu_bitmask_idxbits];
179:
180: unsigned int hashbit1 = new_hash & (__ELF_NATIVE_CLASS - 1);
181: unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift)
182: & (__ELF_NATIVE_CLASS - 1));
183:
184: if (__builtin_expect ((bitmask_word >> hashbit1)
185: & (bitmask_word >> hashbit2) & 1, 0))
186: {
187: Elf32_Word bucket = map->l_gnu_buckets[new_hash
188: % map->l_nbuckets];
189: if (bucket != 0)
190: {
191: const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
192:
193: do
194: if (((*hasharr ^ new_hash) >> 1) == 0)
195: {
196: symidx = hasharr - map->l_gnu_chain_zero;
197: sym = check_match (&symtab[symidx]);
198: if (sym != NULL)
199: goto found_it;
200: }
201: while ((*hasharr++ & 1u) == 0);
202: }
203: }
204:
205: symidx = SHN_UNDEF;
206: }
207: else
208: {
209: if (*old_hash == 0xffffffff)
210: *old_hash = _dl_elf_hash (undef_name);
211:
212:
213:
214:
215: for (symidx = map->l_buckets[*old_hash % map->l_nbuckets];
216: symidx != STN_UNDEF;
217: symidx = map->l_chain[symidx])
218: {
219: sym = check_match (&symtab[symidx]);
220: if (sym != NULL)
221: goto found_it;
222: }
223: }
224:
225:
226:
227:
228:
229: sym = num_versions == 1 ? versioned_sym : NULL;
230:
231: if (sym != NULL)
232: {
233: found_it:
234: switch (ELFW(ST_BIND) (sym->st_info))
235: {
236: case STB_WEAK:
237:
238: if (__builtin_expect (GLRO(dl_dynamic_weak), 0))
239: {
240: if (! result->s)
241: {
242: result->s = sym;
243: result->m = (struct link_map *) map;
244: }
245: break;
246: }
247:
248: case STB_GLOBAL:
249:
250: result->s = sym;
251: result->m = (struct link_map *) map;
252: return 1;
253: default:
254:
255: break;
256: }
257: }
258:
259:
260:
261: if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
262: && __builtin_expect (_dl_name_match_p (version->filename, map), 0))
263: return -1;
264: }
265: while (++i < n);
266:
267:
268: return 0;
269: }