_dl_map_object (struct link_map *loader, const char *name, int preloaded,
		int type, int trace_mode)
{
  int fd;
  char *realname;
  char *name_copy;
  struct link_map *l;

  /* Look for this name among those already loaded.  */
  for (l = _dl_loaded; l; l = l->l_next)
    {
      /* If the requested name matches the soname of a loaded object,
	 use that object.  Elide this check for names that have not
	 yet been opened.  */
      if (l->l_opencount <= 0)
	continue;
      if (!_dl_name_match_p (name, l))
	{
	  const char *soname;

	  if (l->l_info[DT_SONAME] == NULL)
	    continue;

	  soname = (const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
				   + l->l_info[DT_SONAME]->d_un.d_val);
	  if (strcmp (name, soname) != 0)
	    continue;

	  /* We have a match on a new name -- cache it.  */
	  add_name_to_object (l, soname);
	}

      /* We have a match -- bump the reference count and return it.  */
      ++l->l_opencount;
      return l;
    }

  /* Display information if we are debugging.  */
  if (_dl_debug_files && loader != NULL)
    _dl_debug_message (1, "\nfile=", name, ";  needed by ",
		       loader->l_name[0] ? loader->l_name : _dl_argv[0],
		       "\n", NULL);

  if (strchr (name, '/') == NULL)
    {
      /* Search for NAME in several places.  */

      size_t namelen = strlen (name) + 1;

      if (_dl_debug_libs)
	_dl_debug_message (1, "find library=", name, "; searching\n", NULL);

      fd = -1;

      /* When the object has the RUNPATH information we don't use any
         RPATHs.  */
      if (loader != NULL && loader->l_info[DT_RUNPATH] == NULL)
	{
	  /* First try the DT_RPATH of the dependent object that caused NAME
	     to be loaded.  Then that object's dependent, and on up.  */
	  for (l = loader; fd == -1 && l; l = l->l_loader)
	    if (l->l_info[DT_RPATH])
	      {
		/* Make sure the cache information is available.  */
		if (l->l_rpath_dirs == NULL)
		  {
		    size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr
				     + l->l_info[DT_RPATH]->d_un.d_val);
		    l->l_rpath_dirs =
		      decompose_rpath ((const char *) ptrval, l, "RPATH");
		  }

		if (l->l_rpath_dirs != NULL)
		  fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
				  &realname);
	      }

	  /* If dynamically linked, try the DT_RPATH of the executable
             itself.  */
	  l = _dl_loaded;
	  if (fd == -1 && l && l->l_type != lt_loaded && l != loader
	      && l->l_rpath_dirs != NULL)
	    fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
			    &realname);
	}

      /* Try the LD_LIBRARY_PATH environment variable.  */
      if (fd == -1 && env_path_list != NULL)
	fd = open_path (name, namelen, preloaded, env_path_list, &realname);

      /* Look at the RUNPATH informaiton for this binary.  */
      if (loader != NULL && loader->l_info[DT_RUNPATH])
	{
	  /* Make sure the cache information is available.  */
	   if (loader->l_runpath_dirs == NULL)
	      {
		size_t ptrval = (loader->l_info[DT_STRTAB]->d_un.d_ptr
				 + loader->l_info[DT_RUNPATH]->d_un.d_val);
		loader->l_runpath_dirs =
		  decompose_rpath ((const char *) ptrval, loader, "RUNPATH");
	      }

	   if (loader->l_runpath_dirs != NULL)
	      fd = open_path (name, namelen, preloaded, loader->l_runpath_dirs,
			      &realname);
	}

      if (fd == -1)
	{
	  /* Check the list of libraries in the file /etc/ld.so.cache,
	     for compatibility with Linux's ldconfig program.  */
	  extern const char *_dl_load_cache_lookup (const char *name);
	  const char *cached = _dl_load_cache_lookup (name);
	  if (cached)
	    {
	      fd = __open (cached, O_RDONLY);
	      if (fd != -1)
		{
		  realname = local_strdup (cached);
		  if (realname == NULL)
		    {
		      __close (fd);
		      fd = -1;
		    }
		}
	    }
	}

      /* Finally, try the default path.  */
      if (fd == -1)
	fd = open_path (name, namelen, preloaded, rtld_search_dirs, &realname);

      /* Add another newline when we a tracing the library loading.  */
      if (_dl_debug_libs)
        _dl_debug_message (1, "\n", NULL);
    }
  else
    {
      /* The path may contain dynamic string tokens.  */
      realname = (loader
		  ? expand_dynamic_string_token (loader, name)
		  : local_strdup (name));
      if (realname == NULL)
	fd = -1;
      else
	{
	  fd = __open (realname, O_RDONLY);
	  if (fd == -1)
	    free (realname);
	}
    }

  if (fd == -1)
    {
      if (trace_mode)
	{
	  /* We haven't found an appropriate library.  But since we
	     are only interested in the list of libraries this isn't
	     so severe.  Fake an entry with all the information we
	     have.  */
	  static const Elf_Symndx dummy_bucket = STN_UNDEF;

	  /* Enter the new object in the list of loaded objects.  */
	  if ((name_copy = local_strdup (name)) == NULL
	      || (l = _dl_new_object (name_copy, name, type, loader)) == NULL)
	    _dl_signal_error (ENOMEM, name,
			      "cannot create shared object descriptor");
	  /* We use an opencount of 0 as a sign for the faked entry.
	     Since the descriptor is initialized with zero we do not
	     have do this here.
	  l->l_opencount = 0;
	  l->l_reserved = 0; */
	  l->l_buckets = &dummy_bucket;
	  l->l_nbuckets = 1;
	  l->l_relocated = 1;

	  return l;
	}
      else
	_dl_signal_error (errno, name, "cannot open shared object file");
    }

  return _dl_map_object_from_fd (name, fd, realname, loader, type);
}