⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dl-load.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	  init_val = cp[0] != '/' ? existing : unknown;	  for (cnt = 0; cnt < ncapstr; ++cnt)	    dirp->status[cnt] = init_val;	  dirp->what = what;	  if (__builtin_expect (where != NULL, 1))	    dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1				  + ncapstr * sizeof (enum r_dir_status),				  where, where_len);	  else	    dirp->where = NULL;	  dirp->next = _dl_all_dirs;	  _dl_all_dirs = dirp;	  /* Put it in the result array.  */	  result[nelems++] = dirp;	}    }  /* Terminate the array.  */  result[nelems] = NULL;  return result;}static voidinternal_functiondecompose_rpath (struct r_search_path_struct *sps,		 const char *rpath, struct link_map *l, const char *what){  /* Make a copy we can work with.  */  const char *where = l->l_name;  char *copy;  char *cp;  struct r_search_path_elem **result;  size_t nelems;  /* Initialize to please the compiler.  */  const char *errstring = NULL;  /* First see whether we must forget the RUNPATH and RPATH from this     object.  */  if (__builtin_expect (_dl_inhibit_rpath != NULL, 0))     {      const char *found = strstr (_dl_inhibit_rpath, where);      if (found != NULL)	{	  size_t len = strlen (where);	  if ((found == _dl_inhibit_rpath || found[-1] == ':')	      && (found[len] == '\0' || found[len] == ':'))	    {	      /* This object is on the list of objects for which the		 RUNPATH and RPATH must not be used.  */	      result = (struct r_search_path_elem **)		malloc (sizeof (*result));	      if (result == NULL)		{		signal_error_cache:		  errstring = N_("cannot create cache for search path");		signal_error:		  _dl_signal_error (ENOMEM, NULL, NULL, errstring);		}	      result[0] = NULL;	      sps->dirs = result;	      sps->malloced = 1;	      return;	    }	}    }  /* Make a writable copy.  At the same time expand possible dynamic     string tokens.  */  copy = expand_dynamic_string_token (l, rpath);  if (copy == NULL)    {      errstring = N_("cannot create RUNPATH/RPATH copy");      goto signal_error;    }  /* Count the number of necessary elements in the result array.  */  nelems = 0;  for (cp = copy; *cp != '\0'; ++cp)    if (*cp == ':')      ++nelems;  /* Allocate room for the result.  NELEMS + 1 is an upper limit for the     number of necessary entries.  */  result = (struct r_search_path_elem **) malloc ((nelems + 1 + 1)						  * sizeof (*result));  if (result == NULL)    goto signal_error_cache;  fillin_rpath (copy, result, ":", 0, what, where);  /* Free the copied RPATH string.  `fillin_rpath' make own copies if     necessary.  */  free (copy);  sps->dirs = result;  /* The caller will change this value if we haven't used a real malloc.  */  sps->malloced = 1;}voidinternal_function_dl_init_paths (const char *llp){  size_t idx;  const char *strp;  struct r_search_path_elem *pelem, **aelem;  size_t round_size;#ifdef SHARED  struct link_map *l;#endif  /* Initialize to please the compiler.  */  const char *errstring = NULL;  /* Fill in the information about the application's RPATH and the     directories addressed by the LD_LIBRARY_PATH environment variable.  */  /* Get the capabilities.  */  capstr = _dl_important_hwcaps (_dl_platform, _dl_platformlen,				 &ncapstr, &max_capstrlen);  /* First set up the rest of the default search directory entries.  */  aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **)    malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *));  if (rtld_search_dirs.dirs == NULL)    {      errstring = N_("cannot create search path array");    signal_error:      _dl_signal_error (ENOMEM, NULL, NULL, errstring);    }  round_size = ((2 * sizeof (struct r_search_path_elem) - 1		 + ncapstr * sizeof (enum r_dir_status))		/ sizeof (struct r_search_path_elem));  rtld_search_dirs.dirs[0] = (struct r_search_path_elem *)    malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]))	    * round_size * sizeof (struct r_search_path_elem));  if (rtld_search_dirs.dirs[0] == NULL)    {      errstring = N_("cannot create cache for search path");      goto signal_error;    }  rtld_search_dirs.malloced = 0;  pelem = _dl_all_dirs = rtld_search_dirs.dirs[0];  strp = system_dirs;  idx = 0;  do    {      size_t cnt;      *aelem++ = pelem;      pelem->what = "system search path";      pelem->where = NULL;      pelem->dirname = strp;      pelem->dirnamelen = system_dirs_len[idx];      strp += system_dirs_len[idx] + 1;      /* System paths must be absolute.  */      assert (pelem->dirname[0] == '/');      for (cnt = 0; cnt < ncapstr; ++cnt)	pelem->status[cnt] = unknown;      pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size));      pelem += round_size;    }  while (idx < nsystem_dirs_len);  max_dirnamelen = SYSTEM_DIRS_MAX_LEN;  *aelem = NULL;#ifdef SHARED  /* This points to the map of the main object.  */  l = _dl_loaded;  if (l != NULL)    {      assert (l->l_type != lt_loaded);      if (l->l_info[DT_RUNPATH])	{	  /* Allocate room for the search path and fill in information	     from RUNPATH.  */	  decompose_rpath (&l->l_runpath_dirs,			   (const void *) (D_PTR (l, l_info[DT_STRTAB])					   + l->l_info[DT_RUNPATH]->d_un.d_val),			   l, "RUNPATH");	  /* The RPATH is ignored.  */	  l->l_rpath_dirs.dirs = (void *) -1;	}      else	{	  l->l_runpath_dirs.dirs = (void *) -1;	  if (l->l_info[DT_RPATH])	    {	      /* Allocate room for the search path and fill in information		 from RPATH.  */	      decompose_rpath (&l->l_rpath_dirs,			       (const void *) (D_PTR (l, l_info[DT_STRTAB])					       + l->l_info[DT_RPATH]->d_un.d_val),			       l, "RPATH");	      l->l_rpath_dirs.malloced = 0;	    }	  else	    l->l_rpath_dirs.dirs = (void *) -1;	}    }#endif	/* SHARED */  if (llp != NULL && *llp != '\0')    {      size_t nllp;      const char *cp = llp;      const char *old = llp;      size_t len = strlen (old) + 1;      char *new = alloca(len);      char *llp_tmp;      llp_tmp = memcpy (new, old, len);      /* Decompose the LD_LIBRARY_PATH contents.  First determine how many	 elements it has.  */      nllp = 1;      while (*cp)	{	  if (*cp == ':' || *cp == ';')	    ++nllp;	  ++cp;	}      env_path_list.dirs = (struct r_search_path_elem **)	malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));      if (env_path_list.dirs == NULL)	{	  errstring = N_("cannot create cache for search path");	  goto signal_error;	}      (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;",			   0, "LD_LIBRARY_PATH", NULL);      if (env_path_list.dirs[0] == NULL)	{	  free (env_path_list.dirs);	  env_path_list.dirs = (void *) -1;	}      env_path_list.malloced = 0;    }  else    env_path_list.dirs = (void *) -1;  /* Remember the last search directory added at startup.  */  _dl_init_all_dirs = _dl_all_dirs;}/* Think twice before changing anything in this function.  It is placed   here and prepared using the `alloca' magic to prevent it from being   inlined.  The function is only called in case of an error.  But then   performance does not count.  The function used to be "inlinable" and   the compiled did so all the time.  This increased the code size for   absolutely no good reason.  */static void__attribute__ ((noreturn))lose (int code, int fd, const char *name, char *realname, struct link_map *l,      const char *msg){  /* The use of `alloca' here looks ridiculous but it helps.  The goal     is to avoid the function from being inlined.  There is no official     way to do this so we use this trick.  gcc never inlines functions     which use `alloca'.  */  int *a = (int *) alloca (sizeof (int));  a[0] = fd;  /* The file might already be closed.  */  if (a[0] != -1)    (void) close (a[0]);  if (l != NULL)    {      /* Remove the stillborn object from the list and free it.  */      assert (l->l_next == NULL);#ifndef SHARED      if (l->l_prev == NULL)	/* No other module loaded.  */	_dl_loaded = NULL;      else#endif	l->l_prev->l_next = NULL;      --_dl_nloaded;      free (l);    }  free (realname);  _dl_signal_error (code, name, NULL, msg);}/* Map in the shared object NAME, actually located in REALNAME, and already   opened on FD.  */#ifndef EXTERNAL_MAP_FROM_FDstatic#endifstruct link_map *_dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,			char *realname, struct link_map *loader, int l_type,			int mode){  struct link_map *l = NULL;  const ElfW(Ehdr) *header;  const ElfW(Phdr) *phdr;  const ElfW(Phdr) *ph;  size_t maplength;  int type;  struct stat64 st;  /* Initialize to keep the compiler happy.  */  const char *errstring = NULL;  int errval = 0;  /* Get file information.  */  if (__builtin_expect (fstat64 (fd, &st) < 0, 0))    {      errstring = N_("cannot stat shared object");    call_lose_errno:      errval = errno;    call_lose:      fprintf (stderr, "%s\n", errstring);      lose (errval, fd, name, realname, l, errstring);    }  /* Look again to see if the real name matched another already loaded.  */  for (l = _dl_loaded; l; l = l->l_next)    if (l->l_ino == st.st_ino && l->l_dev == st.st_dev)      {	/* The object is already loaded.	   Just bump its reference count and return it.  */	close (fd);	/* If the name is not in the list of names for this object add	   it.  */	free (realname);	add_name_to_object (l, name);	return l;      }  if (mode & RTLD_NOLOAD)    /* We are not supposed to load the object unless it is already       loaded.  So return now.  */    return NULL;  /* Print debugging message.  */  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))    _dl_debug_printf ("file=%s;  generating link map\n", name);  /* This is the ELF header.  We read it in `open_verify'.  */  header = (void *) fbp->buf;#ifndef MAP_ANON# define MAP_ANON 0  if (_dl_zerofd == -1)    {      _dl_zerofd = _dl_sysdep_open_zero_fill ();      if (_dl_zerofd == -1)	{	  close (fd);	  _dl_signal_error (errno, NULL, NULL,			    N_("cannot open zero fill device"));	}    }#endif  /* Enter the new object in the list of loaded objects.  */  l = _dl_new_object (realname, name, l_type, loader);  if (__builtin_expect (! l, 0))    {      errstring = N_("cannot create shared object descriptor");      goto call_lose_errno;    }  /* Extract the remaining details we need from the ELF header     and then read in the program header table.  */  l->l_entry = header->e_entry;  type = header->e_type;  l->l_phnum = header->e_phnum;  maplength = header->e_phnum * sizeof (ElfW(Phdr));  if (header->e_phoff + maplength <= fbp->len)    phdr = (void *) (fbp->buf + header->e_phoff);  else    {      phdr = alloca (maplength);      lseek (fd, SEEK_SET, header->e_phoff);      if (__libc_read (fd, (void *) phdr, maplength) != maplength)	{	  errstring = N_("cannot read file data");	  goto call_lose_errno;	}    }  {    /* Scan the program header table, collecting its load commands.  */    struct loadcmd      {	ElfW(Addr) mapstart, mapend, dataend, allocend;	off_t mapoff;	int prot;      } loadcmds[l->l_phnum], *c;    size_t nloadcmds = 0;    /* The struct is initialized to zero so this is not necessary:    l->l_ld = 0;    l->l_phdr = 0;    l->l_addr = 0; */    for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)      switch (ph->p_type)	{	  /* These entries tell us where to find things once the file's	     segments are mapped in.  We record the addresses it says	     verbatim, and later correct for the run-time load address.  */	case PT_DYNAMIC:	  l->l_ld = (void *) ph->p_vaddr;	  l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));	  break;	case PT_PHDR:	  l->l_phdr = (void *) ph->p_vaddr;	  break;	case PT_LOAD:	  /* A load command tells us to map in part of the file.	     We record the load commands and process them all later.  */	  if ((ph->p_align & (_dl_pagesize - 1)) != 0)	    {	      errstring = N_("ELF load command alignment not page-aligned");	      goto call_lose;	    }	  if (((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)) != 0)	    {	      errstring		= N_("ELF load command address/offset not properly aligned");	      goto call_lose;	    }	  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -