diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | elf/Versions | 4 | ||||
-rw-r--r-- | elf/dl-addr.c | 18 | ||||
-rw-r--r-- | elf/dl-open.c | 40 | ||||
-rw-r--r-- | elf/dl-sym.c | 14 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 4 |
6 files changed, 51 insertions, 38 deletions
@@ -1,3 +1,12 @@ +2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com> + + * elf/Versions (ld): Add _dl_find_dso_for_object. + * elf/dl-addr.c (_dl_addr): Use _dl_find_dso_for_object. + * elf/dl-open.c (_dl_find_dso_for_object): New function. + (dl_open_worker): Use _dl_find_dso_for_object. + * elf/dl-sym.c (do_sym): Likewise. + * sysdeps/generic/ldsodefs.h: Declare _dl_find_dso_for_object. + 2013-02-18 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> * sysdeps/s390/s390-64/dl-trampoline.S (_dl_runtime_resolve): diff --git a/elf/Versions b/elf/Versions index d6b5e50..2383992 100644 --- a/elf/Versions +++ b/elf/Versions @@ -51,8 +51,8 @@ ld { # Those are in the dynamic linker, but used by libc.so. __libc_enable_secure; _dl_allocate_tls; _dl_allocate_tls_init; - _dl_argv; _dl_get_tls_static_info; _dl_deallocate_tls; - _dl_make_stack_executable; _dl_out_of_memory; + _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; + _dl_deallocate_tls; _dl_make_stack_executable; _dl_out_of_memory; _dl_rtld_di_serinfo; _dl_starting_up; _dl_tls_setup; _rtld_global; _rtld_global_ro; diff --git a/elf/dl-addr.c b/elf/dl-addr.c index 91cc443..a533466 100644 --- a/elf/dl-addr.c +++ b/elf/dl-addr.c @@ -130,18 +130,14 @@ _dl_addr (const void *address, Dl_info *info, /* Protect against concurrent loads and unloads. */ __rtld_lock_lock_recursive (GL(dl_load_lock)); - /* Find the highest-addressed object that ADDRESS is not below. */ - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next) - if (addr >= l->l_map_start && addr < l->l_map_end - && (l->l_contiguous || _dl_addr_inside_object (l, addr))) - { - determine_info (addr, l, info, mapp, symbolp); - result = 1; - goto out; - } + struct link_map *l = _dl_find_dso_for_object (addr); + + if (l) + { + determine_info (addr, l, info, mapp, symbolp); + result = 1; + } - out: __rtld_lock_unlock_recursive (GL(dl_load_lock)); return result; diff --git a/elf/dl-open.c b/elf/dl-open.c index 67f7e73..201d95d 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -165,6 +165,29 @@ add_to_global (struct link_map *new) return 0; } +/* Search link maps in all namespaces for the DSO that containes the object at + address ADDR. Returns the pointer to the link map of the matching DSO, or + NULL if a match is not found. */ +struct link_map * +internal_function +_dl_find_dso_for_object (const ElfW(Addr) addr) +{ + struct link_map *l; + + /* Find the highest-addressed object that ADDR is not below. */ + for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) + for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) + if (addr >= l->l_map_start && addr < l->l_map_end + && (l->l_contiguous + || _dl_addr_inside_object (l, (ElfW(Addr)) addr))) + { + assert (ns == l->l_ns); + return l; + } + return NULL; +} +rtld_hidden_def (_dl_find_dso_for_object); + static void dl_open_worker (void *a) { @@ -194,20 +217,11 @@ dl_open_worker (void *a) call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; #endif - struct link_map *l; - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - if (caller_dlopen >= (const void *) l->l_map_start - && caller_dlopen < (const void *) l->l_map_end - && (l->l_contiguous - || _dl_addr_inside_object (l, (ElfW(Addr)) caller_dlopen))) - { - assert (ns == l->l_ns); - call_map = l; - goto found_caller; - } + struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen); + + if (l) + call_map = l; - found_caller: if (args->nsid == __LM_ID_CALLER) { #ifndef SHARED diff --git a/elf/dl-sym.c b/elf/dl-sym.c index d2b4db7..05de6c1 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -91,20 +91,10 @@ do_sym (void *handle, const char *name, void *who, 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 = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - - /* Find the highest-addressed object that CALLER is not below. */ - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; - l = l->l_next) - if (caller >= l->l_map_start && caller < l->l_map_end - && (l->l_contiguous || _dl_addr_inside_object (l, caller))) - { - match = l; - break; - } + struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded; if (handle == RTLD_DEFAULT) { diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index d6350fa..01a2712 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1006,6 +1006,10 @@ extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) /* Show show of an object. */ extern void _dl_show_scope (struct link_map *new, int from); +extern struct link_map *_dl_find_dso_for_object (const ElfW(Addr) addr) + internal_function; +rtld_hidden_proto (_dl_find_dso_for_object) + __END_DECLS #endif /* ldsodefs.h */ |