char name[namlen]; struct link_map *map = ni->library->lib_handle; ElfW(Addr) loadbase; const ElfW(Sym) *ref = NULL; void get_sym (void) { struct link_map *scope[2] = { map, NULL }; loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0); }
struct get_sym_args args; args.name = __alloca (namlen); args.map = ni->library->lib_handle;
nss_lookup_function (service_user *ni, const char *fct_name){  void **found, *result;  /* We now modify global data.  Protect it.  */  __libc_lock_lock (lock);  /* Search the tree of functions previously requested.  Data in the     tree are `known_function' structures, whose first member is a     `const char *', the lookup key.  The search returns a pointer to     the tree node structure; the first member of the is a pointer to     our structure (i.e. what will be a `known_function'); since the     first member of that is the lookup key string, &FCT_NAME is close     enough to a pointer to our structure to use as a lookup key that     will be passed to `known_compare' (above).  */  found = __tsearch (&fct_name, (void **) &ni->known, &known_compare);  if (*found != &fct_name)    /* The search found an existing structure in the tree.  */    result = ((known_function *) *found)->fct_ptr;  else    {      /* This name was not known before.  Now we have a node in the tree	 (in the proper sorted position for FCT_NAME) that points to	 &FCT_NAME instead of any real `known_function' structure.	 Allocate a new structure and fill it in.  */      known_function *known = malloc (sizeof *known);      if (! known)	{	remove_from_tree:	  /* Oops.  We can't instantiate this node properly.	     Remove it from the tree.  */	  __tdelete (&fct_name, (void **) &ni->known, &known_compare);	  result = NULL;	}      else	{	  /* Point the tree node at this new structure.  */	  *found = known;	  known->fct_name = fct_name;	  if (ni->library == NULL)	    {	      /* This service has not yet been used.  Fetch the service		 library for it, creating a new one if need be.  If there		 is no service table from the file, this static variable		 holds the head of the service_library list made from the		 default configuration.  */	      static name_database default_table;	      ni->library = nss_new_service (service_table ?: &default_table,					     ni->name);	      if (ni->library == NULL)		{		  /* This only happens when out of memory.  */		  free (known);		  goto remove_from_tree;		}	    }	  if (ni->library->lib_handle == NULL)	    {	      /* Load the shared library.  */	      size_t shlen = (7 + strlen (ni->library->name) + 3			      + strlen (__nss_shlib_revision) + 1);	      char shlib_name[shlen];	      void do_open (void)		{		  /* Open and relocate the shared object.  */		  ni->library->lib_handle = _dl_open (shlib_name, RTLD_LAZY);		}	      /* Construct shared object name.  */	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"),					    ni->library->name),				  ".so"),			__nss_shlib_revision);	      if (nss_dlerror_run (do_open) != 0)		/* Failed to load the library.  */		ni->library->lib_handle = (void *) -1l;	    }	  if (ni->library->lib_handle == (void *) -1l)	    /* Library not found => function not found.  */	    result = NULL;	  else	    {	      /* Get the desired function.  Again,  GNU ld.so magic ahead.  */	      size_t namlen = (5 + strlen (ni->library->name) + 1			       + strlen (fct_name) + 1);	      char name[namlen];	      struct link_map *map = ni->library->lib_handle;	      ElfW(Addr) loadbase;	      const ElfW(Sym) *ref = NULL;	      void get_sym (void)		{		  struct link_map *scope[2] = { map, NULL };		  loadbase = _dl_lookup_symbol (name, &ref,						scope, map->l_name, 0);		}	      /* Construct the function name.  */	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"),					    ni->library->name),				  "_"),			fct_name);	      /* Look up the symbol.  */	      result = (nss_dlerror_run (get_sym)			? NULL : (void *) (loadbase + ref->st_value));	    }	  /* Remember function pointer for later calls.  Even if null, we	     record it so a second try needn't search the library again.  */	  known->fct_ptr = result;	}    }  /* Remove the lock.  */  __libc_lock_unlock (lock);  return result;}