* sysdeps/generic/ldsodefs.h: Define DL_LOOKUP_SCOPE_LOCK.
authorUlrich Drepper <drepper@redhat.com>
Mon, 15 Jan 2007 20:48:56 +0000 (20:48 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 15 Jan 2007 20:48:56 +0000 (20:48 +0000)
* elf/dl-lookup.c (add_dependency): If scope map is locked, unlock
it before getting dl_load_lock and then relock.
(_dl_lookup_symbol_x): Pass flags to add_dependency.
When rerunning _dl_lookup_symbol_x, compute symbol_scope again in
case we unlocked the scope.
* elf/dl-runtime.c (_dl_fixup): Pass DL_LOOKUP_SCOPE_LOCK to
_dl_lookup_symbol_x in case we locked the scope.
(_dl_profile_fixup): Likewise.
* elf/dl-sym.c (do_sym): In flags passed to call_dl_lookup, also
set DL_LOOKUP_SCOPE_LOCK.

ChangeLog
elf/dl-lookup.c
elf/dl-runtime.c
elf/dl-sym.c
sysdeps/generic/ldsodefs.h

index fff37d5..5d60391 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-01-15  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/generic/ldsodefs.h: Define DL_LOOKUP_SCOPE_LOCK.
+       * elf/dl-lookup.c (add_dependency): If scope map is locked, unlock
+       it before getting dl_load_lock and then relock.
+       (_dl_lookup_symbol_x): Pass flags to add_dependency.
+       When rerunning _dl_lookup_symbol_x, compute symbol_scope again in
+       case we unlocked the scope.
+       * elf/dl-runtime.c (_dl_fixup): Pass DL_LOOKUP_SCOPE_LOCK to
+       _dl_lookup_symbol_x in case we locked the scope.
+       (_dl_profile_fixup): Likewise.
+       * elf/dl-sym.c (do_sym): In flags passed to call_dl_lookup, also
+       set DL_LOOKUP_SCOPE_LOCK.
+
 2007-01-13  Ulrich Drepper  <drepper@redhat.com>
 
        * inet/Makefile: Define CFLAGS-getsrvbynm_r.c and
index 019278c..a6a9584 100644 (file)
@@ -1,5 +1,5 @@
 /* Look up a symbol in the loaded objects.
-   Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2005, 2006, 2007 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
@@ -25,6 +25,7 @@
 #include <ldsodefs.h>
 #include <dl-hash.h>
 #include <dl-machine.h>
+#include <sysdep-cancel.h>
 #include <bits/libc-lock.h>
 #include <tls.h>
 
@@ -85,7 +86,7 @@ dl_new_hash (const char *s)
 /* Add extra dependency on MAP to UNDEF_MAP.  */
 static int
 internal_function
-add_dependency (struct link_map *undef_map, struct link_map *map)
+add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
 {
   struct link_map **list;
   struct link_map *runp;
@@ -98,8 +99,18 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
   if (undef_map == map)
     return 0;
 
-  /* Make sure nobody can unload the object while we are at it.  */
-  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  /* Make sure nobody can unload the object while we are at it.
+     If we hold a scope lock drop it now to avoid ABBA locking problems.  */
+  if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0 && !RTLD_SINGLE_THREAD_P)
+    {
+      __rtld_mrlock_unlock (undef_map->l_scope_lock);
+
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+      __rtld_mrlock_lock (undef_map->l_scope_lock);
+    }
+  else
+    __rtld_lock_lock_recursive (GL(dl_load_lock));
 
   /* Avoid references to objects which cannot be unloaded anyway.  */
   if (map->l_type != lt_loaded
@@ -226,9 +237,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
 
   bump_num_relocations ();
 
-  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
-     up a versioned symbol.  */
-  assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
+  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY and DL_LOOKUP_SCOPE_LOCK
+     is allowed if we look up a versioned symbol.  */
+  assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY
+                                       | DL_LOOKUP_SCOPE_LOCK)) == 0);
 
   size_t i = 0;
   if (__builtin_expect (skip_map != NULL, 0))
@@ -338,12 +350,13 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
         runtime lookups.  */
       && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
       /* Add UNDEF_MAP to the dependencies.  */
