summary refs log tree commit diff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-06-10 10:18:47 +0000
committerRoland McGrath <roland@gnu.org>1996-06-10 10:18:47 +0000
commit266180eb985e14fa9f77cfd3b41e9211e9986162 (patch)
tree666ad4e19f0e046ebc3fdbade19c7520b7061b1f /elf/dl-load.c
parent564210fe2fdf88dd0800590b256cdb0751da1dec (diff)
downloadglibc-266180eb985e14fa9f77cfd3b41e9211e9986162.tar.gz
glibc-266180eb985e14fa9f77cfd3b41e9211e9986162.tar.xz
glibc-266180eb985e14fa9f77cfd3b41e9211e9986162.zip
Mon Jun 10 06:14:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
	* sysdeps/mach/hurd/dl-sysdep.c (__open): Define this instead of open.
	(__close, __mmap): Likewise define with __ names now.

Mon Jun 10 05:13:18 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* elf/dl-support.c: New file.
	* elf/Makefile (CFLAGS-dl-support.c): New variable.
	(routines, elide-routines.so): Add dl-support.

	* elf/dl-minimal.c (_dl_pagesize): Remove common defn.
	* elf/dl-load.c (_dl_pagesize): Define it here.
	(_dl_map_object_from_fd): Initialize it if zero.
	* elf/link.h (_dl_pagesize): Remove const.

