about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-close.c6
-rw-r--r--elf/dl-hwcaps.c14
-rw-r--r--elf/dl-misc.c23
-rw-r--r--elf/dl-open.c7
-rw-r--r--elf/dl-sysdep.c13
-rw-r--r--elf/dl-writev.h56
-rw-r--r--elf/ldconfig.c6
-rw-r--r--elf/sprof.c4
8 files changed, 95 insertions, 34 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index c86f609402..fe3014cca3 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -183,6 +183,8 @@ _dl_close_worker (struct link_map *map)
       /* Mark all dependencies as used.  */
       if (l->l_initfini != NULL)
 	{
+	  /* We are always the zeroth entry, and since we don't include
+	     ourselves in the dependency analysis start at 1.  */
 	  struct link_map **lp = &l->l_initfini[1];
 	  while (*lp != NULL)
 	    {
@@ -193,6 +195,10 @@ _dl_close_worker (struct link_map *map)
 		  if (!used[(*lp)->l_idx])
 		    {
 		      used[(*lp)->l_idx] = 1;
+		      /* If we marked a new object as used, and we've
+			 already processed it, then we need to go back
+			 and process again from that point forward to
+			 ensure we keep all of its dependencies also.  */
 		      if ((*lp)->l_idx - 1 < done_index)
 			done_index = (*lp)->l_idx - 1;
 		    }
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
index 8d49383d76..1b7fe52a6a 100644
--- a/elf/dl-hwcaps.c
+++ b/elf/dl-hwcaps.c
@@ -66,6 +66,11 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
 	  {
 	    const ElfW(Addr) start = (phdr[i].p_vaddr
 				      + GLRO(dl_sysinfo_map)->l_addr);
+	    /* The standard ELF note layout is exactly as the anonymous struct.
+	       The next element is a variable length vendor name of length
+	       VENDORLEN (with a real length rounded to ElfW(Addr)), followed
+	       by the data of length DATALEN (with a real length rounded to
+	       ElfW(Addr)).  */
 	    const struct
 	    {
 	      ElfW(Word) vendorlen;
@@ -75,6 +80,11 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
 	    while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
 	      {
 #define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+		/* The layout of the type 2, vendor "GNU" note is as follows:
+		   .long <Number of capabilities enabled by this note>
+		   .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
+		   .byte <The bit number for the next capability>
+		   .asciz <The name of the capability>.  */
 		if (note->type == NT_GNU_HWCAP
 		    && note->vendorlen == sizeof "GNU"
 		    && !memcmp ((note + 1), "GNU", sizeof "GNU")
@@ -84,7 +94,7 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
 					   + ROUND (sizeof "GNU"));
 		    cnt += *p++;
 		    ++p;	/* Skip mask word.  */
-		    dsocaps = (const char *) p;
+		    dsocaps = (const char *) p; /* Pseudo-string "<b>name"  */
 		    dsocapslen = note->datalen - sizeof *p * 2;
 		    break;
 		  }
@@ -107,6 +117,8 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
 #ifdef NEED_DL_SYSINFO_DSO
   if (dsocaps != NULL)
     {
+      /* dsocaps points to the .asciz string, and -1 points to the mask
+         .long just before the string.  */
       const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
       GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
       /* Note that we add the dsocaps to the set already chosen by the
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index a8e9a3f2f0..e0e105b88f 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -31,7 +31,8 @@
 #include <sys/uio.h>
 #include <sysdep.h>
 #include <_itoa.h>
-#include <bits/libc-lock.h>
+#include <dl-writev.h>
+
 
 /* Read the whole contents of FILE into new mmap'd space with given
    protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
@@ -239,25 +240,7 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
     }
 
   /* Finally write the result.  */
-#ifdef HAVE_INLINED_SYSCALLS
-  INTERNAL_SYSCALL_DECL (err);
-  INTERNAL_SYSCALL (writev, err, 3, fd, &iov, niov);
-#elif RTLD_PRIVATE_ERRNO
-  /* We have to take this lock just to be sure we don't clobber the private
-     errno when it's being used by another thread that cares about it.
-     Yet we must be sure not to try calling the lock functions before
-     the thread library is fully initialized.  */
-  if (__builtin_expect (INTUSE (_dl_starting_up), 0))
-    __writev (fd, iov, niov);
-  else
-    {
-      __rtld_lock_lock_recursive (GL(dl_load_lock));
-      __writev (fd, iov, niov);
-      __rtld_lock_unlock_recursive (GL(dl_load_lock));
-    }
-#else
-  __writev (fd, iov, niov);
-#endif
+  _dl_writev (fd, iov, niov);
 }
 
 
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 9ff5f5736d..92fae7f59b 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -37,13 +37,6 @@
 #include <dl-dst.h>
 
 
-extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
-				    void (*dl_main) (const ElfW(Phdr) *phdr,
-						     ElfW(Word) phnum,
-						     ElfW(Addr) *user_entry,
-						     ElfW(auxv_t) *auxv));
-weak_extern (_dl_sysdep_start)
-
 extern int __libc_multiple_libcs;	/* Defined in init-first.c.  */
 
 /* We must be careful not to leave us in an inconsistent state.  Thus we
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 832a57b6d6..6fdcb13145 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -214,10 +214,15 @@ _dl_sysdep_start (void **start_argptr,
     GLRO(dl_pagesize) = __getpagesize ();
 #endif
 
-#if defined NEED_DL_SYSINFO
-  /* Only set the sysinfo value if we also have the vsyscall DSO.  */
-  if (GLRO(dl_sysinfo_dso) != 0 && new_sysinfo)
-    GLRO(dl_sysinfo) = new_sysinfo;
+#ifdef NEED_DL_SYSINFO
+  if (new_sysinfo != 0)
+    {
+# ifdef NEED_DL_SYSINFO_DSO
+      /* Only set the sysinfo value if we also have the vsyscall DSO.  */
+      if (GLRO(dl_sysinfo_dso) != 0)
+# endif
+        GLRO(dl_sysinfo) = new_sysinfo;
+    }
 #endif
 
 #ifdef DL_SYSDEP_INIT
diff --git a/elf/dl-writev.h b/elf/dl-writev.h
new file mode 100644
index 0000000000..0fc0b2b864
--- /dev/null
+++ b/elf/dl-writev.h
@@ -0,0 +1,56 @@
+/* Message-writing for the dynamic linker.  Generic version.
+   Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/uio.h>
+#include <ldsodefs.h>
+#include <bits/libc-lock.h>
+
+/* This is used from only one place: dl-misc.c:_dl_debug_vdprintf.
+   Hence it's in a header with the expectation it will be inlined.
+
+   This is writev, but with a constraint added and others loosened:
+
+   1. Under RTLD_PRIVATE_ERRNO, it must not clobber the private errno
+      when another thread holds the dl_load_lock.
+   2. It is not obliged to detect and report errors at all.
+   3. It's not really obliged to deliver a single atomic write
+      (though it may be preferable).  */
+
+static inline void
+_dl_writev (int fd, const struct iovec *iov, size_t niov)
+{
+  /* Note that if __writev is an implementation that calls malloc,
+     this will cause linking problems building the dynamic linker.  */
+
+#if RTLD_PRIVATE_ERRNO
+  /* We have to take this lock just to be sure we don't clobber the private
+     errno when it's being used by another thread that cares about it.
+     Yet we must be sure not to try calling the lock functions before
+     the thread library is fully initialized.  */
+  if (__builtin_expect (INTUSE (_dl_starting_up), 0))
+    __writev (fd, iov, niov);
+  else
+    {
+      __rtld_lock_lock_recursive (GL(dl_load_lock));
+      __writev (fd, iov, niov);
+      __rtld_lock_unlock_recursive (GL(dl_load_lock));
+    }
+#else
+  __writev (fd, iov, niov);
+#endif
+}
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 57c6a6f04d..340c132a83 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -173,13 +173,17 @@ is_hwcap_platform (const char *name)
 {
   int hwcap_idx = _dl_string_hwcap (name);
 
+  /* Is this a normal hwcap for the machine e.g. fpu?  */
   if (hwcap_idx != -1 && ((1 << hwcap_idx) & hwcap_mask))
     return 1;
 
+  /* ... Or is it a platform pseudo-hwcap e.g. i686?  */
   hwcap_idx = _dl_string_platform (name);
   if (hwcap_idx != -1)
     return 1;
 
+  /* ... Or is this one of the extra pseudo-hwcaps that we map beyond
+     _DL_FIRST_EXTRA e.g. tls, or nosegneg?  */
   for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
     if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
 	&& !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
@@ -1265,6 +1269,8 @@ main (int argc, char **argv)
 	  add_dir (argv[i]);
     }
 
+  /* The last entry in hwcap_extra is reserved for the "tls"
+     pseudo-hwcap which indicates support for TLS.  */
   hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
 
   set_hwcap ();
diff --git a/elf/sprof.c b/elf/sprof.c
index 54dfebdd5a..5c70ec0473 100644
--- a/elf/sprof.c
+++ b/elf/sprof.c
@@ -744,7 +744,7 @@ load_profdata (const char *name, struct shobj *shobj)
 {
   struct profdata *result;
   int fd;
-  struct stat st;
+  struct stat64 st;
   void *addr;
   uint32_t *narcsp;
   size_t fromlimit;
@@ -783,7 +783,7 @@ load_profdata (const char *name, struct shobj *shobj)
 
   /* We have found the file, now make sure it is the right one for the
      data file.  */
-  if (fstat (fd, &st) < 0)
+  if (fstat64 (fd, &st) < 0)
     {
       error (0, errno, _("while stat'ing profiling data file"));
       close (fd);