aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--elf/Versions4
-rw-r--r--elf/dl-addr.c18
-rw-r--r--elf/dl-open.c40
-rw-r--r--elf/dl-sym.c14
-rw-r--r--sysdeps/generic/ldsodefs.h4
6 files changed, 51 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 477ec3b07e..0cc0fed2be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 d6b5e5034d..238399232d 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 91cc443439..a53346627f 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 67f7e739bd..201d95d1be 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 d2b4db7ec0..05de6c1c06 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 d6350facd6..01a2712f33 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 */