1 /* Look up a symbol in a single specified object.
2 Copyright (C) 1995-2023 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
21 #include <elf_machine_sym_no_match.h>
24 /* This function corresponds to do_lookup_x in elf/dl-lookup.c. The
25 variant here is simplified because it requires symbol
27 static const ElfW(Sym
) *
28 check_match (const struct link_map
*const map
, const char *const undef_name
,
29 const char *version
, uint32_t version_hash
,
30 const Elf_Symndx symidx
)
32 const ElfW(Sym
) *symtab
= (const void *) D_PTR (map
, l_info
[DT_SYMTAB
]);
33 const ElfW(Sym
) *sym
= &symtab
[symidx
];
35 unsigned int stt
= ELFW(ST_TYPE
) (sym
->st_info
);
36 if (__glibc_unlikely ((sym
->st_value
== 0 /* No value. */
37 && sym
->st_shndx
!= SHN_ABS
39 || elf_machine_sym_no_match (sym
)))
42 /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
43 STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
44 code/data definitions. */
46 ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
47 | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
48 if (__glibc_unlikely (((1 << stt
) & ALLOWED_STT
) == 0))
51 const char *strtab
= (const void *) D_PTR (map
, l_info
[DT_STRTAB
]);
53 if (strcmp (strtab
+ sym
->st_name
, undef_name
) != 0)
54 /* Not the symbol we are looking for. */
57 ElfW(Half
) ndx
= map
->l_versyms
[symidx
] & 0x7fff;
58 if (map
->l_versions
[ndx
].hash
!= version_hash
59 || strcmp (map
->l_versions
[ndx
].name
, version
) != 0)
60 /* It's not the version we want. */
67 /* This function corresponds to do_lookup_x in elf/dl-lookup.c. The
68 variant here is simplified because it does not search object
69 dependencies. It is optimized for a successful lookup. */
71 _dl_lookup_direct (struct link_map
*map
,
72 const char *undef_name
, uint32_t new_hash
,
73 const char *version
, uint32_t version_hash
)
75 const ElfW(Addr
) *bitmask
= map
->l_gnu_bitmask
;
76 if (__glibc_likely (bitmask
!= NULL
))
78 Elf32_Word bucket
= map
->l_gnu_buckets
[new_hash
% map
->l_nbuckets
];
81 const Elf32_Word
*hasharr
= &map
->l_gnu_chain_zero
[bucket
];
84 if (((*hasharr
^ new_hash
) >> 1) == 0)
86 Elf_Symndx symidx
= ELF_MACHINE_HASH_SYMIDX (map
, hasharr
);
87 const ElfW(Sym
) *sym
= check_match (map
, undef_name
,
88 version
, version_hash
,
93 while ((*hasharr
++ & 1u) == 0);
98 /* Fallback code for lack of GNU_HASH support. */
99 uint32_t old_hash
= _dl_elf_hash (undef_name
);
101 /* Use the old SysV-style hash table. Search the appropriate
102 hash bucket in this object's symbol table for a definition
103 for the same symbol name. */
104 for (Elf_Symndx symidx
= map
->l_buckets
[old_hash
% map
->l_nbuckets
];
106 symidx
= map
->l_chain
[symidx
])
108 const ElfW(Sym
) *sym
= check_match (map
, undef_name
,
109 version
, version_hash
, symidx
);