1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
lookup_t _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], const struct r_found_version *version, int type_class, int flags, struct link_map *skip_map) { const uint_fast32_t new_hash = dl_new_hash (undef_name); unsigned long int old_hash = 0xffffffff; struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope = symbol_scope;
bump_num_relocations ();
assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST));
size_t i = 0; if (__glibc_unlikely (skip_map != NULL)) while ((*scope)->r_list[i] != skip_map) ++i;
for (size_t start = i; *scope != NULL; start = 0, ++scope) if (do_lookup_x (undef_name, new_hash, &old_hash, *ref, ¤t_value, *scope, start, version, flags, skip_map, type_class, undef_map) != 0) break;
if (__glibc_unlikely (current_value.s == NULL)) { if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)) { const char *reference_name = undef_map ? undef_map->l_name : ""; const char *versionstr = version ? ", version " : ""; const char *versionname = (version && version->name ? version->name : ""); struct dl_exception exception; _dl_exception_create_format (&exception, DSO_FILENAME (reference_name), "undefined symbol: %s%s%s", undef_name, versionstr, versionname); _dl_signal_cexception (0, &exception, N_("symbol lookup error")); _dl_exception_free (&exception); } *ref = NULL; return 0; }
int protected = (*ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED); if (__glibc_unlikely (protected != 0)) { if (type_class == ELF_RTYPE_CLASS_PLT) { if (current_value.s != NULL && current_value.m != undef_map) { current_value.s = *ref; current_value.m = undef_map; } } else { struct sym_val protected_value = { NULL, NULL };
for (scope = symbol_scope; *scope != NULL; i = 0, ++scope) if (do_lookup_x (undef_name, new_hash, &old_hash, *ref, &protected_value, *scope, i, version, flags, skip_map, (ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA && ELFW(ST_TYPE) ((*ref)->st_info) == STT_OBJECT && type_class == ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA) ? ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA : ELF_RTYPE_CLASS_PLT, NULL) != 0) break;
if (protected_value.s != NULL && protected_value.m != undef_map) { current_value.s = *ref; current_value.m = undef_map; } } }
if (__glibc_unlikely (current_value.m->l_type == lt_loaded)
&& (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0 && add_dependency (undef_map, current_value.m, flags) < 0)
return _dl_lookup_symbol_x (undef_name, undef_map, ref, (flags & DL_LOOKUP_GSCOPE_LOCK) ? undef_map->l_scope : symbol_scope, version, type_class, flags, skip_map);
if (__glibc_unlikely (current_value.m->l_used == 0)) current_value.m->l_used = 1;
if (__glibc_unlikely (GLRO(dl_debug_mask) & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK))) _dl_debug_bindings (undef_name, undef_map, ref, ¤t_value, version, type_class, protected);
*ref = current_value.s; return LOOKUP_VALUE (current_value.m); }
|