Blame elf/dl-open.c

Packit 6c4009
/* Load a shared object at runtime, relocate it, and run its initializer.
Packit 6c4009
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <dlfcn.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <libintl.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <sys/mman.h>		/* Check whether MAP_COPY is defined.  */
Packit 6c4009
#include <sys/param.h>
Packit 6c4009
#include <libc-lock.h>
Packit 6c4009
#include <ldsodefs.h>
Packit 6c4009
#include <sysdep-cancel.h>
Packit 6c4009
#include <tls.h>
Packit 6c4009
#include <stap-probe.h>
Packit 6c4009
#include <atomic.h>
Packit 6c4009
#include <libc-internal.h>
Packit Service 883e40
#include <array_length.h>
Packit Service b61b6e
#include <libc-early-init.h>
Packit 6c4009
Packit 6c4009
#include <dl-dst.h>
Packit 6c4009
#include <dl-prop.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* We must be careful not to leave us in an inconsistent state.  Thus we
Packit 6c4009
   catch any error and re-raise it after cleaning up.  */
Packit 6c4009
Packit 6c4009
struct dl_open_args
Packit 6c4009
{
Packit 6c4009
  const char *file;
Packit 6c4009
  int mode;
Packit 6c4009
  /* This is the caller of the dlopen() function.  */
Packit 6c4009
  const void *caller_dlopen;
Packit 6c4009
  struct link_map *map;
Packit 6c4009
  /* Namespace ID.  */
Packit 6c4009
  Lmid_t nsid;
Packit Service ea9e91
Packit Service ea9e91
  /* Original value of _ns_global_scope_pending_adds.  Set by
Packit Service ea9e91
     dl_open_worker.  Only valid if nsid is a real namespace
Packit Service ea9e91
     (non-negative).  */
Packit Service ea9e91
  unsigned int original_global_scope_pending_adds;
Packit Service ea9e91
Packit Service b61b6e
  /* Set to true by dl_open_worker if libc.so was already loaded into
Packit Service b61b6e
     the namespace at the time dl_open_worker was called.  This is
Packit Service b61b6e
     used to determine whether libc.so early initialization has
Packit Service b61b6e
     already been done before, and whether to roll back the cached
Packit Service b61b6e
     libc_map value in the namespace in case of a dlopen failure.  */
Packit Service b61b6e
  bool libc_already_loaded;
Packit Service b61b6e
Packit 6c4009
  /* Original parameters to the program and the current environment.  */
Packit 6c4009
  int argc;
Packit 6c4009
  char **argv;
Packit 6c4009
  char **env;
Packit 6c4009
};
Packit 6c4009
Packit Service ea9e91
/* Called in case the global scope cannot be extended.  */
Packit Service ea9e91
static void __attribute__ ((noreturn))
Packit Service ea9e91
add_to_global_resize_failure (struct link_map *new)
Packit Service ea9e91
{
Packit Service ea9e91
  _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
Packit Service ea9e91
		    N_ ("cannot extend global scope"));
Packit Service ea9e91
}
Packit 6c4009
Packit Service ea9e91
/* Grow the global scope array for the namespace, so that all the new
Packit Service ea9e91
   global objects can be added later in add_to_global_update, without
Packit Service ea9e91
   risk of memory allocation failure.  add_to_global_resize raises
Packit Service ea9e91
   exceptions for memory allocation errors.  */
Packit Service ea9e91
static void
Packit Service ea9e91
add_to_global_resize (struct link_map *new)
Packit 6c4009
{
Packit Service ea9e91
  struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
Packit 6c4009
Packit 6c4009
  /* Count the objects we have to put in the global scope.  */
Packit Service ea9e91
  unsigned int to_add = 0;
Packit Service ea9e91
  for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
Packit 6c4009
    if (new->l_searchlist.r_list[cnt]->l_global == 0)
Packit 6c4009
      ++to_add;
Packit 6c4009
Packit 6c4009
  /* The symbols of the new objects and its dependencies are to be
Packit 6c4009
     introduced into the global scope that will be used to resolve
Packit 6c4009
     references from other dynamically-loaded objects.
Packit 6c4009
Packit 6c4009
     The global scope is the searchlist in the main link map.  We
Packit 6c4009
     extend this list if necessary.  There is one problem though:
Packit 6c4009
     since this structure was allocated very early (before the libc
Packit 6c4009
     is loaded) the memory it uses is allocated by the malloc()-stub
Packit 6c4009
     in the ld.so.  When we come here these functions are not used
Packit 6c4009
     anymore.  Instead the malloc() implementation of the libc is
Packit 6c4009
     used.  But this means the block from the main map cannot be used
Packit 6c4009
     in an realloc() call.  Therefore we allocate a completely new
Packit 6c4009
     array the first time we have to add something to the locale scope.  */
Packit 6c4009
Packit Service ea9e91
  if (__builtin_add_overflow (ns->_ns_global_scope_pending_adds, to_add,
Packit Service ea9e91
			      &ns->_ns_global_scope_pending_adds))
Packit Service ea9e91
    add_to_global_resize_failure (new);
Packit Service ea9e91
Packit Service ea9e91
  unsigned int new_size = 0; /* 0 means no new allocation.  */
Packit Service ea9e91
  void *old_global = NULL; /* Old allocation if free-able.  */
Packit Service ea9e91
Packit Service ea9e91
  /* Minimum required element count for resizing.  Adjusted below for
Packit Service ea9e91
     an exponential resizing policy.  */
Packit Service ea9e91
  size_t required_new_size;
Packit Service ea9e91
  if (__builtin_add_overflow (ns->_ns_main_searchlist->r_nlist,
Packit Service ea9e91
			      ns->_ns_global_scope_pending_adds,
Packit Service ea9e91
			      &required_new_size))
Packit Service ea9e91
    add_to_global_resize_failure (new);
Packit Service ea9e91
Packit 6c4009
  if (ns->_ns_global_scope_alloc == 0)
Packit 6c4009
    {
Packit Service ea9e91
      if (__builtin_add_overflow (required_new_size, 8, &new_size))
Packit Service ea9e91
	add_to_global_resize_failure (new);
Packit Service ea9e91
    }
Packit Service ea9e91
  else if (required_new_size > ns->_ns_global_scope_alloc)
Packit Service ea9e91
    {
Packit Service ea9e91
      if (__builtin_mul_overflow (required_new_size, 2, &new_size))
Packit Service ea9e91
	add_to_global_resize_failure (new);
Packit 6c4009
Packit Service ea9e91
      /* The old array was allocated with our malloc, not the minimal
Packit Service ea9e91
	 malloc.  */
Packit Service ea9e91
      old_global = ns->_ns_main_searchlist->r_list;
Packit 6c4009
    }
Packit Service ea9e91
Packit Service ea9e91
  if (new_size > 0)
Packit 6c4009
    {
Packit Service ea9e91
      size_t allocation_size;
Packit Service ea9e91
      if (__builtin_mul_overflow (new_size, sizeof (struct link_map *),
Packit Service ea9e91
				  &allocation_size))
Packit Service ea9e91
	add_to_global_resize_failure (new);
Packit Service ea9e91
      struct link_map **new_global = malloc (allocation_size);
Packit 6c4009
      if (new_global == NULL)
Packit Service ea9e91
	add_to_global_resize_failure (new);
Packit 6c4009
Packit Service ea9e91
      /* Copy over the old entries.  */
Packit Service ea9e91
      memcpy (new_global, ns->_ns_main_searchlist->r_list,
Packit Service ea9e91
	      ns->_ns_main_searchlist->r_nlist * sizeof (struct link_map *));
Packit 6c4009
Packit Service ea9e91
      ns->_ns_global_scope_alloc = new_size;
Packit 6c4009
      ns->_ns_main_searchlist->r_list = new_global;
Packit 6c4009
Packit 6c4009
      if (!RTLD_SINGLE_THREAD_P)
Packit 6c4009
	THREAD_GSCOPE_WAIT ();
Packit 6c4009
Packit 6c4009
      free (old_global);
Packit 6c4009
    }
Packit Service ea9e91
}
Packit Service ea9e91
Packit Service ea9e91
/* Actually add the new global objects to the global scope.  Must be
Packit Service ea9e91
   called after add_to_global_resize.  This function cannot fail.  */
