about summary refs log tree commit diff
path: root/elf/dl-sym.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-sym.c')
-rw-r--r--elf/dl-sym.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index fa0e3a67fc..88a5adb0d5 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -1,5 +1,5 @@
 /* Look up a symbol in a shared object loaded by `dlopen'.
-   Copyright (C) 1999-2002,2004,2006,2007 Free Software Foundation, Inc.
+   Copyright (C) 1999,2000,2001,2002,2004,2006 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
@@ -26,12 +26,10 @@
 #include <ldsodefs.h>
 #include <dl-hash.h>
 #include <sysdep-cancel.h>
-#ifdef USE_TLS
-# include <dl-tls.h>
-#endif
+#include <dl-tls.h>
 
 
-#if defined USE_TLS && defined SHARED
+#ifdef SHARED
 /* Systems which do not have tls_index also probably have to define
    DONT_USE_TLS_INDEX.  */
 
@@ -100,9 +98,10 @@ do_sym (void *handle, const char *name, void *who,
   for (Lmid_t ns = 0; ns < 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)))
+      if (caller >= l->l_map_start && caller < l->l_map_end)
 	{
+	  /* There must be exactly one DSO for the range of the virtual
+	     memory.  Otherwise something is really broken.  */
 	  match = l;
 	  break;
 	}
@@ -114,13 +113,15 @@ do_sym (void *handle, const char *name, void *who,
 	 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)
+      if (match->l_type != lt_loaded || 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
 	{
+	  __rtld_mrlock_lock (match->l_scope_lock);
+
 	  struct call_dl_lookup_args args;
 	  args.name = name;
 	  args.map = match;
@@ -128,15 +129,13 @@ do_sym (void *handle, const char *name, void *who,
 	  args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY;
 	  args.refp = &ref;
 
-	  THREAD_GSCOPE_SET_FLAG ();
-
 	  const char *objname;
 	  const char *errstring = NULL;
 	  bool malloced;
 	  int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
 					  call_dl_lookup, &args);
 
-	  THREAD_GSCOPE_RESET_FLAG ();
+	  __rtld_mrlock_unlock (match->l_scope_lock);
 
 	  if (__builtin_expect (errstring != NULL, 0))
 	    {
@@ -183,7 +182,7 @@ RTLD_NEXT used in code not dynamically loaded"));
     {
       void *value;
 
-#if defined USE_TLS && defined SHARED
+#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.  */