Back to index

glibc  2.9
dl-open.c
Go to the documentation of this file.
00001 /* Load a shared object at runtime, relocate it, and run its initializer.
00002    Copyright (C) 1996-2004, 2005, 2006, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <dlfcn.h>
00022 #include <errno.h>
00023 #include <libintl.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <unistd.h>
00028 #include <sys/mman.h>              /* Check whether MAP_COPY is defined.  */
00029 #include <sys/param.h>
00030 #include <bits/libc-lock.h>
00031 #include <ldsodefs.h>
00032 #include <bp-sym.h>
00033 #include <caller.h>
00034 #include <sysdep-cancel.h>
00035 #include <tls.h>
00036 
00037 #include <dl-dst.h>
00038 
00039 
00040 extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
00041                                 void (*dl_main) (const ElfW(Phdr) *phdr,
00042                                                ElfW(Word) phnum,
00043                                                ElfW(Addr) *user_entry));
00044 weak_extern (BP_SYM (_dl_sysdep_start))
00045 
00046 extern int __libc_multiple_libcs;  /* Defined in init-first.c.  */
00047 
00048 /* Undefine the following for debugging.  */
00049 /* #define SCOPE_DEBUG 1 */
00050 #ifdef SCOPE_DEBUG
00051 static void show_scope (struct link_map *new);
00052 #endif
00053 
00054 /* We must be carefull not to leave us in an inconsistent state.  Thus we
00055    catch any error and re-raise it after cleaning up.  */
00056 
00057 struct dl_open_args
00058 {
00059   const char *file;
00060   int mode;
00061   /* This is the caller of the dlopen() function.  */
00062   const void *caller_dlopen;
00063   /* This is the caller if _dl_open().  */
00064   const void *caller_dl_open;
00065   struct link_map *map;
00066   /* Namespace ID.  */
00067   Lmid_t nsid;
00068   /* Original parameters to the program and the current environment.  */
00069   int argc;
00070   char **argv;
00071   char **env;
00072 };
00073 
00074 
00075 static int
00076 add_to_global (struct link_map *new)
00077 {
00078   struct link_map **new_global;
00079   unsigned int to_add = 0;
00080   unsigned int cnt;
00081 
00082   /* Count the objects we have to put in the global scope.  */
00083   for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
00084     if (new->l_searchlist.r_list[cnt]->l_global == 0)
00085       ++to_add;
00086 
00087   /* The symbols of the new objects and its dependencies are to be
00088      introduced into the global scope that will be used to resolve
00089      references from other dynamically-loaded objects.
00090 
00091      The global scope is the searchlist in the main link map.  We
00092      extend this list if necessary.  There is one problem though:
00093      since this structure was allocated very early (before the libc
00094      is loaded) the memory it uses is allocated by the malloc()-stub
00095      in the ld.so.  When we come here these functions are not used
00096      anymore.  Instead the malloc() implementation of the libc is
00097      used.  But this means the block from the main map cannot be used
00098      in an realloc() call.  Therefore we allocate a completely new
00099      array the first time we have to add something to the locale scope.  */
00100 
00101   struct link_namespaces *ns = &GL(dl_ns)[new->l_ns];
00102   if (ns->_ns_global_scope_alloc == 0)
00103     {
00104       /* This is the first dynamic object given global scope.  */
00105       ns->_ns_global_scope_alloc
00106        = ns->_ns_main_searchlist->r_nlist + to_add + 8;
00107       new_global = (struct link_map **)
00108        malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *));
00109       if (new_global == NULL)
00110        {
00111          ns->_ns_global_scope_alloc = 0;
00112        nomem:
00113          _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
00114                          N_("cannot extend global scope"));
00115          return 1;
00116        }
00117 
00118       /* Copy over the old entries.  */
00119       ns->_ns_main_searchlist->r_list
00120        = memcpy (new_global, ns->_ns_main_searchlist->r_list,
00121                 (ns->_ns_main_searchlist->r_nlist
00122                  * sizeof (struct link_map *)));
00123     }
00124   else if (ns->_ns_main_searchlist->r_nlist + to_add
00125           > ns->_ns_global_scope_alloc)
00126     {
00127       /* We have to extend the existing array of link maps in the
00128         main map.  */
00129       struct link_map **old_global
00130        = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
00131       size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
00132 
00133       new_global = (struct link_map **)
00134        malloc (new_nalloc * sizeof (struct link_map *));
00135       if (new_global == NULL)
00136        goto nomem;
00137 
00138       memcpy (new_global, old_global,
00139              ns->_ns_global_scope_alloc * sizeof (struct link_map *));
00140 
00141       ns->_ns_global_scope_alloc = new_nalloc;
00142       ns->_ns_main_searchlist->r_list = new_global;
00143 
00144       if (!RTLD_SINGLE_THREAD_P)
00145        THREAD_GSCOPE_WAIT ();
00146 
00147       free (old_global);
00148     }
00149 
00150   /* Now add the new entries.  */
00151   unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
00152   for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
00153     {
00154       struct link_map *map = new->l_searchlist.r_list[cnt];
00155 
00156       if (map->l_global == 0)
00157        {
00158          map->l_global = 1;
00159          ns->_ns_main_searchlist->r_list[new_nlist++] = map;
00160        }
00161     }
00162   atomic_write_barrier ();
00163   ns->_ns_main_searchlist->r_nlist = new_nlist;
00164 
00165   return 0;
00166 }
00167 
00168 int
00169 _dl_scope_free (void *old)
00170 {
00171   struct dl_scope_free_list *fsl;
00172 #define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0]))
00173 
00174   if (RTLD_SINGLE_THREAD_P)
00175     free (old);
00176   else if ((fsl = GL(dl_scope_free_list)) == NULL)
00177     {
00178       GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl));
00179       if (fsl == NULL)
00180        {
00181          THREAD_GSCOPE_WAIT ();
00182          free (old);
00183          return 1;
00184        }
00185       else
00186        {
00187          fsl->list[0] = old;
00188          fsl->count = 1;
00189        }
00190     }
00191   else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE)
00192     fsl->list[fsl->count++] = old;
00193   else
00194     {
00195       THREAD_GSCOPE_WAIT ();
00196       while (fsl->count > 0)
00197        free (fsl->list[--fsl->count]);
00198       return 1;
00199     }
00200   return 0;
00201 }
00202 
00203 static void
00204 dl_open_worker (void *a)
00205 {
00206   struct dl_open_args *args = a;
00207   const char *file = args->file;
00208   int mode = args->mode;
00209   struct link_map *new;
00210   int lazy;
00211   unsigned int i;
00212   bool any_tls = false;
00213   struct link_map *call_map = NULL;
00214 
00215   /* Check whether _dl_open() has been called from a valid DSO.  */
00216   if (__check_caller (args->caller_dl_open,
00217                     allow_libc|allow_libdl|allow_ldso) != 0)
00218     _dl_signal_error (0, "dlopen", NULL, N_("invalid caller"));
00219 
00220   /* Determine the caller's map if necessary.  This is needed in case
00221      we have a DST, when we don't know the namespace ID we have to put
00222      the new object in, or when the file name has no path in which
00223      case we need to look along the RUNPATH/RPATH of the caller.  */
00224   const char *dst = strchr (file, '$');
00225   if (dst != NULL || args->nsid == __LM_ID_CALLER
00226       || strchr (file, '/') == NULL)
00227     {
00228       const void *caller_dlopen = args->caller_dlopen;
00229 
00230       /* We have to find out from which object the caller is calling.
00231         By default we assume this is the main application.  */
00232       call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
00233 
00234       struct link_map *l;
00235       for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
00236        for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
00237          if (caller_dlopen >= (const void *) l->l_map_start
00238              && caller_dlopen < (const void *) l->l_map_end
00239              && (l->l_contiguous
00240                 || _dl_addr_inside_object (l, (ElfW(Addr)) caller_dlopen)))
00241            {
00242              assert (ns == l->l_ns);
00243              call_map = l;
00244              goto found_caller;
00245            }
00246 
00247     found_caller:
00248       if (args->nsid == __LM_ID_CALLER)
00249        {
00250 #ifndef SHARED
00251          /* In statically linked apps there might be no loaded object.  */
00252          if (call_map == NULL)
00253            args->nsid = LM_ID_BASE;
00254          else
00255 #endif
00256            args->nsid = call_map->l_ns;
00257        }
00258     }
00259 
00260   assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
00261 
00262   /* Maybe we have to expand a DST.  */
00263   if (__builtin_expect (dst != NULL, 0))
00264     {
00265       size_t len = strlen (file);
00266       size_t required;
00267       char *new_file;
00268 
00269       /* Determine how much space we need.  We have to allocate the
00270         memory locally.  */
00271       required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
00272 
00273       /* Get space for the new file name.  */
00274       new_file = (char *) alloca (required + 1);
00275 
00276       /* Generate the new file name.  */
00277       _dl_dst_substitute (call_map, file, new_file, 0);
00278 
00279       /* If the substitution failed don't try to load.  */
00280       if (*new_file == '\0')
00281        _dl_signal_error (0, "dlopen", NULL,
00282                        N_("empty dynamic string token substitution"));
00283 
00284       /* Now we have a new file name.  */
00285       file = new_file;
00286 
00287       /* It does not matter whether call_map is set even if we
00288         computed it only because of the DST.  Since the path contains
00289         a slash the value is not used.  See dl-load.c.  */
00290     }
00291 
00292   /* Load the named object.  */
00293   args->map = new = _dl_map_object (call_map, file, 0, lt_loaded, 0,
00294                                 mode | __RTLD_CALLMAP, args->nsid);
00295 
00296   /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
00297      set and the object is not already loaded.  */
00298   if (new == NULL)
00299     {
00300       assert (mode & RTLD_NOLOAD);
00301       return;
00302     }
00303 
00304   if (__builtin_expect (mode & __RTLD_SPROF, 0))
00305     /* This happens only if we load a DSO for 'sprof'.  */
00306     return;
00307 
00308   /* This object is directly loaded.  */
00309   ++new->l_direct_opencount;
00310 
00311   /* It was already open.  */
00312   if (__builtin_expect (new->l_searchlist.r_list != NULL, 0))
00313     {
00314       /* Let the user know about the opencount.  */
00315       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
00316        _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
00317                        new->l_name, new->l_ns, new->l_direct_opencount);
00318 
00319       /* If the user requested the object to be in the global namespace
00320         but it is not so far, add it now.  */
00321       if ((mode & RTLD_GLOBAL) && new->l_global == 0)
00322        (void) add_to_global (new);
00323 
00324       assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
00325 
00326       return;
00327     }
00328 
00329   /* Load that object's dependencies.  */
00330   _dl_map_object_deps (new, NULL, 0, 0,
00331                      mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
00332 
00333   /* So far, so good.  Now check the versions.  */
00334   for (i = 0; i < new->l_searchlist.r_nlist; ++i)
00335     if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
00336       (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
00337                                  0, 0);
00338 
00339 #ifdef SCOPE_DEBUG
00340   show_scope (new);
00341 #endif
00342 
00343 #ifdef SHARED
00344   /* Auditing checkpoint: we have added all objects.  */
00345   if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
00346     {
00347       struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
00348       /* Do not call the functions for any auditing object.  */
00349       if (head->l_auditing == 0)
00350        {
00351          struct audit_ifaces *afct = GLRO(dl_audit);
00352          for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
00353            {
00354              if (afct->activity != NULL)
00355               afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
00356 
00357              afct = afct->next;
00358            }
00359        }
00360     }
00361 #endif
00362 
00363   /* Notify the debugger all new objects are now ready to go.  */
00364   struct r_debug *r = _dl_debug_initialize (0, args->nsid);
00365   r->r_state = RT_CONSISTENT;
00366   _dl_debug_state ();
00367 
00368   /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */
00369   lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy);
00370 
00371   /* Relocate the objects loaded.  We do this in reverse order so that copy
00372      relocs of earlier objects overwrite the data written by later objects.  */
00373 
00374   struct link_map *l = new;
00375   while (l->l_next)
00376     l = l->l_next;
00377   while (1)
00378     {
00379       if (! l->l_real->l_relocated)
00380        {
00381 #ifdef SHARED
00382          if (__builtin_expect (GLRO(dl_profile) != NULL, 0))
00383            {
00384              /* If this here is the shared object which we want to profile
00385                make sure the profile is started.  We can find out whether
00386                 this is necessary or not by observing the `_dl_profile_map'
00387                 variable.  If was NULL but is not NULL afterwars we must
00388                start the profiling.  */
00389              struct link_map *old_profile_map = GL(dl_profile_map);
00390 
00391              _dl_relocate_object (l, l->l_scope, 1, 1);
00392 
00393              if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
00394               {
00395                 /* We must prepare the profiling.  */
00396                 _dl_start_profile ();
00397 
00398                 /* Prevent unloading the object.  */
00399                 GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
00400               }
00401            }
00402          else
00403 #endif
00404            _dl_relocate_object (l, l->l_scope, lazy, 0);
00405        }
00406 
00407       if (l == new)
00408        break;
00409       l = l->l_prev;
00410     }
00411 
00412   /* If the file is not loaded now as a dependency, add the search
00413      list of the newly loaded object to the scope.  */
00414   for (i = 0; i < new->l_searchlist.r_nlist; ++i)
00415     {
00416       struct link_map *imap = new->l_searchlist.r_list[i];
00417 
00418       /* If the initializer has been called already, the object has
00419         not been loaded here and now.  */
00420       if (imap->l_init_called && imap->l_type == lt_loaded)
00421        {
00422          struct r_scope_elem **runp = imap->l_scope;
00423          size_t cnt = 0;
00424 
00425          while (*runp != NULL)
00426            {
00427              if (*runp == &new->l_searchlist)
00428               break;
00429              ++cnt;
00430              ++runp;
00431            }
00432 
00433          if (*runp != NULL)
00434            /* Avoid duplicates.  */
00435            continue;
00436 
00437          if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))
00438            {
00439              /* The 'r_scope' array is too small.  Allocate a new one
00440                dynamically.  */
00441              size_t new_size;
00442              struct r_scope_elem **newp;
00443 
00444 #define SCOPE_ELEMS(imap) \
00445   (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
00446 
00447              if (imap->l_scope != imap->l_scope_mem
00448                 && imap->l_scope_max < SCOPE_ELEMS (imap))
00449               {
00450                 new_size = SCOPE_ELEMS (imap);
00451                 newp = imap->l_scope_mem;
00452               }
00453              else
00454               {
00455                 new_size = imap->l_scope_max * 2;
00456                 newp = (struct r_scope_elem **)
00457                   malloc (new_size * sizeof (struct r_scope_elem *));
00458                 if (newp == NULL)
00459                   _dl_signal_error (ENOMEM, "dlopen", NULL,
00460                                   N_("cannot create scope list"));
00461               }
00462 
00463              memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
00464              struct r_scope_elem **old = imap->l_scope;
00465 
00466              imap->l_scope = newp;
00467 
00468              if (old != imap->l_scope_mem)
00469               _dl_scope_free (old);
00470 
00471              imap->l_scope_max = new_size;
00472            }
00473 
00474          /* First terminate the extended list.  Otherwise a thread
00475             might use the new last element and then use the garbage
00476             at offset IDX+1.  */
00477          imap->l_scope[cnt + 1] = NULL;
00478          atomic_write_barrier ();
00479          imap->l_scope[cnt] = &new->l_searchlist;
00480        }
00481       /* Only add TLS memory if this object is loaded now and
00482         therefore is not yet initialized.  */
00483       else if (! imap->l_init_called
00484               /* Only if the module defines thread local data.  */
00485               && __builtin_expect (imap->l_tls_blocksize > 0, 0))
00486        {
00487          /* Now that we know the object is loaded successfully add
00488             modules containing TLS data to the slot info table.  We
00489             might have to increase its size.  */
00490          _dl_add_to_slotinfo (imap);
00491 
00492          if (imap->l_need_tls_init)
00493            {
00494              imap->l_need_tls_init = 0;
00495 #ifdef SHARED
00496              /* Update the slot information data for at least the
00497                generation of the DSO we are allocating data for.  */
00498              _dl_update_slotinfo (imap->l_tls_modid);
00499 #endif
00500 
00501              GL(dl_init_static_tls) (imap);
00502              assert (imap->l_need_tls_init == 0);
00503            }
00504 
00505          /* We have to bump the generation counter.  */
00506          any_tls = true;
00507        }
00508     }
00509 
00510   /* Bump the generation number if necessary.  */
00511   if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
00512     _dl_fatal_printf (N_("\
00513 TLS generation counter wrapped!  Please report this."));
00514 
00515   /* Run the initializer functions of new objects.  */
00516   _dl_init (new, args->argc, args->argv, args->env);
00517 
00518   /* Now we can make the new map available in the global scope.  */
00519   if (mode & RTLD_GLOBAL)
00520     /* Move the object in the global namespace.  */
00521     if (add_to_global (new) != 0)
00522       /* It failed.  */
00523       return;
00524 
00525   /* Mark the object as not deletable if the RTLD_NODELETE flags was
00526      passed.  */
00527   if (__builtin_expect (mode & RTLD_NODELETE, 0))
00528     new->l_flags_1 |= DF_1_NODELETE;
00529 
00530 #ifndef SHARED
00531   /* We must be the static _dl_open in libc.a.  A static program that
00532      has loaded a dynamic object now has competition.  */
00533   __libc_multiple_libcs = 1;
00534 #endif
00535 
00536   /* Let the user know about the opencount.  */
00537   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
00538     _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
00539                     new->l_name, new->l_ns, new->l_direct_opencount);
00540 }
00541 
00542 
00543 void *
00544 _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
00545          int argc, char *argv[], char *env[])
00546 {
00547   if ((mode & RTLD_BINDING_MASK) == 0)
00548     /* One of the flags must be set.  */
00549     _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
00550 
00551   /* Make sure we are alone.  */
00552   __rtld_lock_lock_recursive (GL(dl_load_lock));
00553 
00554   if (nsid == LM_ID_NEWLM)
00555     {
00556       /* Find a new namespace.  */
00557       for (nsid = 1; nsid < DL_NNS; ++nsid)
00558        if (GL(dl_ns)[nsid]._ns_loaded == NULL)
00559          break;
00560 
00561       if (nsid == DL_NNS)
00562        {
00563          /* No more namespace available.  */
00564          __rtld_lock_unlock_recursive (GL(dl_load_lock));
00565 
00566          _dl_signal_error (EINVAL, file, NULL, N_("\
00567 no more namespaces available for dlmopen()"));
00568        }
00569 
00570       _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
00571     }
00572   /* Never allow loading a DSO in a namespace which is empty.  Such
00573      direct placements is only causing problems.  Also don't allow
00574      loading into a namespace used for auditing.  */
00575   else if (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER
00576           && (GL(dl_ns)[nsid]._ns_nloaded == 0
00577               || GL(dl_ns)[nsid]._ns_loaded->l_auditing))
00578     _dl_signal_error (EINVAL, file, NULL,
00579                     N_("invalid target namespace in dlmopen()"));
00580 
00581   struct dl_open_args args;
00582   args.file = file;
00583   args.mode = mode;
00584   args.caller_dlopen = caller_dlopen;
00585   args.caller_dl_open = RETURN_ADDRESS (0);
00586   args.map = NULL;
00587   args.nsid = nsid;
00588   args.argc = argc;
00589   args.argv = argv;
00590   args.env = env;
00591 
00592   const char *objname;
00593   const char *errstring;
00594   bool malloced;
00595   int errcode = _dl_catch_error (&objname, &errstring, &malloced,
00596                              dl_open_worker, &args);
00597 
00598 #ifndef MAP_COPY
00599   /* We must munmap() the cache file.  */
00600   _dl_unload_cache ();
00601 #endif
00602 
00603   /* See if an error occurred during loading.  */
00604   if (__builtin_expect (errstring != NULL, 0))
00605     {
00606       /* Remove the object from memory.  It may be in an inconsistent
00607         state if relocation failed, for example.  */
00608       if (args.map)
00609        {
00610          /* Maybe some of the modules which were loaded use TLS.
00611             Since it will be removed in the following _dl_close call
00612             we have to mark the dtv array as having gaps to fill the
00613             holes.  This is a pessimistic assumption which won't hurt
00614             if not true.  There is no need to do this when we are
00615             loading the auditing DSOs since TLS has not yet been set
00616             up.  */
00617          if ((mode & __RTLD_AUDIT) == 0)
00618            GL(dl_tls_dtv_gaps) = true;
00619 
00620          _dl_close_worker (args.map);
00621        }
00622 
00623       assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
00624 
00625       /* Release the lock.  */
00626       __rtld_lock_unlock_recursive (GL(dl_load_lock));
00627 
00628       /* Make a local copy of the error string so that we can release the
00629         memory allocated for it.  */
00630       size_t len_errstring = strlen (errstring) + 1;
00631       char *local_errstring;
00632       if (objname == errstring + len_errstring)
00633        {
00634          size_t total_len = len_errstring + strlen (objname) + 1;
00635          local_errstring = alloca (total_len);
00636          memcpy (local_errstring, errstring, total_len);
00637          objname = local_errstring + len_errstring;
00638        }
00639       else
00640        {
00641          local_errstring = alloca (len_errstring);
00642          memcpy (local_errstring, errstring, len_errstring);
00643        }
00644 
00645       if (malloced)
00646        free ((char *) errstring);
00647 
00648       /* Reraise the error.  */
00649       _dl_signal_error (errcode, objname, NULL, local_errstring);
00650     }
00651 
00652   assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
00653 
00654   /* Release the lock.  */
00655   __rtld_lock_unlock_recursive (GL(dl_load_lock));
00656 
00657 #ifndef SHARED
00658   DL_STATIC_INIT (args.map);
00659 #endif
00660 
00661   return args.map;
00662 }
00663 
00664 
00665 #ifdef SCOPE_DEBUG
00666 #include <unistd.h>
00667 
00668 static void
00669 show_scope (struct link_map *new)
00670 {
00671   int scope_cnt;
00672 
00673   for (scope_cnt = 0; new->l_scope[scope_cnt] != NULL; ++scope_cnt)
00674     {
00675       char numbuf[2];
00676       unsigned int cnt;
00677 
00678       numbuf[0] = '0' + scope_cnt;
00679       numbuf[1] = '\0';
00680       _dl_printf ("scope %s:", numbuf);
00681 
00682       for (cnt = 0; cnt < new->l_scope[scope_cnt]->r_nlist; ++cnt)
00683        if (*new->l_scope[scope_cnt]->r_list[cnt]->l_name)
00684          _dl_printf (" %s", new->l_scope[scope_cnt]->r_list[cnt]->l_name);
00685        else
00686          _dl_printf (" <main>");
00687 
00688       _dl_printf ("\n");
00689     }
00690 }
00691 #endif
00692 
00693 #ifdef IS_IN_rtld
00694 /* Return non-zero if ADDR lies within one of L's segments.  */
00695 int
00696 internal_function
00697 _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
00698 {
00699   int n = l->l_phnum;
00700   const ElfW(Addr) reladdr = addr - l->l_addr;
00701 
00702   while (--n >= 0)
00703     if (l->l_phdr[n].p_type == PT_LOAD
00704        && reladdr - l->l_phdr[n].p_vaddr >= 0
00705        && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
00706       return 1;
00707   return 0;
00708 }
00709 #endif