Packit Service ea9e91
static void
Packit Service ea9e91
add_to_global_update (struct link_map *new)
Packit Service ea9e91
{
Packit Service ea9e91
  struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
Packit 6c4009
Packit 6c4009
  /* Now add the new entries.  */
Packit 6c4009
  unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
Packit Service ea9e91
  for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
Packit 6c4009
    {
Packit 6c4009
      struct link_map *map = new->l_searchlist.r_list[cnt];
Packit 6c4009
Packit 6c4009
      if (map->l_global == 0)
Packit 6c4009
	{
Packit 6c4009
	  map->l_global = 1;
Packit Service ea9e91
Packit Service ea9e91
	  /* The array has been resized by add_to_global_resize.  */
Packit Service ea9e91
	  assert (new_nlist < ns->_ns_global_scope_alloc);
Packit Service ea9e91
Packit 6c4009
	  ns->_ns_main_searchlist->r_list[new_nlist++] = map;
Packit 6c4009
Packit 6c4009
	  /* We modify the global scope.  Report this.  */
Packit 6c4009
	  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
Packit 6c4009
	    _dl_debug_printf ("\nadd %s [%lu] to global scope\n",
Packit 6c4009
			      map->l_name, map->l_ns);
Packit 6c4009
	}
Packit 6c4009
    }
Packit Service ea9e91
Packit Service ea9e91
  /* Some of the pending adds have been performed by the loop above.
Packit Service ea9e91
     Adjust the counter accordingly.  */
Packit Service ea9e91
  unsigned int added = new_nlist - ns->_ns_main_searchlist->r_nlist;
Packit Service ea9e91
  assert (added <= ns->_ns_global_scope_pending_adds);
Packit Service ea9e91
  ns->_ns_global_scope_pending_adds -= added;
Packit Service ea9e91
Packit 6c4009
  atomic_write_barrier ();
Packit 6c4009
  ns->_ns_main_searchlist->r_nlist = new_nlist;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Search link maps in all namespaces for the DSO that contains the object at
Packit 6c4009
   address ADDR.  Returns the pointer to the link map of the matching DSO, or
Packit 6c4009
   NULL if a match is not found.  */
Packit 6c4009
struct link_map *
Packit 6c4009
_dl_find_dso_for_object (const ElfW(Addr) addr)
Packit 6c4009
{
Packit 6c4009
  struct link_map *l;
Packit 6c4009
Packit 6c4009
  /* Find the highest-addressed object that ADDR is not below.  */
Packit 6c4009
  for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
Packit 6c4009
    for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
Packit 6c4009
      if (addr >= l->l_map_start && addr < l->l_map_end
Packit 6c4009
	  && (l->l_contiguous
Packit 6c4009
	      || _dl_addr_inside_object (l, (ElfW(Addr)) addr)))
Packit 6c4009
	{
Packit 6c4009
	  assert (ns == l->l_ns);
Packit 6c4009
	  return l;
Packit 6c4009
	}
Packit 6c4009
  return NULL;
Packit 6c4009
}
Packit 6c4009
rtld_hidden_def (_dl_find_dso_for_object);
Packit 6c4009
Packit Service 883e40
/* Return true if NEW is found in the scope for MAP.  */
Packit Service 883e40
static size_t
Packit Service 883e40
scope_has_map (struct link_map *map, struct link_map *new)
Packit Service 883e40
{
Packit Service 883e40
  size_t cnt;
Packit Service 883e40
  for (cnt = 0; map->l_scope[cnt] != NULL; ++cnt)
Packit Service 883e40
    if (map->l_scope[cnt] == &new->l_searchlist)
Packit Service 883e40
      return true;
Packit Service 883e40
  return false;
Packit Service 883e40
}
Packit Service 883e40
Packit Service 883e40
/* Return the length of the scope for MAP.  */
Packit Service 883e40
static size_t
Packit Service 883e40
scope_size (struct link_map *map)
Packit Service 883e40
{
Packit Service 883e40
  size_t cnt;
Packit Service 883e40
  for (cnt = 0; map->l_scope[cnt] != NULL; )
Packit Service 883e40
    ++cnt;
Packit Service 883e40
  return cnt;
Packit Service 883e40
}
Packit Service 883e40
Packit Service 883e40
/* Resize the scopes of depended-upon objects, so that the new object
Packit Service 883e40
   can be added later without further allocation of memory.  This
Packit Service 883e40
   function can raise an exceptions due to malloc failure.  */
Packit Service 883e40
static void
Packit Service 883e40
resize_scopes (struct link_map *new)
Packit Service 883e40
{
Packit Service 883e40
  /* If the file is not loaded now as a dependency, add the search
Packit Service 883e40
     list of the newly loaded object to the scope.  */
Packit Service 883e40
  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
Packit Service 883e40
    {
Packit Service 883e40
      struct link_map *imap = new->l_searchlist.r_list[i];
Packit Service 883e40
Packit Service 883e40
      /* If the initializer has been called already, the object has
Packit Service 883e40
	 not been loaded here and now.  */
Packit Service 883e40
      if (imap->l_init_called && imap->l_type == lt_loaded)
Packit Service 883e40
	{
Packit Service 883e40
	  if (scope_has_map (imap, new))
Packit Service 883e40
	    /* Avoid duplicates.  */
Packit Service 883e40
	    continue;
Packit Service 883e40
Packit Service 883e40
	  size_t cnt = scope_size (imap);
Packit Service 883e40
	  if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
Packit Service 883e40
	    {
Packit Service 883e40
	      /* The l_scope array is too small.  Allocate a new one
Packit Service 883e40
		 dynamically.  */
Packit Service 883e40
	      size_t new_size;
Packit Service 883e40
	      struct r_scope_elem **newp;
Packit Service 883e40
Packit Service 883e40
	      if (imap->l_scope != imap->l_scope_mem
Packit Service 883e40
		  && imap->l_scope_max < array_length (imap->l_scope_mem))
Packit Service 883e40
		{
Packit Service 883e40
		  /* If the current l_scope memory is not pointing to
Packit Service 883e40
		     the static memory in the structure, but the
Packit Service 883e40
		     static memory in the structure is large enough to
Packit Service 883e40
		     use for cnt + 1 scope entries, then switch to
Packit Service 883e40
		     using the static memory.  */
Packit Service 883e40
		  new_size = array_length (imap->l_scope_mem);
Packit Service 883e40
		  newp = imap->l_scope_mem;
Packit Service 883e40
		}
Packit Service 883e40
	      else
Packit Service 883e40
		{
Packit Service 883e40
		  new_size = imap->l_scope_max * 2;
Packit Service 883e40
		  newp = (struct r_scope_elem **)
Packit Service 883e40
		    malloc (new_size * sizeof (struct r_scope_elem *));
Packit Service 883e40
		  if (newp == NULL)
Packit Service 883e40
		    _dl_signal_error (ENOMEM, "dlopen", NULL,
Packit Service 883e40
				      N_("cannot create scope list"));
Packit Service 883e40
		}
Packit Service 883e40
Packit Service 883e40
	      /* Copy the array and the terminating NULL.  */
Packit Service 883e40
	      memcpy (newp, imap->l_scope,
Packit Service 883e40
		      (cnt + 1) * sizeof (imap->l_scope[0]));
Packit Service 883e40
	      struct r_scope_elem **old = imap->l_scope;
Packit Service 883e40
Packit Service 883e40
	      imap->l_scope = newp;
Packit Service 883e40
Packit Service 883e40
	      if (old != imap->l_scope_mem)
Packit Service 883e40
		_dl_scope_free (old);
Packit Service 883e40
Packit Service 883e40
	      imap->l_scope_max = new_size;
Packit Service 883e40
	    }
Packit Service 883e40
	}
Packit Service 883e40
    }
Packit Service 883e40
}
Packit Service 883e40
Packit Service 883e40
/* Second stage of resize_scopes: Add NEW to the scopes.  Also print
Packit Service 883e40
   debugging information about scopes if requested.
Packit Service 883e40
Packit Service 883e40
   This function cannot raise an exception because all required memory
Packit Service 883e40
   has been allocated by a previous call to resize_scopes.  */
Packit Service 883e40
static void
Packit Service 883e40
update_scopes (struct link_map *new)
Packit Service 883e40
{
Packit Service 883e40
  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
Packit Service 883e40
    {
Packit Service 883e40
      struct link_map *imap = new->l_searchlist.r_list[i];
Packit Service 883e40
      int from_scope = 0;
Packit Service 883e40
Packit Service 883e40
      if (imap->l_init_called && imap->l_type == lt_loaded)
Packit Service 883e40
	{
Packit Service 883e40
	  if (scope_has_map (imap, new))
Packit Service 883e40
	    /* Avoid duplicates.  */
Packit Service 883e40
	    continue;
Packit Service 883e40
Packit Service 883e40
	  size_t cnt = scope_size (imap);
Packit Service 883e40
	  /* Assert that resize_scopes has sufficiently enlarged the
Packit Service 883e40
	     array.  */
Packit Service 883e40
	  assert (cnt + 1 < imap->l_scope_max);
Packit Service 883e40
Packit Service 883e40
	  /* First terminate the extended list.  Otherwise a thread
Packit Service 883e40
	     might use the new last element and then use the garbage
Packit Service 883e40
	     at offset IDX+1.  */
Packit Service 883e40
	  imap->l_scope[cnt + 1] = NULL;
Packit Service 883e40
	  atomic_write_barrier ();
Packit Service 883e40
	  imap->l_scope[cnt] = &new->l_searchlist;
Packit Service 883e40
Packit Service 883e40
	  from_scope = cnt;
Packit Service 883e40
	}
Packit Service 883e40
Packit Service 883e40
      /* Print scope information.  */
Packit Service 883e40
      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
Packit Service 883e40
	_dl_show_scope (imap, from_scope);
Packit Service 883e40
    }
Packit Service 883e40
}
Packit Service 883e40
Packit Service 883e40
/* Call _dl_add_to_slotinfo with DO_ADD set to false, to allocate
Packit Service 883e40
   space in GL (dl_tls_dtv_slotinfo_list).  This can raise an
Packit Service 883e40
   exception.  The return value is true if any of the new objects use
Packit Service 883e40
   TLS.  */
Packit Service 883e40
static bool
Packit Service 883e40
resize_tls_slotinfo (struct link_map *new)
Packit Service 883e40
{
Packit Service 883e40
  bool any_tls = false;
Packit Service 883e40
  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
Packit Service 883e40
    {
Packit Service 883e40
      struct link_map *imap = new->l_searchlist.r_list[i];
Packit Service 883e40
Packit Service 883e40
      /* Only add TLS memory if this object is loaded now and
Packit Service 883e40
	 therefore is not yet initialized.  */
Packit Service 883e40
      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
Packit Service 883e40
	{
Packit Service 883e40
	  _dl_add_to_slotinfo (imap, false);
Packit Service 883e40
	  any_tls = true;
Packit Service 883e40
	}
Packit Service 883e40
    }
Packit Service 883e40
  return any_tls;
Packit Service 883e40
}
Packit Service 883e40
Packit Service 883e40
/* Second stage of TLS update, after resize_tls_slotinfo.  This
Packit Service 883e40
   function does not raise any exception.  It should only be called if
Packit Service 883e40
   resize_tls_slotinfo returned true.  */
Packit Service 883e40
static void
Packit Service 883e40
update_tls_slotinfo (struct link_map *new)
Packit Service 883e40
{
Packit Service 883e40
  unsigned int first_static_tls = new->l_searchlist.r_nlist;
Packit Service 883e40
  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
Packit Service 883e40
    {
Packit Service 883e40
      struct link_map *imap = new->l_searchlist.r_list[i];
Packit Service 883e40
Packit Service 883e40
      /* Only add TLS memory if this object is loaded now and
Packit Service 883e40
	 therefore is not yet initialized.  */
Packit Service 883e40
      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
Packit Service 883e40
	{
Packit Service 883e40
	  _dl_add_to_slotinfo (imap, true);
Packit Service 883e40
Packit Service 883e40
	  if (imap->l_need_tls_init
Packit Service 883e40
	      && first_static_tls == new->l_searchlist.r_nlist)
Packit Service 883e40
	    first_static_tls = i;
Packit Service 883e40
	}
Packit Service 883e40
    }
Packit Service 883e40
Packit Service 883e40
  if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
Packit Service 883e40
    _dl_fatal_printf (N_("\
Packit Service 883e40
TLS generation counter wrapped!  Please report this."));
Packit Service 883e40
Packit Service 883e40
  /* We need a second pass for static tls data, because
Packit Service 883e40
     _dl_update_slotinfo must not be run while calls to
Packit Service 883e40
     _dl_add_to_slotinfo are still pending.  */
Packit Service 883e40
  for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
Packit Service 883e40
    {
Packit Service 883e40
      struct link_map *imap = new->l_searchlist.r_list[i];
Packit Service 883e40
Packit Service 883e40
      if (imap->l_need_tls_init
Packit Service 883e40
	  && ! imap->l_init_called
Packit Service 883e40
	  && imap->l_tls_blocksize > 0)
Packit Service 883e40
	{
Packit Service 883e40
	  /* For static TLS we have to allocate the memory here and
Packit Service 883e40
	     now, but we can delay updating the DTV.  */
Packit Service 883e40
	  imap->l_need_tls_init = 0;
Packit Service 883e40
#ifdef SHARED
Packit Service 883e40
	  /* Update the slot information data for at least the
Packit Service 883e40
	     generation of the DSO we are allocating data for.  */
Packit Service 883e40
Packit Service 883e40
	  /* FIXME: This can terminate the process on memory
Packit Service 883e40
	     allocation failure.  It is not possible to raise
Packit Service 883e40
	     exceptions from this context; to fix this bug,
Packit Service 883e40
	     _dl_update_slotinfo would have to be split into two
Packit Service 883e40
	     operations, similar to resize_scopes and update_scopes
Packit Service 883e40
	     above.  This is related to bug 16134.  */
Packit Service 883e40
	  _dl_update_slotinfo (imap->l_tls_modid);
Packit Service 883e40
#endif
Packit Service 883e40
Packit Service 883e40
	  GL(dl_init_static_tls) (imap);
Packit Service 883e40
	  assert (imap->l_need_tls_init == 0);
Packit Service 883e40
	}
Packit Service 883e40
    }
Packit Service 883e40
}
Packit Service 883e40
Packit Service 807d93
/* Mark the objects as NODELETE if required.  This is delayed until
Packit Service 807d93
   after dlopen failure is not possible, so that _dl_close can clean
Packit Service 807d93
   up objects if necessary.  */
Packit Service 807d93
static void
Packit Service f35cab
activate_nodelete (struct link_map *new)
Packit Service 807d93
{
Packit Service f35cab
  /* It is necessary to traverse the entire namespace.  References to
Packit Service f35cab
     objects in the global scope and unique symbol bindings can force
Packit Service f35cab
     NODELETE status for objects outside the local scope.  */
Packit Service f35cab
  for (struct link_map *l = GL (dl_ns)[new->l_ns]._ns_loaded; l != NULL;
Packit Service f35cab
       l = l->l_next)
Packit Service 4d38ce
    if (l->l_nodelete_pending)
Packit Service f35cab
      {
Packit Service f35cab
	if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
Packit Service f35cab
	  _dl_debug_printf ("activating NODELETE for %s [%lu]\n",
Packit Service f35cab
			    l->l_name, l->l_ns);
Packit Service f35cab
Packit Service cb696d
	/* The flag can already be true at this point, e.g. a signal
Packit Service cb696d
	   handler may have triggered lazy binding and set NODELETE
Packit Service cb696d
	   status immediately.  */
Packit Service 4d38ce
	l->l_nodelete_active = true;
Packit Service 4d38ce
Packit Service 4d38ce
	/* This is just a debugging aid, to indicate that
Packit Service 4d38ce
	   activate_nodelete has run for this map.  */
Packit Service 4d38ce
	l->l_nodelete_pending = false;
Packit Service f35cab
      }
Packit Service 807d93
}
Packit Service 807d93
Packit Service 5c587e
/* struct dl_init_args and call_dl_init are used to call _dl_init with
Packit Service 5c587e
   exception handling disabled.  */
Packit Service 5c587e
struct dl_init_args
Packit Service 5c587e
{
Packit Service 5c587e
  struct link_map *new;
Packit Service 5c587e
  int argc;
Packit Service 5c587e
  char **argv;
Packit Service 5c587e
  char **env;
Packit Service 5c587e
};
Packit Service 5c587e
Packit Service 5c587e
static void
Packit Service 5c587e
call_dl_init (void *closure)
Packit Service 5c587e
{
Packit Service 5c587e
  struct dl_init_args *args = closure;
Packit Service 5c587e
  _dl_init (args->new, args->argc, args->argv, args->env);
Packit Service 5c587e
}
Packit Service 5c587e
Packit 6c4009
static void
Packit 6c4009
dl_open_worker (void *a)
Packit 6c4009
{
Packit 6c4009
  struct dl_open_args *args = a;
Packit 6c4009
  const char *file = args->file;
Packit 6c4009
  int mode = args->mode;
Packit 6c4009
  struct link_map *call_map = NULL;
Packit 6c4009
Packit 6c4009
  /* Determine the caller's map if necessary.  This is needed in case
Packit 6c4009
     we have a DST, when we don't know the namespace ID we have to put
Packit 6c4009
     the new object in, or when the file name has no path in which
Packit 6c4009
     case we need to look along the RUNPATH/RPATH of the caller.  */
Packit 6c4009
  const char *dst = strchr (file, '$');
Packit 6c4009
  if (dst != NULL || args->nsid == __LM_ID_CALLER
Packit 6c4009
      || strchr (file, '/') == NULL)
Packit 6c4009
    {
Packit 6c4009
      const void *caller_dlopen = args->caller_dlopen;
Packit 6c4009
Packit 6c4009
      /* We have to find out from which object the caller is calling.
Packit 6c4009
	 By default we assume this is the main application.  */
Packit 6c4009
      call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
Packit 6c4009
Packit 6c4009
      struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
Packit 6c4009
Packit 6c4009
      if (l)
Packit 6c4009
	call_map = l;
Packit 6c4009
Packit 6c4009
      if (args->nsid == __LM_ID_CALLER)
Packit 6c4009
	args->nsid = call_map->l_ns;
Packit 6c4009
    }
Packit 6c4009
Packit Service b61b6e
  /* The namespace ID is now known.  Keep track of whether libc.so was
Packit Service b61b6e
     already loaded, to determine whether it is necessary to call the
Packit Service b61b6e
     early initialization routine (or clear libc_map on error).  */
Packit Service b61b6e
  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
Packit Service b61b6e
Packit Service ea9e91
  /* Retain the old value, so that it can be restored.  */
Packit Service ea9e91
  args->original_global_scope_pending_adds
Packit Service ea9e91
    = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
Packit Service ea9e91
Packit 6c4009
  /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
Packit 6c4009
     may not be true if this is a recursive call to dlopen.  */
Packit 6c4009
  _dl_debug_initialize (0, args->nsid);
Packit 6c4009
Packit 6c4009
  /* Load the named object.  */
Packit 6c4009
  struct link_map *new;
Packit 6c4009
  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
Packit 6c4009
				    mode | __RTLD_CALLMAP, args->nsid);
Packit 6c4009
Packit 6c4009
  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
Packit 6c4009
     set and the object is not already loaded.  */
Packit 6c4009
  if (new == NULL)
Packit 6c4009
    {
Packit 6c4009
      assert (mode & RTLD_NOLOAD);
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (__glibc_unlikely (mode & __RTLD_SPROF))
Packit Service cb696d
    /* This happens only if we load a DSO for 'sprof'.  */
Packit Service cb696d
    return;
Packit 6c4009
Packit 6c4009
  /* This object is directly loaded.  */
Packit 6c4009
  ++new->l_direct_opencount;
Packit 6c4009
Packit 6c4009
  /* It was already open.  */
Packit 6c4009
  if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
Packit 6c4009
    {
Packit 6c4009
      /* Let the user know about the opencount.  */
Packit 6c4009
      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
Packit 6c4009
	_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
Packit 6c4009
			  new->l_name, new->l_ns, new->l_direct_opencount);
Packit 6c4009
Packit Service 807d93
      /* If the user requested the object to be in the global
Packit Service 807d93
	 namespace but it is not so far, prepare to add it now.  This
Packit Service 807d93
	 can raise an exception to do a malloc failure.  */
Packit 6c4009
      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
Packit Service 807d93
	add_to_global_resize (new);
Packit Service 807d93
Packit Service 807d93
      /* Mark the object as not deletable if the RTLD_NODELETE flags
Packit Service 807d93
	 was passed.  */
Packit Service 807d93
      if (__glibc_unlikely (mode & RTLD_NODELETE))
Packit Service ea9e91
	{
Packit Service 807d93
	  if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
Packit Service 4d38ce
	      && !new->l_nodelete_active)
Packit Service 807d93
	    _dl_debug_printf ("marking %s [%lu] as NODELETE\n",
Packit Service 807d93
			      new->l_name, new->l_ns);
Packit Service 4d38ce
	  new->l_nodelete_active = true;
Packit Service ea9e91
	}
Packit Service 58a1d7
Packit Service 807d93
      /* Finalize the addition to the global scope.  */
Packit Service 807d93
      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
Packit Service 807d93
	add_to_global_update (new);
Packit Service 807d93
Packit 6c4009
      assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
Packit 6c4009
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit Service 807d93
  /* Schedule NODELETE marking for the directly loaded object if
Packit Service 807d93
     requested.  */
Packit Service 807d93
  if (__glibc_unlikely (mode & RTLD_NODELETE))
Packit Service 4d38ce
    new->l_nodelete_pending = true;
Packit Service 807d93
Packit 6c4009
  /* Load that object's dependencies.  */
Packit 6c4009
  _dl_map_object_deps (new, NULL, 0, 0,
Packit 6c4009
		       mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
Packit 6c4009
Packit 6c4009
  /* So far, so good.  Now check the versions.  */
Packit 6c4009
  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
Packit 6c4009
    if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
Packit 6c4009
      (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
Packit 6c4009
				     0, 0);
Packit 6c4009
Packit 6c4009
#ifdef SHARED
Packit 6c4009
  /* Auditing checkpoint: we have added all objects.  */
Packit 6c4009
  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
Packit 6c4009
    {
Packit 6c4009
      struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
Packit 6c4009
      /* Do not call the functions for any auditing object.  */
Packit 6c4009
      if (head->l_auditing == 0)
Packit 6c4009
	{
Packit 6c4009
	  struct audit_ifaces *afct = GLRO(dl_audit);
Packit 6c4009
	  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit 6c4009
	    {
Packit 6c4009
	      if (afct->activity != NULL)
Packit Service 050912
		{
Packit Service 050912
		  struct auditstate *state = link_map_audit_state (head, cnt);
Packit Service 050912
		  afct->activity (&state->cookie, LA_ACT_CONSISTENT);
Packit Service 050912
		}
Packit 6c4009
Packit 6c4009
	      afct = afct->next;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  /* Notify the debugger all new objects are now ready to go.  */
Packit 6c4009
  struct r_debug *r = _dl_debug_initialize (0, args->nsid);
Packit 6c4009
  r->r_state = RT_CONSISTENT;
Packit 6c4009
  _dl_debug_state ();
Packit 6c4009
  LIBC_PROBE (map_complete, 3, args->nsid, r, new);
Packit 6c4009
Packit Service 5b819e
  _dl_open_check (new);
Packit Service 5b819e
Packit 6c4009
  /* Print scope information.  */
Packit 6c4009
  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
Packit 6c4009
    _dl_show_scope (new, 0);
Packit 6c4009
Packit 6c4009
  /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */
Packit 6c4009
  int reloc_mode = mode & __RTLD_AUDIT;
Packit 6c4009
  if (GLRO(dl_lazy))
Packit 6c4009
    reloc_mode |= mode & RTLD_LAZY;
Packit 6c4009
Packit Service 660ba3
  /* Objects must be sorted by dependency for the relocation process.
Packit Service 660ba3
     This allows IFUNC relocations to work and it also means copy
Packit Service 660ba3
     relocation of dependencies are if necessary overwritten.
Packit Service 660ba3
     __dl_map_object_deps has already sorted l_initfini for us.  */
Packit Service 8792f0
  unsigned int first = UINT_MAX;
Packit Service 8792f0
  unsigned int last = 0;
Packit Service 78de6b
  unsigned int j = 0;
Packit Service 78de6b
  struct link_map *l = new->l_initfini[0];
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      if (! l->l_real->l_relocated)
Packit Service 8792f0
	{
Packit Service 8792f0
	  if (first == UINT_MAX)
Packit Service 8792f0
	    first = j;
Packit Service 8792f0
	  last = j + 1;
Packit Service 8792f0
	}
Packit Service 78de6b
      l = new->l_initfini[++j];
Packit 6c4009
    }
Packit 6c4009
  while (l != NULL);
Packit 6c4009
Packit 6c4009
  int relocation_in_progress = 0;
Packit 6c4009
Packit Service 807d93
  /* Perform relocation.  This can trigger lazy binding in IFUNC
Packit Service 807d93
     resolvers.  For NODELETE mappings, these dependencies are not
Packit Service 807d93
     recorded because the flag has not been applied to the newly
Packit Service 807d93
     loaded objects.  This means that upon dlopen failure, these
Packit Service 807d93
     NODELETE objects can be unloaded despite existing references to
Packit Service 807d93
     them.  However, such relocation dependencies in IFUNC resolvers
Packit Service 807d93
     are undefined anyway, so this is not a problem.  */
Packit Service 807d93
Packit Service 8792f0
  for (unsigned int i = last; i-- > first; )
Packit 6c4009
    {
Packit Service 8792f0
      l = new->l_initfini[i];
Packit Service 8792f0
Packit Service 8792f0
      if (l->l_real->l_relocated)
Packit Service 8792f0
	continue;
Packit 6c4009
Packit 6c4009
      if (! relocation_in_progress)
Packit 6c4009
	{
Packit 6c4009
	  /* Notify the debugger that relocations are about to happen.  */
Packit 6c4009
	  LIBC_PROBE (reloc_start, 2, args->nsid, r);
Packit 6c4009
	  relocation_in_progress = 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
#ifdef SHARED
Packit 6c4009
      if (__glibc_unlikely (GLRO(dl_profile) != NULL))
Packit 6c4009
	{
Packit 6c4009
	  /* If this here is the shared object which we want to profile
Packit 6c4009
	     make sure the profile is started.  We can find out whether
Packit 6c4009
	     this is necessary or not by observing the `_dl_profile_map'
Packit 6c4009
	     variable.  If it was NULL but is not NULL afterwards we must
Packit 6c4009
	     start the profiling.  */
Packit 6c4009
	  struct link_map *old_profile_map = GL(dl_profile_map);
Packit 6c4009
Packit 6c4009
	  _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
Packit 6c4009
Packit 6c4009
	  if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
Packit 6c4009
	    {
Packit 6c4009
	      /* We must prepare the profiling.  */
Packit 6c4009
	      _dl_start_profile ();
Packit 6c4009
Packit 6c4009
	      /* Prevent unloading the object.  */
Packit Service 4d38ce
	      GL(dl_profile_map)->l_nodelete_active = true;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
#endif
Packit 6c4009
	_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
Packit 6c4009
    }
Packit 6c4009
Packit Service 883e40
  /* This only performs the memory allocations.  The actual update of
Packit Service 883e40
     the scopes happens below, after failure is impossible.  */
Packit Service 883e40
  resize_scopes (new);
Packit Service 6de65a
Packit Service 883e40
  /* Increase the size of the GL (dl_tls_dtv_slotinfo_list) data
Packit Service 883e40
     structure.  */
Packit Service 883e40
  bool any_tls = resize_tls_slotinfo (new);
Packit Service 1f32a9
Packit Service 883e40
  /* Perform the necessary allocations for adding new global objects
Packit Service 883e40
     to the global scope below.  */
Packit Service 883e40
  if (mode & RTLD_GLOBAL)
Packit Service 883e40
    add_to_global_resize (new);
Packit Service 1f32a9
Packit Service 883e40
  /* Demarcation point: After this, no recoverable errors are allowed.
Packit Service 883e40
     All memory allocations for new objects must have happened
Packit Service 883e40
     before.  */
Packit Service 883e40
Packit Service cb696d
  /* Finalize the NODELETE status first.  This comes before
Packit Service cb696d
     update_scopes, so that lazy binding will not see pending NODELETE
Packit Service cb696d
     state for newly loaded objects.  There is a compiler barrier in
Packit Service cb696d
     update_scopes which ensures that the changes from
Packit Service cb696d
     activate_nodelete are visible before new objects show up in the
Packit Service cb696d
     local scope.  */
Packit Service f35cab
  activate_nodelete (new);
Packit Service 807d93
Packit Service 883e40
  /* Second stage after resize_scopes: Actually perform the scope
Packit Service 883e40
     update.  After this, dlsym and lazy binding can bind to new
Packit Service 883e40
     objects.  */
Packit Service 883e40
  update_scopes (new);
Packit Service 883e40
Packit Service 883e40
  /* FIXME: It is unclear whether the order here is correct.
Packit Service 883e40
     Shouldn't new objects be made available for binding (and thus
Packit Service 883e40
     execution) only after there TLS data has been set up fully?
Packit Service 883e40
     Fixing bug 16134 will likely make this distinction less
Packit Service 883e40
     important.  */
Packit Service 883e40
Packit Service 883e40
  /* Second stage after resize_tls_slotinfo: Update the slotinfo data
Packit Service 883e40
     structures.  */
Packit Service 883e40
  if (any_tls)
Packit Service 883e40
    /* FIXME: This calls _dl_update_slotinfo, which aborts the process
Packit Service 883e40
       on memory allocation failure.  See bug 16134.  */
Packit Service 883e40
    update_tls_slotinfo (new);
Packit Service 75716b
Packit Service 1f32a9
  /* Notify the debugger all new objects have been relocated.  */
Packit Service 1f32a9
  if (relocation_in_progress)
Packit Service 1f32a9
    LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
Packit Service 1f32a9
Packit Service b61b6e
  /* If libc.so was not there before, attempt to call its early
Packit Service 7f405e
     initialization routine.  Indicate to the initialization routine
Packit Service 7f405e
     whether the libc being initialized is the one in the base
Packit Service 7f405e
     namespace.  */
Packit Service b61b6e
  if (!args->libc_already_loaded)
Packit Service 7f405e
    {
Packit Service 7f405e
      struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map;
Packit Service 7f405e
#ifdef SHARED
Packit Service 7f405e
      bool initial = libc_map->l_ns == LM_ID_BASE;
Packit Service 7f405e
#else
Packit Service 7f405e
      /* In the static case, there is only one namespace, but it
Packit Service 7f405e
	 contains a secondary libc (the primary libc is statically
Packit Service 7f405e
	 linked).  */
Packit Service 7f405e
      bool initial = false;
Packit Service 7f405e
#endif
Packit Service 7f405e
      _dl_call_libc_early_init (libc_map, initial);
Packit Service 7f405e
    }
Packit Service b61b6e
Packit 6c4009
#ifndef SHARED
Packit 6c4009
  DL_STATIC_INIT (new);
Packit 6c4009
#endif
Packit 6c4009
Packit Service ea9e91
  /* Perform the necessary allocations for adding new global objects
Packit Service ea9e91
     to the global scope below, via add_to_global_update.  */
Packit Service ea9e91
  if (mode & RTLD_GLOBAL)
Packit Service ea9e91
    add_to_global_resize (new);
Packit Service ea9e91
Packit Service 5c587e
  /* Run the initializer functions of new objects.  Temporarily
Packit Service 5c587e
     disable the exception handler, so that lazy binding failures are
Packit Service 5c587e
     fatal.  */
Packit Service 5c587e
  {
Packit Service 5c587e
    struct dl_init_args init_args =
Packit Service 5c587e
      {
Packit Service 5c587e
        .new = new,
Packit Service 5c587e
        .argc = args->argc,
Packit Service 5c587e
        .argv = args->argv,
Packit Service 5c587e
        .env = args->env
Packit Service 5c587e
      };
Packit Service 5c587e
    _dl_catch_exception (NULL, call_dl_init, &init_args);
Packit Service 5c587e
  }
Packit 6c4009
Packit 6c4009
  /* Now we can make the new map available in the global scope.  */
Packit 6c4009
  if (mode & RTLD_GLOBAL)
Packit Service ea9e91
    add_to_global_update (new);
Packit 6c4009
Packit 6c4009
#ifndef SHARED
Packit 6c4009
  /* We must be the static _dl_open in libc.a.  A static program that
Packit 6c4009
     has loaded a dynamic object now has competition.  */
Packit 6c4009
  __libc_multiple_libcs = 1;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  /* Let the user know about the opencount.  */
Packit 6c4009
  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
Packit 6c4009
    _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
Packit 6c4009
		      new->l_name, new->l_ns, new->l_direct_opencount);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void *
Packit 6c4009
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
Packit 6c4009
	  int argc, char *argv[], char *env[])
Packit 6c4009
{
Packit 6c4009
  if ((mode & RTLD_BINDING_MASK) == 0)
Packit 6c4009
    /* One of the flags must be set.  */
Packit 6c4009
    _dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
Packit 6c4009
Packit 6c4009
  /* Make sure we are alone.  */
Packit 6c4009
  __rtld_lock_lock_recursive (GL(dl_load_lock));
Packit 6c4009
Packit 6c4009
  if (__glibc_unlikely (nsid == LM_ID_NEWLM))
Packit 6c4009
    {
Packit 6c4009
      /* Find a new namespace.  */
Packit 6c4009
      for (nsid = 1; DL_NNS > 1 && nsid < GL(dl_nns); ++nsid)
Packit 6c4009
	if (GL(dl_ns)[nsid]._ns_loaded == NULL)
Packit 6c4009
	  break;
Packit 6c4009
Packit 6c4009
      if (__glibc_unlikely (nsid == DL_NNS))
Packit 6c4009
	{
Packit 6c4009
	  /* No more namespace available.  */
Packit 6c4009
	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
Packit 6c4009
Packit 6c4009
	  _dl_signal_error (EINVAL, file, NULL, N_("\
Packit 6c4009
no more namespaces available for dlmopen()"));
Packit 6c4009
	}
Packit 6c4009
      else if (nsid == GL(dl_nns))
Packit 6c4009
	{
Packit 6c4009
	  __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
Packit 6c4009
	  ++GL(dl_nns);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
Packit 6c4009
    }
Packit 6c4009
  /* Never allow loading a DSO in a namespace which is empty.  Such
Packit 6c4009
     direct placements is only causing problems.  Also don't allow
Packit 6c4009
     loading into a namespace used for auditing.  */
Packit 6c4009
  else if (__glibc_unlikely (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER)
Packit 6c4009
	   && (__glibc_unlikely (nsid < 0 || nsid >= GL(dl_nns))
Packit 6c4009
	       /* This prevents the [NSID] index expressions from being
Packit 6c4009
		  evaluated, so the compiler won't think that we are
Packit 6c4009
		  accessing an invalid index here in the !SHARED case where
Packit 6c4009
		  DL_NNS is 1 and so any NSID != 0 is invalid.  */
Packit 6c4009
	       || DL_NNS == 1
Packit 6c4009
	       || GL(dl_ns)[nsid]._ns_nloaded == 0
Packit 6c4009
	       || GL(dl_ns)[nsid]._ns_loaded->l_auditing))
Packit 6c4009
    _dl_signal_error (EINVAL, file, NULL,
Packit 6c4009
		      N_("invalid target namespace in dlmopen()"));
Packit 6c4009
Packit 6c4009
  struct dl_open_args args;
Packit 6c4009
  args.file = file;
Packit 6c4009
  args.mode = mode;
Packit 6c4009
  args.caller_dlopen = caller_dlopen;
Packit 6c4009
  args.map = NULL;
Packit 6c4009
  args.nsid = nsid;
Packit Service b61b6e
  /* args.libc_already_loaded is always assigned by dl_open_worker
Packit Service b61b6e
     (before any explicit/non-local returns).  */
Packit 6c4009
  args.argc = argc;
Packit 6c4009
  args.argv = argv;
Packit 6c4009
  args.env = env;
Packit 6c4009
Packit 6c4009
  struct dl_exception exception;
Packit 6c4009
  int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
Packit 6c4009
Packit 6c4009
#if defined USE_LDCONFIG && !defined MAP_COPY
Packit 6c4009
  /* We must unmap the cache file.  */
Packit 6c4009
  _dl_unload_cache ();
Packit 6c4009
#endif
Packit 6c4009
Packit Service ea9e91
  /* Do this for both the error and success cases.  The old value has
Packit Service ea9e91
     only been determined if the namespace ID was assigned (i.e., it
Packit Service ea9e91
     is not __LM_ID_CALLER).  In the success case, we actually may
Packit Service ea9e91
     have consumed more pending adds than planned (because the local
Packit Service ea9e91
     scopes overlap in case of a recursive dlopen, the inner dlopen
Packit Service ea9e91
     doing some of the globalization work of the outer dlopen), so the
Packit Service ea9e91
     old pending adds value is larger than absolutely necessary.
Packit Service ea9e91
     Since it is just a conservative upper bound, this is harmless.
Packit Service ea9e91
     The top-level dlopen call will restore the field to zero.  */
Packit Service ea9e91
  if (args.nsid >= 0)
Packit Service ea9e91
    GL (dl_ns)[args.nsid]._ns_global_scope_pending_adds
Packit Service ea9e91
      = args.original_global_scope_pending_adds;
Packit Service ea9e91
Packit 6c4009
  /* See if an error occurred during loading.  */
Packit 6c4009
  if (__glibc_unlikely (exception.errstring != NULL))
Packit 6c4009
    {
Packit Service b61b6e
      /* Avoid keeping around a dangling reference to the libc.so link
Packit Service b61b6e
	 map in case it has been cached in libc_map.  */
Packit Service b61b6e
      if (!args.libc_already_loaded)
Packit Service b61b6e
	GL(dl_ns)[nsid].libc_map = NULL;
Packit Service b61b6e
Packit 6c4009
      /* Remove the object from memory.  It may be in an inconsistent
Packit 6c4009
	 state if relocation failed, for example.  */
Packit 6c4009
      if (args.map)
Packit 6c4009
	{
Packit 6c4009
	  /* Maybe some of the modules which were loaded use TLS.
Packit 6c4009
	     Since it will be removed in the following _dl_close call
Packit 6c4009
	     we have to mark the dtv array as having gaps to fill the
Packit 6c4009
	     holes.  This is a pessimistic assumption which won't hurt
Packit 6c4009
	     if not true.  There is no need to do this when we are
Packit 6c4009
	     loading the auditing DSOs since TLS has not yet been set
Packit 6c4009
	     up.  */
Packit 6c4009
	  if ((mode & __RTLD_AUDIT) == 0)
Packit 6c4009
	    GL(dl_tls_dtv_gaps) = true;
Packit 6c4009
Packit 6c4009
	  _dl_close_worker (args.map, true);
Packit Service 807d93
Packit Service 4d38ce
	  /* All l_nodelete_pending objects should have been deleted
Packit Service 4d38ce
	     at this point, which is why it is not necessary to reset
Packit Service 4d38ce
	     the flag here.  */
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
Packit 6c4009
Packit 6c4009
      /* Release the lock.  */
Packit 6c4009
      __rtld_lock_unlock_recursive (GL(dl_load_lock));
Packit 6c4009
Packit 6c4009
      /* Reraise the error.  */
Packit 6c4009
      _dl_signal_exception (errcode, &exception, NULL);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
Packit 6c4009
Packit 6c4009
  /* Release the lock.  */
Packit 6c4009
  __rtld_lock_unlock_recursive (GL(dl_load_lock));
Packit 6c4009
Packit 6c4009
  return args.map;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
_dl_show_scope (struct link_map *l, int from)
Packit 6c4009
{
Packit 6c4009
  _dl_debug_printf ("object=%s [%lu]\n",
Packit 6c4009
		    DSO_FILENAME (l->l_name), l->l_ns);
Packit 6c4009
  if (l->l_scope != NULL)
Packit 6c4009
    for (int scope_cnt = from; l->l_scope[scope_cnt] != NULL; ++scope_cnt)
Packit 6c4009
      {
Packit 6c4009
	_dl_debug_printf (" scope %u:", scope_cnt);
Packit 6c4009
Packit 6c4009
	for (unsigned int cnt = 0; cnt < l->l_scope[scope_cnt]->r_nlist; ++cnt)
Packit 6c4009
	  if (*l->l_scope[scope_cnt]->r_list[cnt]->l_name)
Packit 6c4009
	    _dl_debug_printf_c (" %s",
Packit 6c4009
				l->l_scope[scope_cnt]->r_list[cnt]->l_name);
Packit 6c4009
	  else
Packit 6c4009
	    _dl_debug_printf_c (" %s", RTLD_PROGNAME);
Packit 6c4009
Packit 6c4009
	_dl_debug_printf_c ("\n");
Packit 6c4009
      }
Packit 6c4009
  else
Packit 6c4009
    _dl_debug_printf (" no scope\n");
Packit 6c4009
  _dl_debug_printf ("\n");
Packit 6c4009
}