📄 dl-lookup.c
字号:
if (! _dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i, skip_map, 0)) while (*++scope) if (_dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, skip_map, 0)) break; if (__builtin_expect (current_value.s == NULL, 0)) { *ref = NULL; return 0; } protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n", (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], protected ? "protected" : "normal", undef_name); if (__builtin_expect (protected == 0, 1)) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } else { /* It is very tricky. We need to figure out what value to return for the protected symbol. */ struct sym_val protected_value = { NULL, NULL }; if (i >= (*scope)->r_nlist || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, i, skip_map, ELF_RTYPE_CLASS_PLT)) while (*++scope) if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0, skip_map, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } return LOOKUP_VALUE (undef_map); }}/* This function works like _dl_lookup_symbol but it takes an additional arguement with the version number of the requested symbol. XXX We'll see whether we need this separate function. */lookup_tinternal_function_dl_lookup_versioned_symbol (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 explicit){ unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; int protected; ++_dl_num_relocations; /* Search the relevant loaded objects for a definition. */ for (scope = symbol_scope; *scope; ++scope) { int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope, 0, version, NULL, type_class); if (res > 0) { /* We have to check whether this would bind UNDEF_MAP to an object in the global scope which was dynamically loaded. In this case we have to prevent the latter from being unloaded unless the UNDEF_MAP object is also unloaded. */ if (__builtin_expect (current_value.m->l_type == lt_loaded, 0) /* Don't do this for explicit lookups as opposed to implicit runtime lookups. */ && ! explicit /* Add UNDEF_MAP to the dependencies. */ && add_dependency (undef_map, current_value.m) < 0) /* Something went wrong. Perhaps the object we tried to reference was just removed. Try finding another definition. */ return _dl_lookup_versioned_symbol (undef_name, undef_map, ref, symbol_scope, version, type_class, 0); break; } if (__builtin_expect (res, 0) < 0) { /* Oh, oh. The file named in the relocation entry does not contain the needed symbol. */ const char *reference_name = undef_map ? undef_map->l_name : NULL; /* XXX We cannot translate the message. */ _dl_signal_cerror (0, (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), N_("relocation error"), make_string ("symbol ", undef_name, ", version ", version->name, " not defined in file ", version->filename, " with link time reference", res == -2 ? " (no version symbols)" : "")); *ref = NULL; return 0; } } if (__builtin_expect (current_value.s == NULL, 0)) { if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) { /* We could find no value for a strong reference. */ const char *reference_name = undef_map ? undef_map->l_name : NULL; /* XXX We cannot translate the message. */ _dl_signal_cerror (0, (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), NULL, make_string (undefined_msg, undef_name, ", version ", version->name ?: NULL)); } *ref = NULL; return 0; } protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) { const char *reference_name = undef_map ? undef_map->l_name : NULL; _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n", (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], protected ? "protected" : "normal", undef_name, version->name); } if (__builtin_expect (protected == 0, 1)) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } else { /* It is very tricky. We need to figure out what value to return for the protected symbol */ struct sym_val protected_value = { NULL, NULL }; for (scope = symbol_scope; *scope; ++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, *scope, 0, version, NULL, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } return LOOKUP_VALUE (undef_map); }}/* Similar to _dl_lookup_symbol_skip but takes an additional argument with the version we are looking for. */lookup_tinternal_function_dl_lookup_versioned_symbol_skip (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, struct link_map *skip_map){ const char *reference_name = undef_map ? undef_map->l_name : NULL; const unsigned long int hash = _dl_elf_hash (undef_name); struct sym_val current_value = { NULL, NULL }; struct r_scope_elem **scope; size_t i; int protected; ++_dl_num_relocations; /* Search the relevant loaded objects for a definition. */ scope = symbol_scope; for (i = 0; (*scope)->r_list[i] != skip_map; ++i) assert (i < (*scope)->r_nlist); if (! _dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope, i, version, skip_map, 0)) while (*++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope, 0, version, skip_map, 0)) break; if (__builtin_expect (current_value.s == NULL, 0)) { if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) { /* We could find no value for a strong reference. */ const size_t len = strlen (undef_name); char buf[sizeof undefined_msg + len]; char *tmp; tmp = memcpy (buf, undefined_msg, sizeof undefined_msg - 1); tmp += (sizeof undefined_msg - 1); memcpy (tmp, undef_name, len + 1); /* XXX We cannot translate the messages. */ _dl_signal_cerror (0, (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), NULL, buf); } *ref = NULL; return 0; } protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED; if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0)) _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n", (reference_name && reference_name[0] ? reference_name : (_dl_argv[0] ?: "<main program>")), current_value.m->l_name[0] ? current_value.m->l_name : _dl_argv[0], protected ? "protected" : "normal", undef_name, version->name); if (__builtin_expect (protected == 0, 1)) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } else { /* It is very tricky. We need to figure out what value to return for the protected symbol */ struct sym_val protected_value = { NULL, NULL }; if (i >= (*scope)->r_nlist || !_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, *scope, i, version, skip_map, ELF_RTYPE_CLASS_PLT)) while (*++scope) if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value, *scope, 0, version, skip_map, ELF_RTYPE_CLASS_PLT)) break; if (protected_value.s == NULL || protected_value.m == undef_map) { *ref = current_value.s; return LOOKUP_VALUE (current_value.m); } return LOOKUP_VALUE (undef_map); }}/* Cache the location of MAP's hash table. */voidinternal_function_dl_setup_hash (struct link_map *map){ Elf_Symndx *hash; Elf_Symndx nchain; if (!map->l_info[DT_HASH]) return; hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr); map->l_nbuckets = *hash++; nchain = *hash++; map->l_buckets = hash; hash += map->l_nbuckets; map->l_chain = hash;}/* These are here so that we only inline do_lookup{,_versioned} in the common case, not everywhere. */static intinternal_function_dl_do_lookup (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, struct link_map *skip, int type_class){ return do_lookup (undef_name, hash, ref, result, scope, i, skip, type_class);}static intinternal_function_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result, struct r_scope_elem *scope, size_t i, const struct r_found_version *const version, struct link_map *skip, int type_class){ return do_lookup_versioned (undef_name, hash, ref, result, scope, i, version, skip, type_class);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -