const char *dst;
dl_open_worker (void *a){  struct dl_open_args *args = a;  const char *file = args->file;  int mode = args->mode;  struct link_map *new, *l;  const char *dst;  int lazy;  unsigned int i;#ifdef USE_TLS  bool any_tls;#endif  /* Check whether _dl_open() has been called from a valid DSO.  */  if (__check_caller (args->caller_dl_open, allow_libc|allow_libdl) != 0)    GLRO(dl_signal_error) (0, "dlopen", NULL, N_("invalid caller"));  /* Maybe we have to expand a DST.  */  dst = strchr (file, '$');  if (__builtin_expect (dst != NULL, 0))    {      const void *caller_dlopen = args->caller_dlopen;      size_t len = strlen (file);      size_t required;      struct link_map *call_map;      char *new_file;      /* DSTs must not appear in SUID/SGID programs.  */      if (__libc_enable_secure)	/* This is an error.  */	GLRO(dl_signal_error) (0, "dlopen", NULL,			       N_("DST not allowed in SUID/SGID programs"));      /* We have to find out from which object the caller is calling.  */      call_map = NULL;      for (l = GL(dl_loaded); l; l = l->l_next)	if (caller_dlopen >= (const void *) l->l_map_start	    && caller_dlopen < (const void *) l->l_map_end)	  {	    /* There must be exactly one DSO for the range of the virtual	       memory.  Otherwise something is really broken.  */	    call_map = l;	    break;	  }      if (call_map == NULL)	/* In this case we assume this is the main application.  */	call_map = GL(dl_loaded);      /* Determine how much space we need.  We have to allocate the	 memory locally.  */      required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));      /* Get space for the new file name.  */      new_file = (char *) alloca (required + 1);      /* Generate the new file name.  */      _dl_dst_substitute (call_map, file, new_file, 0);      /* If the substitution failed don't try to load.  */      if (*new_file == '\0')	GLRO(dl_signal_error) (0, "dlopen", NULL,			       N_("empty dynamic string token substitution"));      /* Now we have a new file name.  */      file = new_file;    }  /* Load the named object.  */  args->map = new = GLRO(dl_map_object) (NULL, file, 0, lt_loaded, 0, mode);  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is     set and the object is not already loaded.  */  if (new == NULL)    {      assert (mode & RTLD_NOLOAD);      return;    }  if (__builtin_expect (mode & __RTLD_SPROF, 0))    /* This happens only if we load a DSO for 'sprof'.  */    return;  /* It was already open.  */  if (__builtin_expect (new->l_searchlist.r_list != NULL, 0))    {      /* Let the user know about the opencount.  */      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))	GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n",			       new->l_name, new->l_opencount);      /* If the user requested the object to be in the global namespace	 but it is not so far, add it now.  */      if ((mode & RTLD_GLOBAL) && new->l_global == 0)	(void) add_to_global (new);      /* Increment just the reference counter of the object.  */      ++new->l_opencount;      return;    }  /* Load that object's dependencies.  */  GLRO(dl_map_object_deps) (new, NULL, 0, 0, mode & __RTLD_DLOPEN);  /* So far, so good.  Now check the versions.  */  for (i = 0; i < new->l_searchlist.r_nlist; ++i)    if (new->l_searchlist.r_list[i]->l_versions == NULL)      (void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i], 0, 0);#ifdef SCOPE_DEBUG  show_scope (new);#endif  /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */  lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy);  /* Relocate the objects loaded.  We do this in reverse order so that copy     relocs of earlier objects overwrite the data written by later objects.  */  l = new;  while (l->l_next)    l = l->l_next;  while (1)    {      if (! l->l_relocated)	{#ifdef SHARED	  if (GLRO(dl_profile) != NULL)	    {	      /* If this here is the shared object which we want to profile		 make sure the profile is started.  We can find out whether	         this is necessary or not by observing the `_dl_profile_map'	         variable.  If was NULL but is not NULL afterwars we must		 start the profiling.  */	      struct link_map *old_profile_map = GL(dl_profile_map);	      GLRO(dl_relocate_object) (l, l->l_scope, 1, 1);	      if (old_profile_map == NULL && GL(dl_profile_map) != NULL)		{		  /* We must prepare the profiling.  */		  GLRO(dl_start_profile) ();		  /* Prevent unloading the object.  */		  GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;		}	    }	  else#endif	    GLRO(dl_relocate_object) (l, l->l_scope, lazy, 0);	}      if (l == new)	break;      l = l->l_prev;    }#ifdef USE_TLS  /* Do static TLS initialization now if it has been delayed because     the TLS template might not be fully relocated at _dl_allocate_static_tls     time.  */  for (l = new; l; l = l->l_next)    if (l->l_need_tls_init)      {	l->l_need_tls_init = 0;	GL(dl_init_static_tls) (l);      }  /* We normally don't bump the TLS generation counter.  There must be     actually a need to do this.  */  any_tls = false;#endif  /* Increment the open count for all dependencies.  If the file is     not loaded as a dependency here add the search list of the newly     loaded object to the scope.  */  for (i = 0; i < new->l_searchlist.r_nlist; ++i)    if (++new->l_searchlist.r_list[i]->l_opencount > 1	&& new->l_searchlist.r_list[i]->l_type == lt_loaded)      {	struct link_map *imap = new->l_searchlist.r_list[i];	struct r_scope_elem **runp = imap->l_scope;	size_t cnt = 0;	while (*runp != NULL)	  {	    /* This can happen if imap was just loaded, but during	       relocation had l_opencount bumped because of relocation	       dependency.  Avoid duplicates in l_scope.  */	    if (__builtin_expect (*runp == &new->l_searchlist, 0))	      break;	    ++cnt;	    ++runp;	  }	if (*runp != NULL)	  /* Avoid duplicates.  */	  continue;	if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))	  {	    /* The 'r_scope' array is too small.  Allocate a new one	       dynamically.  */	    struct r_scope_elem **newp;	    size_t new_size = imap->l_scope_max * 2;	    if (imap->l_scope == imap->l_scope_mem)	      {		newp = (struct r_scope_elem **)		  malloc (new_size * sizeof (struct r_scope_elem *));		if (newp == NULL)		  GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,					 N_("cannot create scope list"));		imap->l_scope = memcpy (newp, imap->l_scope,					cnt * sizeof (imap->l_scope[0]));	      }	    else	      {		newp = (struct r_scope_elem **)		  realloc (imap->l_scope,			   new_size * sizeof (struct r_scope_elem *));		if (newp == NULL)		  GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,					 N_("cannot create scope list"));		imap->l_scope = newp;	      }	    imap->l_scope_max = new_size;	  }	imap->l_scope[cnt++] = &new->l_searchlist;	imap->l_scope[cnt] = NULL;      }#if USE_TLS    else if (new->l_searchlist.r_list[i]->l_opencount == 1	     /* Only if the module defines thread local data.  */	     && __builtin_expect (new->l_searchlist.r_list[i]->l_tls_blocksize				  > 0, 0))      {	/* Now that we know the object is loaded successfully add	   modules containing TLS data to the dtv info table.  We	   might have to increase its size.  */	struct dtv_slotinfo_list *listp;	struct dtv_slotinfo_list *prevp;	size_t idx = new->l_searchlist.r_list[i]->l_tls_modid;	assert (new->l_searchlist.r_list[i]->l_type == lt_loaded);	/* Find the place in the dtv slotinfo list.  */	listp = GL(dl_tls_dtv_slotinfo_list);	prevp = NULL;		/* Needed to shut up gcc.  */	do	  {	    /* Does it fit in the array of this list element?  */	    if (idx < listp->len)	      break;	    idx -= listp->len;	    prevp = listp;	    listp = listp->next;	  }	while (listp != NULL);	if (listp == NULL)	  {	    /* When we come here it means we have to add a new element	       to the slotinfo list.  And the new module must be in	       the first slot.  */	    assert (idx == 0);	    listp = prevp->next = (struct dtv_slotinfo_list *)	      malloc (sizeof (struct dtv_slotinfo_list)		      + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));	    if (listp == NULL)	      {		/* We ran out of memory.  We will simply fail this		   call but don't undo anything we did so far.  The		   application will crash or be terminated anyway very		   soon.  */		/* We have to do this since some entries in the dtv		   slotinfo array might already point to this		   generation.  */		++GL(dl_tls_generation);		GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL, N_("\cannot create TLS data structures"));	      }	    listp->len = TLS_SLOTINFO_SURPLUS;	    listp->next = NULL;	    memset (listp->slotinfo, '\0',		    TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));	  }	/* Add the information into the slotinfo data structure.  */	listp->slotinfo[idx].map = new->l_searchlist.r_list[i];	listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;	/* We have to bump the generation counter.  */	any_tls = true;      }  /* Bump the generation number if necessary.  */  if (any_tls)    if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))      __libc_fatal (_("TLS generation counter wrapped!  Please send report with the 'glibcbug' script."));#endif  /* Run the initializer functions of new objects.  */  GLRO(dl_init) (new, __libc_argc, __libc_argv, __environ);  /* Now we can make the new map available in the global scope.  */  if (mode & RTLD_GLOBAL)    /* Move the object in the global namespace.  */    if (add_to_global (new) != 0)      /* It failed.  */      return;  /* Mark the object as not deletable if the RTLD_NODELETE flags was     passed.  */  if (__builtin_expect (mode & RTLD_NODELETE, 0))    new->l_flags_1 |= DF_1_NODELETE;#ifndef SHARED  /* We must be the static _dl_open in libc.a.  A static program that     has loaded a dynamic object now has competition.  */  __libc_multiple_libcs = 1;#endif  /* Let the user know about the opencount.  */  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))    GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n",			   new->l_name, new->l_opencount);}