-      && add_dependency (undef_map, current_value.m) < 0)
+      && add_dependency (undef_map, current_value.m, flags) < 0)
       /* Something went wrong.  Perhaps the object we tried to reference
         was just removed.  Try finding another definition.  */
       return _dl_lookup_symbol_x (undef_name, undef_map, ref,
-                                 symbol_scope, version, type_class,
-                                 flags, skip_map);
+                                 (flags & DL_LOOKUP_SCOPE_LOCK) == 0
+                                 ? symbol_scope : undef_map->l_scope, version,
+                                 type_class, flags, skip_map);
 
   /* The object is used.  */
   current_value.m->l_used = 1;
index afc99f6..9ecf62b 100644 (file)
@@ -1,5 +1,5 @@
 /* On-demand PLT fixup for shared objects.
-   Copyright (C) 1995-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2006, 2007 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
@@ -93,14 +93,20 @@ _dl_fixup (
            version = NULL;
        }
 
+      /* We need to keep the scope around so do some locking.  This is
+        not necessary for objects which cannot be unloaded or when
+        we are not using any threads (yet).  */
+      int flags = DL_LOOKUP_ADD_DEPENDENCY;
       if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
-       __rtld_mrlock_lock (l->l_scope_lock);
+       {
+         __rtld_mrlock_lock (l->l_scope_lock);
+         flags |= DL_LOOKUP_SCOPE_LOCK;
+       }
 
-      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
-                                   l->l_scope, version, ELF_RTYPE_CLASS_PLT,
-                                   DL_LOOKUP_ADD_DEPENDENCY, NULL);
+      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
+                                   version, ELF_RTYPE_CLASS_PLT, flags, NULL);
 
-      if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
+      if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
        __rtld_mrlock_unlock (l->l_scope_lock);
 
       /* Currently result contains the base load address (or link map)
@@ -181,15 +187,21 @@ _dl_profile_fixup (
                version = NULL;
            }
 
+         /* We need to keep the scope around so do some locking.  This is
+            not necessary for objects which cannot be unloaded or when
+            we are not using any threads (yet).  */
+         int flags = DL_LOOKUP_ADD_DEPENDENCY;
          if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
-           __rtld_mrlock_lock (l->l_scope_lock);
+           {
+             __rtld_mrlock_lock (l->l_scope_lock);
+             flags |= DL_LOOKUP_SCOPE_LOCK;
+           }
 
-         result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym,
-                                       l->l_scope, version,
-                                       ELF_RTYPE_CLASS_PLT,
-                                       DL_LOOKUP_ADD_DEPENDENCY, NULL);
+         result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
+                                       &defsym, l->l_scope, version,
+                                       ELF_RTYPE_CLASS_PLT, flags, NULL);
 
-         if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
+         if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
            __rtld_mrlock_unlock (l->l_scope_lock);
 
          /* Currently result contains the base load address (or link map)
index 88a5adb..1c3ab5c 100644 (file)
@@ -1,5 +1,5 @@
 /* Look up a symbol in a shared object loaded by `dlopen'.
-   Copyright (C) 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
+   Copyright (C) 1999-2002,2004,2006,2007 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
@@ -126,7 +126,7 @@ do_sym (void *handle, const char *name, void *who,
          args.name = name;
          args.map = match;
          args.vers = vers;
-         args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY;
+         args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_SCOPE_LOCK;
          args.refp = &ref;
 
          const char *objname;
index dda91bb..a9d20b2 100644 (file)
@@ -1,5 +1,5 @@
 /* Run-time dynamic linker data structures for loaded ELF shared objects.
-   Copyright (C) 1995-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2006, 2007 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
@@ -838,7 +838,9 @@ enum
     DL_LOOKUP_ADD_DEPENDENCY = 1,
     /* Return most recent version instead of default version for
        unversioned lookup.  */
-    DL_LOOKUP_RETURN_NEWEST = 2
+    DL_LOOKUP_RETURN_NEWEST = 2,
+    /* Set if the scopr lock in the UNDEF_MAP is taken.  */
+    DL_LOOKUP_SCOPE_LOCK = 4
   };
 
 /* Lookup versioned symbol.  */
@@ -847,7 +849,7 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
                                     const ElfW(Sym) **sym,
                                     struct r_scope_elem *symbol_scope[],
                                     const struct r_found_version *version,
-                                    int type_class, int explicit,
+                                    int type_class, int flags,
                                     struct link_map *skip_map)
      internal_function attribute_hidden;