about summary refs log tree commit diff
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 */