Sun Jun  9 04:04:26 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* elf/Makefile (routines): Add dl-symbol.
	* elf/dl-lookup.c (_dl_symbol_value): Moved to ...
	* elf/dl-symbol.c: New file.

	* elf/elf.h (Elf32_Xword, Elf32_Sxword): New types.
	(Elf32_Section, Elf64_Section): New types, 16 bits.
	(Elf32_Sym, Elf64_Sym): Use it.

	* elf/dl-deps.c (_dl_open): Moved to ...
	* elf/dl-open.c: New file.
	* Makefile (routines): Add dl-open.

	* elf/Makefile (dl-routines): New variable.
	(routines): Add $(dl-routines).
	(elide-routines.so): New variable, set to $(dl-routines).
	(libdl-inhibit-o): Variable removed; build all flavors of -ldl.
	(rtld-routines): All but rtld, dl-sysdep, and dl-minimal moved to
 	$(dl-routines).

	* elf/dl-lookup.c (_dl_lookup_symbol): Remove magic symbol grokage.

	* elf/dladdr.c: Use ELFW(ST_BIND) in place of ELF32_ST_BIND.

	* elf/dl-load.c (open_path): Use __ names for open and close.  Avoid
	using strdup.
	(_dl_map_object): Likewise.
	(_dl_map_object_from_fd): Use __ names for mmap, munmap, and mprotect.
	* elf/dl-minimal.c (malloc): Likewise.
	* elf/dl-reloc.c (_dl_relocate_object): Likewise.

	* elf/dl-minimal.c (_dl_pagesize): New variable.
	(malloc): Use that instead of a static variable.
	* elf/dl-reloc.c (_dl_relocate_object): Use _dl_pagesize instead of
	calling getpagesize.
	* elf/dl-load.c (_dl_map_object_from_fd): Likewise.
	* elf/link.h: Declare _dl_pagesize.

	* elf/rtld.c (dl_r_debug): Renamed to _dl_r_debug.

	* elf/link.h (struct link_map): Use Half for l_phnum instead of Word.
  	* elf/rtld.c (dl_main): Use Half for phdr count arg.
	(_dl_sysdep_start): Update prototype of DL_MAIN function ptr arg.

	* elf/dl-load.c (_dl_map_object_from_fd): Use explicit Elf32_Word to
 	extract 4-byte magic number, not ElfW(Word).  Match EI_CLASS against
 	native wordsize, either 32 or 64.

	* elf/elf.h (Elf64_Byte, Elf64_Section): Typedefs removed.  In C a
 	char is always a byte, no need for a typedef.  Section indices are
	16-bit quantities in elf64, which already have a typedef Elf64_Half.

	Remove partial -lelf implementation.  There is now a
	separately-distributed `libelf' package that implements it.
	* elf/dl-lookup.c: Don't #include <libelf.h> any more.
	(_dl_elf_hash): New function, moved from
	libelf.h:elf_hash.
	(_dl_lookup_symbol): Use it instead of elf_hash.
	* elf/libelf.h: File removed.
	* elf/elf_hash.c: File removed.
	* elf/Makefile (headers): Remove libelf.h.
	(extra-libs): Remove libelf.
	(libelf-routines): Variable removed.

	* elf/Makefile (libdl.so): Remove commands from this target.  The
 	implicit rule commands are correct, this explicit rule just serves to
 	add some dependencies.

	* elf/dl-lookup.c (_dl_lookup_symbol): Use ELFW(ST_TYPE) in place of
 	ELF32_ST_TYPE.  Likewise ST_BIND.
	* elf/do-rel.h (elf_dynamic_do_rel): Likewise R_SYM.

	* elf/link.h (ElfW): New macro for wordsize-independent ElfXX_* type
	naming.
	(ELFW): New macro, likewise for ELFXX_* macro naming.
	(_ElfW, _ElfW_1): New macros, subroutines of ElfW and ELF.

Sat Jun  8 20:52:38 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* elf/link.h, elf/do-rel.h, elf/dynamic-link.h, elf/dl-deps.c,
 	elf/dl-init.c, elf/dl-load.c, elf/dl-lookup.c, elf/dl-reloc.c,
 	elf/dl-runtime.c, elf/dladdr.c, elf/dlclose.c, elf/dlsym.c,
 	elf/linux-compat.c, elf/rtld.c: Change all uses of `Elf32_XXX' to
 	`ElfW(XXX)' for wordsize-independence.

Sat Jun  8 20:50:42 1996  Richard Henderson  <rth@tamu.edu>

	* elf/elf.h: Move Elf64_* types in parity with Elf32 counterparts.
	(Elf64_auxv_t): New type.
	(EM_ALPHA, R_ALPHA_*): New macros for elf64-alpha format.
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c133
1 files changed, 82 insertions, 51 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 8103c7af2a..c6acc8c222 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -60,6 +60,7 @@ Cambridge, MA 02139, USA.  */
 #define STRING(x) #x
 
 int _dl_zerofd = -1;
+size_t _dl_pagesize;
 
 
 /* Try to open NAME in one of the directories in DIRPATH.
@@ -82,31 +83,48 @@ open_path (const char *name, size_t namelen,
       return -1;
     }
 
-  buf = alloca (strlen (dirpath) + 1 + namelen);
+  buf = __alloca (strlen (dirpath) + 1 + namelen);
   do
     {
+      size_t buflen;
+
       dirpath = p;
       p = strpbrk (dirpath, ":;");
       if (p == NULL)
 	p = strchr (dirpath, '\0');
 
       if (p == dirpath)
-	/* Two adjacent colons, or a colon at the beginning or the end of
-	   the path means to search the current directory.  */
-	(void) memcpy (buf, name, namelen);
+	{
+	  /* Two adjacent colons, or a colon at the beginning or the end of
+	     the path means to search the current directory.  */
+	  (void) memcpy (buf, name, namelen);
+	  buflen = namelen;
+	}
       else
 	{
 	  /* Construct the pathname to try.  */
 	  (void) memcpy (buf, dirpath, p - dirpath);
 	  buf[p - dirpath] = '/';
 	  (void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
+	  buflen = p - dirpath + 1 + namelen;
 	}
 
-      fd = open (buf, O_RDONLY);
+      fd = __open (buf, O_RDONLY);
       if (fd != -1)
 	{
-	  *realname = strdup (buf);
-	  return fd;
+	  *realname = malloc (buflen);
+	  if (*realname)
+	    {
+	      memcpy (*realname, buf, buflen);
+	      return fd;
+	    }
+	  else
+	    {
+	      /* No memory for the name, we certainly won't be able
+		 to load and link it.  */
+	      __close (fd);
+	      return -1;
+	    }
 	}
       if (errno != ENOENT && errno != EACCES)
 	/* The file exists and is readable, but something went wrong.  */
@@ -117,7 +135,6 @@ open_path (const char *name, size_t namelen,
   return -1;
 }
 
-
 /* Map in the shared object file NAME.  */
 
 struct link_map *
@@ -163,9 +180,19 @@ _dl_map_object (struct link_map *loader, const char *name)
     }
   else
     {
-      fd = open (name, O_RDONLY);
+      fd = __open (name, O_RDONLY);
       if (fd != -1)
-	realname = strdup (name);
+	{
+	  size_t len = strlen (name) + 1;
+	  realname = malloc (len);
+	  if (realname)
+	    memcpy (realname, name, len);
+	  else
+	    {
+	      __close (fd);
+	      fd = -1;
+	    }
+	}
     }
 
   if (fd == -1)
@@ -182,25 +209,24 @@ struct link_map *
 _dl_map_object_from_fd (const char *name, int fd, char *realname)
 {
   struct link_map *l = NULL;
-  const size_t pagesize = getpagesize ();
   void *file_mapping = NULL;
   size_t mapping_size = 0;
 
 #define LOSE(s) lose (0, (s))
   void lose (int code, const char *msg)
     {
-      (void) close (fd);
+      (void) __close (fd);
       if (file_mapping)
-	munmap (file_mapping, mapping_size);
+	__munmap (file_mapping, mapping_size);
       _dl_signal_error (code, l ? l->l_name : name, msg);
     }
 
-  inline caddr_t map_segment (Elf32_Addr mapstart, size_t len,
+  inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
 			      int prot, int fixed, off_t offset)
     {
-      caddr_t mapat = mmap ((caddr_t) mapstart, len, prot,
-			    fixed|MAP_COPY|MAP_FILE,
-			    fd, offset);
+      caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot,
+			      fixed|MAP_COPY|MAP_FILE,
+			      fd, offset);
       if (mapat == (caddr_t) -1)
 	lose (errno, "failed to map segment from shared object");
       return mapat;
@@ -213,11 +239,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	{
 	  void *result;
 	  if (file_mapping)
-	    munmap (file_mapping, mapping_size);
-	  mapping_size = (location + size + 1 + pagesize - 1);
-	  mapping_size &= ~(pagesize - 1);
-	  result = mmap (file_mapping, mapping_size, PROT_READ,
-			 MAP_COPY|MAP_FILE, fd, 0);
+	    __munmap (file_mapping, mapping_size);
+	  mapping_size = (location + size + 1 + _dl_pagesize - 1);
+	  mapping_size &= ~(_dl_pagesize - 1);
+	  result = __mmap (file_mapping, mapping_size, PROT_READ,
+			   MAP_COPY|MAP_FILE, fd, 0);
 	  if (result == (void *) -1)
 	    lose (errno, "cannot map file data");
 	  file_mapping = result;
@@ -225,9 +251,9 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
       return file_mapping + location;
     }
 
-  const Elf32_Ehdr *header;
-  const Elf32_Phdr *phdr;
-  const Elf32_Phdr *ph;
+  const ElfW(Ehdr) *header;
+  const ElfW(Phdr) *phdr;
+  const ElfW(Phdr) *ph;
   int type;
 
   /* Look again to see if the real name matched another already loaded.  */
@@ -236,12 +262,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
       {
 	/* The object is already loaded.
 	   Just bump its reference count and return it.  */
-	close (fd);
+	__close (fd);
 	free (realname);
 	++l->l_opencount;
 	return l;
       }
 
+  if (_dl_pagesize == 0)
+    _dl_pagesize = __getpagesize ();
+
   /* Map in the first page to read the header.  */
   header = map (0, sizeof *header);
 
@@ -260,8 +289,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 #endif
       )
     LOSE ("invalid ELF header");
-  if (header->e_ident[EI_CLASS] != ELFCLASS32)
-    LOSE ("ELF file class not 32-bit");
+#define ELF32_CLASS ELFCLASS32
+#define ELF64_CLASS ELFCLASS64
+  if (header->e_ident[EI_CLASS] != ELFW(CLASS))
+    LOSE ("ELF file class not " STRING(__ELF_WORDSIZE) "-bit");
   if (header->e_ident[EI_DATA] != byteorder)
     LOSE ("ELF file data encoding not " byteorder_name);
   if (header->e_ident[EI_VERSION] != EV_CURRENT)
@@ -270,7 +301,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
     LOSE ("ELF file version not " STRING(EV_CURRENT));
   if (! elf_machine_matches_host (header->e_machine))
     LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
-  if (header->e_phentsize != sizeof (Elf32_Phdr))
+  if (header->e_phentsize != sizeof (ElfW(Phdr)))
     LOSE ("ELF file's phentsize not the expected size");
 
   /* Enter the new object in the list of loaded objects.  */
@@ -289,13 +320,13 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
   l->l_entry = header->e_entry;
   type = header->e_type;
   l->l_phnum = header->e_phnum;
-  phdr = map (header->e_phoff, l->l_phnum * sizeof (Elf32_Phdr));
+  phdr = map (header->e_phoff, l->l_phnum * sizeof (ElfW(Phdr)));
 
   {
     /* Scan the program header table, collecting its load commands.  */
     struct loadcmd
       {
-	Elf32_Addr mapstart, mapend, dataend, allocend;
+	ElfW(Addr) mapstart, mapend, dataend, allocend;
 	off_t mapoff;
 	int prot;
       } loadcmds[l->l_phnum], *c;
@@ -320,15 +351,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	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 % pagesize != 0)
+	  if (ph->p_align % _dl_pagesize != 0)
 	    LOSE ("ELF load command alignment not page-aligned");
 	  if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
 	    LOSE ("ELF load command address/offset not properly aligned");
 	  {
 	    struct loadcmd *c = &loadcmds[nloadcmds++];
 	    c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
-	    c->mapend = ((ph->p_vaddr + ph->p_filesz + pagesize - 1)
-			 & ~(pagesize - 1));
+	    c->mapend = ((ph->p_vaddr + ph->p_filesz + _dl_pagesize - 1)
+			 & ~(_dl_pagesize - 1));
 	    c->dataend = ph->p_vaddr + ph->p_filesz;
 	    c->allocend = ph->p_vaddr + ph->p_memsz;
 	    c->mapoff = ph->p_offset & ~(ph->p_align - 1);
@@ -344,7 +375,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	}
 
     /* We are done reading the file's headers now.  Unmap them.  */
-    munmap (file_mapping, mapping_size);
+    __munmap (file_mapping, mapping_size);
 
     /* Now process the load commands and map segments into memory.  */
     c = loadcmds;
@@ -362,16 +393,16 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	mapat = map_segment (c->mapstart,
 			     loadcmds[nloadcmds - 1].allocend - c->mapstart,
 			     c->prot, 0, c->mapoff);
-	l->l_addr = (Elf32_Addr) mapat - c->mapstart;
+	l->l_addr = (ElfW(Addr)) mapat - c->mapstart;
 
 	/* Change protection on the excess portion to disallow all access;
 	   the portions we do not remap later will be inaccessible as if
 	   unallocated.  Then jump into the normal segment-mapping loop to
 	   handle the portion of the segment past the end of the file
 	   mapping.  */
-	mprotect (mapat + c->mapend,
-		  loadcmds[nloadcmds - 1].allocend - c->mapend,
-		  0);
+	__mprotect (mapat + c->mapend,
+		    loadcmds[nloadcmds - 1].allocend - c->mapend,
+		    0);
 	goto postmap;
       }
 
@@ -387,11 +418,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	  {
 	    /* Extra zero pages should appear at the end of this segment,
 	       after the data mapped from the file.   */
-	    Elf32_Addr zero, zeroend, zeropage;
+	    ElfW(Addr) zero, zeroend, zeropage;
 
 	    zero = l->l_addr + c->dataend;
 	    zeroend = l->l_addr + c->allocend;
-	    zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
+	    zeropage = (zero + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
 
 	    if (zeroend < zeropage)
 	      /* All the extra data is in the last page of the segment.
@@ -404,23 +435,23 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 		if ((c->prot & PROT_WRITE) == 0)
 		  {
 		    /* Dag nab it.  */
-		    if (mprotect ((caddr_t) (zero & ~(pagesize - 1)),
-				  pagesize, c->prot|PROT_WRITE) < 0)
+		    if (__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
+				    _dl_pagesize, c->prot|PROT_WRITE) < 0)
 		      lose (errno, "cannot change memory protections");
 		  }
 		memset ((void *) zero, 0, zeropage - zero);
 		if ((c->prot & PROT_WRITE) == 0)
-		  mprotect ((caddr_t) (zero & ~(pagesize - 1)),
-			    pagesize, c->prot);
+		  __mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
+			      _dl_pagesize, c->prot);
 	      }
 
 	    if (zeroend > zeropage)
 	      {
 		/* Map the remaining zero pages in from the zero fill FD.  */
 		caddr_t mapat;
-		mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
-			      MAP_ANON|MAP_PRIVATE|MAP_FIXED,
-			      _dl_zerofd, 0);
+		mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
+				c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+				_dl_zerofd, 0);
 		if (mapat == (caddr_t) -1)
 		  lose (errno, "cannot map zero-fill pages");
 	      }
@@ -441,11 +472,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
 	LOSE ("object file has no dynamic section");
     }
   else
-    (Elf32_Addr) l->l_ld += l->l_addr;
+    (ElfW(Addr)) l->l_ld += l->l_addr;
 
   if (l->l_phdr == 0)
-    l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
-  (Elf32_Addr) l->l_phdr += l->l_addr;
+    l->l_phdr = (void *) ((const ElfW(Ehdr) *) l->l_addr)->e_phoff;
+  (ElfW(Addr)) l->l_phdr += l->l_addr;
 
   elf_get_dynamic_info (l->l_ld, l->l_info);
   if (l->l_info[DT_HASH])