diff options
Diffstat (limited to 'elf/dl-sym.c')
-rw-r--r-- | elf/dl-sym.c | 274 |
1 files changed, 0 insertions, 274 deletions
diff --git a/elf/dl-sym.c b/elf/dl-sym.c deleted file mode 100644 index 7cd6e97643..0000000000 --- a/elf/dl-sym.c +++ /dev/null @@ -1,274 +0,0 @@ -/* Look up a symbol in a shared object loaded by `dlopen'. - Copyright (C) 1999-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdlib.h> -#include <libintl.h> - -#include <dlfcn.h> -#include <ldsodefs.h> -#include <dl-hash.h> -#include <sysdep-cancel.h> -#include <dl-tls.h> -#include <dl-irel.h> - - -#ifdef SHARED -/* Systems which do not have tls_index also probably have to define - DONT_USE_TLS_INDEX. */ - -# ifndef __TLS_GET_ADDR -# define __TLS_GET_ADDR __tls_get_addr -# endif - -/* Return the symbol address given the map of the module it is in and - the symbol record. This is used in dl-sym.c. */ -static void * -internal_function -_dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref) -{ -# ifndef DONT_USE_TLS_INDEX - tls_index tmp = - { - .ti_module = map->l_tls_modid, - .ti_offset = ref->st_value - }; - - return __TLS_GET_ADDR (&tmp); -# else - return __TLS_GET_ADDR (map->l_tls_modid, ref->st_value); -# endif -} -#endif - - -struct call_dl_lookup_args -{ - /* Arguments to do_dlsym. */ - struct link_map *map; - const char *name; - struct r_found_version *vers; - int flags; - - /* Return values of do_dlsym. */ - lookup_t loadbase; - const ElfW(Sym) **refp; -}; - -static void -call_dl_lookup (void *ptr) -{ - struct call_dl_lookup_args *args = (struct call_dl_lookup_args *) ptr; - args->map = GLRO(dl_lookup_symbol_x) (args->name, args->map, args->refp, - args->map->l_scope, args->vers, 0, - args->flags, NULL); -} - - -static void * -internal_function -do_sym (void *handle, const char *name, void *who, - struct r_found_version *vers, int flags) -{ - const ElfW(Sym) *ref = NULL; - lookup_t result; - ElfW(Addr) caller = (ElfW(Addr)) who; - - struct link_map *l = _dl_find_dso_for_object (caller); - /* If the address is not recognized the call comes from the main - program (we hope). */ - struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded; - - if (handle == RTLD_DEFAULT) - { - /* Search the global scope. We have the simple case where - we look up in the scope of an object which was part of - the initial binary. And then the more complex part - where the object is dynamically loaded and the scope - array can change. */ - if (RTLD_SINGLE_THREAD_P) - result = GLRO(dl_lookup_symbol_x) (name, match, &ref, - match->l_scope, vers, 0, - flags | DL_LOOKUP_ADD_DEPENDENCY, - NULL); - else - { - struct call_dl_lookup_args args; - args.name = name; - args.map = match; - args.vers = vers; - args.flags - = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK; - args.refp = &ref; - - THREAD_GSCOPE_SET_FLAG (); - - const char *objname; - const char *errstring = NULL; - bool malloced; - int err = _dl_catch_error (&objname, &errstring, &malloced, - call_dl_lookup, &args); - - THREAD_GSCOPE_RESET_FLAG (); - - if (__glibc_unlikely (errstring != NULL)) - { - /* The lookup was unsuccessful. Rethrow the error. */ - char *errstring_dup = strdupa (errstring); - char *objname_dup = strdupa (objname); - if (malloced) - free ((char *) errstring); - - _dl_signal_error (err, objname_dup, NULL, errstring_dup); - /* NOTREACHED */ - } - - result = args.map; - } - } - else if (handle == RTLD_NEXT) - { - if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded)) - { - if (match == NULL - || caller < match->l_map_start - || caller >= match->l_map_end) - _dl_signal_error (0, NULL, NULL, N_("\ -RTLD_NEXT used in code not dynamically loaded")); - } - - struct link_map *l = match; - while (l->l_loader != NULL) - l = l->l_loader; - - result = GLRO(dl_lookup_symbol_x) (name, match, &ref, l->l_local_scope, - vers, 0, 0, match); - } - else - { - /* Search the scope of the given object. */ - struct link_map *map = handle; - result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope, - vers, 0, flags, NULL); - } - - if (ref != NULL) - { - void *value; - -#ifdef SHARED - if (ELFW(ST_TYPE) (ref->st_info) == STT_TLS) - /* The found symbol is a thread-local storage variable. - Return the address for to the current thread. */ - value = _dl_tls_symaddr (result, ref); - else -#endif - value = DL_SYMBOL_ADDRESS (result, ref); - - /* Resolve indirect function address. */ - if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC)) - { - DL_FIXUP_VALUE_TYPE fixup - = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value); - fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup)); - value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup); - } - -#ifdef SHARED - /* Auditing checkpoint: we have a new binding. Provide the - auditing libraries the possibility to change the value and - tell us whether further auditing is wanted. */ - if (__glibc_unlikely (GLRO(dl_naudit) > 0)) - { - const char *strtab = (const char *) D_PTR (result, - l_info[DT_STRTAB]); - /* Compute index of the symbol entry in the symbol table of - the DSO with the definition. */ - unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, - l_info[DT_SYMTAB])); - - if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) - { - unsigned int altvalue = 0; - struct audit_ifaces *afct = GLRO(dl_audit); - /* Synthesize a symbol record where the st_value field is - the result. */ - ElfW(Sym) sym = *ref; - sym.st_value = (ElfW(Addr)) value; - - for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) - { - if (afct->symbind != NULL - && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM) - != 0 - || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO) - != 0))) - { - unsigned int flags = altvalue | LA_SYMB_DLSYM; - uintptr_t new_value - = afct->symbind (&sym, ndx, - &match->l_audit[cnt].cookie, - &result->l_audit[cnt].cookie, - &flags, strtab + ref->st_name); - if (new_value != (uintptr_t) sym.st_value) - { - altvalue = LA_SYMB_ALTVALUE; - sym.st_value = new_value; - } - } - - afct = afct->next; - } - - value = (void *) sym.st_value; - } - } -#endif - - return value; - } - - return NULL; -} - - -void * -internal_function -_dl_vsym (void *handle, const char *name, const char *version, void *who) -{ - struct r_found_version vers; - - /* Compute hash value to the version string. */ - vers.name = version; - vers.hidden = 1; - vers.hash = _dl_elf_hash (version); - /* We don't have a specific file where the symbol can be found. */ - vers.filename = NULL; - - return do_sym (handle, name, who, &vers, 0); -} - - -void * -internal_function -_dl_sym (void *handle, const char *name, void *who) -{ - return do_sym (handle, name, who, NULL, DL_LOOKUP_RETURN_NEWEST); -} |