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

📄 dl-load.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Map in a shared object's segments from the file.   Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.   This file is part of the GNU C Library.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */#include <elf.h>#include <errno.h>#include <fcntl.h>#include <libintl.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <ldsodefs.h>#include <sys/mman.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/types.h>#include "dynamic-link.h"#include <abi-tag.h>#include <dl-osinfo.h>#include <dl-dst.h>/* On some systems, no flag bits are given to specify file mapping.  */#ifndef MAP_FILE# define MAP_FILE	0#endif/* The right way to map in the shared library files is MAP_COPY, which   makes a virtual copy of the data at the time of the mmap call; this   guarantees the mapped pages will be consistent even if the file is   overwritten.  Some losing VM systems like Linux's lack MAP_COPY.  All we   get is MAP_PRIVATE, which copies each page when it is modified; this   means if the file is overwritten, we may at some point get some pages   from the new version after starting with pages from the old version.  */#ifndef MAP_COPY# define MAP_COPY	MAP_PRIVATE#endif/* Some systems link their relocatable objects for another base address   than 0.  We want to know the base address for these such that we can   subtract this address from the segment addresses during mapping.   This results in a more efficient address space usage.  Defaults to   zero for almost all systems.  */#ifndef MAP_BASE_ADDR# define MAP_BASE_ADDR(l)	0#endif#include <endian.h>#if BYTE_ORDER == BIG_ENDIAN# define byteorder ELFDATA2MSB#elif BYTE_ORDER == LITTLE_ENDIAN# define byteorder ELFDATA2LSB#else# error "Unknown BYTE_ORDER " BYTE_ORDER# define byteorder ELFDATANONE#endif#define STRING(x) __STRING (x)#ifdef MAP_ANON/* The fd is not examined when using MAP_ANON.  */# define ANONFD -1#elseint _dl_zerofd = -1;# define ANONFD _dl_zerofd#endif/* Handle situations where we have a preferred location in memory for   the shared objects.  */#ifdef ELF_PREFERRED_ADDRESS_DATAELF_PREFERRED_ADDRESS_DATA;#endif#ifndef ELF_PREFERRED_ADDRESS# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)#endif#ifndef ELF_FIXED_ADDRESS# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)#endif/* Type for the buffer we put the ELF header and hopefully the program   header.  This buffer does not really have to be too large.  In most   cases the program header follows the ELF header directly.  If this   is not the case all bets are off and we can make the header arbitrarily   large and still won't get it read.  This means the only question is   how large are the ELF and program header combined.  The ELF header   in 64-bit files is 56 bytes long.  Each program header entry is again   56 bytes long.  I.e., even with a file which has 17 program header   entries we only have to read 1kB.  And 17 program header entries is   plenty, normal files have < 10.  If this heuristic should really fail   for some file the code in `_dl_map_object_from_fd' knows how to   recover.  */struct filebuf{  ssize_t len;  char buf[1024];};size_t _dl_pagesize;unsigned int _dl_osversion;int _dl_clktck;extern const char *_dl_platform;extern size_t _dl_platformlen;/* The object to be initialized first.  */struct link_map *_dl_initfirst;/* This is the decomposed LD_LIBRARY_PATH search path.  */static struct r_search_path_struct env_path_list;/* List of the hardware capabilities we might end up using.  */static const struct r_strlenpair *capstr;static size_t ncapstr;static size_t max_capstrlen;/* Get the generated information about the trusted directories.  */#include "trusted-dirs.h"static const char system_dirs[] = SYSTEM_DIRS;static const size_t system_dirs_len[] ={  SYSTEM_DIRS_LEN};#define nsystem_dirs_len \  (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))/* Local version of `strdup' function.  */static inline char *local_strdup (const char *s){  size_t len = strlen (s) + 1;  void *new = malloc (len);  if (new == NULL)    return NULL;  return (char *) memcpy (new, s, len);}static size_tis_dst (const char *start, const char *name, const char *str, size_t cmplen,	int is_path, int secure){  size_t len;  if (strncmp (name, str, cmplen) == 0)    len = cmplen + 1;  else if (strncmp (name, str + 1, cmplen - 2) == 0	   && (name[cmplen - 2] == '\0' || name[cmplen - 2] == '/'	       || (is_path && name[cmplen - 2] == ':')))    len = cmplen - 1;  else    return 0;  if (__builtin_expect (secure, 0)      && ((name[len - 1] != '\0' && (!is_path || name[len - 1] != ':'))	  || (name != start + 1 && (!is_path || name[-2] != ':'))))    return 0;  return len;}size_t_dl_dst_count (const char *name, int is_path){  const char *const start = name;  size_t cnt = 0;  do    {      size_t len = 1;      /* $ORIGIN is not expanded for SUID/GUID programs (except if it	 is $ORIGIN alone) and it must always appear first in path.	 Note that it is no bug that the string in the second and	 fourth `strncmp' call is longer than the sequence which is	 actually tested.  */      if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,			 0)) != 0	  || ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path, 0))	      != 0))	++cnt;      name = strchr (name + len, '$');    }  while (name != NULL);  return cnt;}char *_dl_dst_substitute (struct link_map *l, const char *name, char *result,		    int is_path){  const char *const start = name;  char *last_elem, *wp;  /* Now fill the result path.  While copying over the string we keep     track of the start of the last path element.  When we come accross     a DST we copy over the value or (if the value is not available)     leave the entire path element out.  */  last_elem = wp = result;  do    {      if (__builtin_expect (*name == '$', 0))	{	  const char *repl = NULL;	  size_t len = 1;	  /* Note that it is no bug that the string in the second and	     fourth `strncmp' call is longer than the sequence which	     is actually tested.  */	  if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,			     0)) != 0)	    repl = l->l_origin;	  else if ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path,				  0)) != 0)	    repl = _dl_platform;	  if (repl != NULL && repl != (const char *) -1)	    {	      wp = strcpy (wp, repl);              wp += strlen (repl);	      name += len;	    }	  else if (len > 1)	    {	      /* We cannot use this path element, the value of the		 replacement is unknown.  */	      wp = last_elem;	      name += len;	      while (*name != '\0' && (!is_path || *name != ':'))		++name;	    }	  else	    /* No DST we recognize.  */	    *wp++ = *name++;	}      else	{	  *wp++ = *name++;	  if (is_path && *name == ':')	    last_elem = wp;	}    }  while (*name != '\0');  *wp = '\0';  return result;}/* Return copy of argument with all recognized dynamic string tokens   ($ORIGIN and $PLATFORM for now) replaced.  On some platforms it   might not be possible to determine the path from which the object   belonging to the map is loaded.  In this case the path element   containing $ORIGIN is left out.  */static char *expand_dynamic_string_token (struct link_map *l, const char *s){  /* We make two runs over the string.  First we determine how large the     resulting string is and then we copy it over.  Since this is now     frequently executed operation we are looking here not for performance     but rather for code size.  */  size_t cnt;  size_t total;  char *result;  /* Determine the number of DST elements.  */  cnt = DL_DST_COUNT (s, 1);  /* If we do not have to replace anything simply copy the string.  */  if (__builtin_expect (cnt, 0) == 0)    return local_strdup (s);  /* Determine the length of the substituted string.  */  total = DL_DST_REQUIRED (l, s, strlen (s), cnt);  /* Allocate the necessary memory.  */  result = (char *) malloc (total + 1);  if (result == NULL)    return NULL;  return DL_DST_SUBSTITUTE (l, s, result, 1);}/* Add `name' to the list of names for a particular shared object.   `name' is expected to have been allocated with malloc and will   be freed if the shared object already has this name.   Returns false if the object already had this name.  */static voidinternal_functionadd_name_to_object (struct link_map *l, const char *name){  struct libname_list *lnp, *lastp;  struct libname_list *newname;  size_t name_len;  lastp = NULL;  for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next)    if (strcmp (name, lnp->name) == 0)      return;  name_len = strlen (name) + 1;  newname = (struct libname_list *) malloc (sizeof *newname + name_len);  if (newname == NULL)    {      /* No more memory.  */      _dl_signal_error (ENOMEM, name, NULL, N_("cannot allocate name record"));      return;    }  /* The object should have a libname set from _dl_new_object.  */  assert (lastp != NULL);  newname->name = memcpy (newname + 1, name, name_len);  newname->next = NULL;  newname->dont_free = 0;  lastp->next = newname;}/* All known directories in sorted order.  */struct r_search_path_elem *_dl_all_dirs;/* All directories after startup.  */struct r_search_path_elem *_dl_init_all_dirs;/* Standard search directories.  */static struct r_search_path_struct rtld_search_dirs;static size_t max_dirnamelen;static inline struct r_search_path_elem **fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,	      int check_trusted, const char *what, const char *where){  char *cp;  size_t nelems = 0;  printf("In fillin_rpath\n");  while ((cp = strsep (&rpath, sep)) != NULL)    {      struct r_search_path_elem *dirp;      size_t len = strlen (cp);      /* `strsep' can pass an empty string.  This has to be         interpreted as `use the current directory'. */      if (len == 0)	{	  static const char curwd[] = "./";	  cp = (char *) curwd;	}      /* Remove trailing slashes (except for "/").  */      while (len > 1 && cp[len - 1] == '/')	--len;      /* Now add one if there is none so far.  */      if (len > 0 && cp[len - 1] != '/')	cp[len++] = '/';      /* Make sure we don't use untrusted directories if we run SUID.  */      if (__builtin_expect (check_trusted, 0))	{	  const char *trun = system_dirs;	  size_t idx;	  int unsecure = 1;	  /* All trusted directories must be complete names.  */	  if (cp[0] == '/')	    {	      for (idx = 0; idx < nsystem_dirs_len; ++idx)		{		  if (len == system_dirs_len[idx]		      && memcmp (trun, cp, len) == 0)		    {		      /* Found it.  */		      unsecure = 0;		      break;		    }		  trun += system_dirs_len[idx] + 1;		}	    }	  if (unsecure)	    /* Simply drop this directory.  */	    continue;	}      /* See if this directory is already known.  */      for (dirp = _dl_all_dirs; dirp != NULL; dirp = dirp->next)	if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)	  break;      if (dirp != NULL)	{	  /* It is available, see whether it's on our own list.  */	  size_t cnt;	  for (cnt = 0; cnt < nelems; ++cnt)	    if (result[cnt] == dirp)	      break;	  if (cnt == nelems)	    result[nelems++] = dirp;	}      else	{	  size_t cnt;	  enum r_dir_status init_val;	  size_t where_len = where ? strlen (where) + 1 : 0;	  /* It's a new directory.  Create an entry and add it.  */	  dirp = (struct r_search_path_elem *)	    malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status)		    + where_len + len + 1);	  if (dirp == NULL)	    _dl_signal_error (ENOMEM, NULL, NULL,			      N_("cannot create cache for search path"));	  dirp->dirname = ((char *) dirp + sizeof (*dirp)			   + ncapstr * sizeof (enum r_dir_status));	  *((char *) (memcpy ((char *) dirp->dirname, cp, len) + len)) = '\0';	  dirp->dirnamelen = len;	  if (len > max_dirnamelen)	    max_dirnamelen = len;	  /* We have to make sure all the relative directories are	     never ignored.  The current directory might change and	     all our saved information would be void.  */

⌨️ 快捷键说明

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