about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/dl-osinfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/dl-osinfo.h')
-rw-r--r--sysdeps/unix/sysv/linux/dl-osinfo.h226
1 files changed, 63 insertions, 163 deletions
diff --git a/sysdeps/unix/sysv/linux/dl-osinfo.h b/sysdeps/unix/sysv/linux/dl-osinfo.h
index 3c93218dfc..abc67fcdcf 100644
--- a/sysdeps/unix/sysv/linux/dl-osinfo.h
+++ b/sysdeps/unix/sysv/linux/dl-osinfo.h
@@ -1,5 +1,5 @@
-/* Operating system specific code for generic dynamic loader functions.  Linux.
-   Copyright (C) 2000,2001,2002,2004,2005,2006 Free Software Foundation, Inc.
+/* Operating system specific code  for generic dynamic loader functions.
+   Copyright (C) 2000, 2001, 2002, 2004 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
@@ -18,14 +18,10 @@
    02111-1307 USA.  */
 
 #include <string.h>
-#include <errno.h>
 #include <fcntl.h>
+#include <sys/sysctl.h>
 #include <sys/utsname.h>
-#include <kernel-features.h>
-#include <dl-sysdep.h>
-#include <stdint.h>
-#include <hp-timing.h>
-#include <endian.h>
+#include "kernel-features.h"
 
 #ifndef MIN
 # define MIN(a,b) (((a)<(b))?(a):(b))
@@ -43,167 +39,71 @@ dl_fatal (const char *str)
 }
 #endif
 
-static inline int __attribute__ ((always_inline))
-_dl_discover_osversion (void)
-{
-#if (defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO) && defined SHARED
-  if (GLRO(dl_sysinfo_map) != NULL)
-    {
-      /* If the kernel-supplied DSO contains a note indicating the kernel's
-	 version, we don't need to call uname or parse any strings.  */
-
-      static const struct
-      {
-	ElfW(Word) vendorlen;
-	ElfW(Word) datalen;
-	ElfW(Word) type;
-	char vendor[8];
-      } expected_note = { sizeof "Linux", sizeof (ElfW(Word)), 0, "Linux" };
-      const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
-      const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
-      for (uint_fast16_t i = 0; i < phnum; ++i)
-	if (phdr[i].p_type == PT_NOTE)
-	  {
-	    const ElfW(Addr) start = (phdr[i].p_vaddr
-				      + GLRO(dl_sysinfo_map)->l_addr);
-	    const struct
-	    {
-	      ElfW(Word) vendorlen;
-	      ElfW(Word) datalen;
-	      ElfW(Word) type;
-	    } *note = (const void *) start;
-	    while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
-	      {
-		if (!memcmp (note, &expected_note, sizeof expected_note))
-		  return *(const ElfW(Word) *) ((const void *) note
-						+ sizeof expected_note);
-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
-		note = ((const void *) (note + 1)
-			+ ROUND (note->vendorlen) + ROUND (note->datalen));
-	      }
-	  }
-    }
-#endif
-
-  char bufmem[64];
-  char *buf = bufmem;
-  unsigned int version;
-  int parts;
-  char *cp;
-  struct utsname uts;
-
-  /* Try the uname system call.  */
-  if (__uname (&uts))
-    {
-      /* This was not successful.  Now try reading the /proc filesystem.  */
-      int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);
-      if (fd < 0)
-	return -1;
-      ssize_t reslen = __read (fd, bufmem, sizeof (bufmem));
-      __close (fd);
-      if (reslen <= 0)
-	/* This also didn't work.  We give up since we cannot
-	   make sure the library can actually work.  */
-	return -1;
-      buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0';
-    }
-  else
-    buf = uts.release;
-
-  /* Now convert it into a number.  The string consists of at most
-     three parts.  */
-  version = 0;
-  parts = 0;
-  cp = buf;
-  while ((*cp >= '0') && (*cp <= '9'))
-    {
-      unsigned int here = *cp++ - '0';
-
-      while ((*cp >= '0') && (*cp <= '9'))
-	{
-	  here *= 10;
-	  here += *cp++ - '0';
-	}
 
-      ++parts;
-      version <<= 8;
-      version |= here;
-
-      if (*cp++ != '.')
-	/* Another part following?  */
-	break;
-    }
-
-  if (parts < 3)
-    version <<= 8 * (3 - parts);
-
-  return version;
-}
-
-#define DL_SYSDEP_OSCHECK(FATAL)					      \
+#define DL_SYSDEP_OSCHECK(FATAL) \
   do {									      \
-    /* Test whether the kernel is new enough.  This test is only performed    \
-       if the library is not compiled to run on all kernels.  */	      \
-									      \
-    int version = _dl_discover_osversion ();				      \
-    if (__builtin_expect (version >= 0, 1))				      \
+    /* Test whether the kernel is new enough.  This test is only	      \
+       performed if the library is not compiled to run on all		      \
+       kernels.  */							      \
+    if (__LINUX_KERNEL_VERSION > 0)					      \
       {									      \
-	if (__builtin_expect (GLRO(dl_osversion) == 0, 1)		      \
-	    || GLRO(dl_osversion) > version)				      \
-	  GLRO(dl_osversion) = version;					      \
+	char bufmem[64];						      \
+	char *buf = bufmem;						      \
+	unsigned int version;						      \
+	int parts;							      \
+	char *cp;							      \
+	struct utsname uts;						      \
+									      \
+	/* Try the uname syscall */					      \
+	if (__uname (&uts))					      	      \
+	  {							      	      \
+	    /* This was not successful.  Now try reading the /proc	      \
+	       filesystem.  */						      \
+	    ssize_t reslen;						      \
+	    int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);	      \
+	    if (fd == -1						      \
+		|| (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0)      \
+  	      /* This also didn't work.  We give up since we cannot	      \
+		 make sure the library can actually work.  */		      \
+	      FATAL ("FATAL: cannot determine kernel version\n");	      \
+	    __close (fd);						      \
+	    buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0';	      \
+	  }								      \
+	else								      \
+          buf = uts.release;						      \
+									      \
+	/* Now convert it into a number.  The string consists of at most      \
+	   three parts.  */						      \
+	version = 0;							      \
+	parts = 0;							      \
+	cp = buf;							      \
+	while ((*cp >= '0') && (*cp <= '9'))				      \
+	  {								      \
+	    unsigned int here = *cp++ - '0';				      \
+									      \
+	    while ((*cp >= '0') && (*cp <= '9'))			      \
+	      {								      \
+		here *= 10;						      \
+		here += *cp++ - '0';					      \
+	      }								      \
+									      \
+	    ++parts;							      \
+	    version <<= 8;						      \
+	    version |= here;						      \
+									      \
+	    if (*cp++ != '.')						      \
+	      /* Another part following?  */				      \
+	      break;							      \
+	  }								      \
+									      \
+	if (parts < 3)							      \
+	  version <<= 8 * (3 - parts);					      \
 									      \
 	/* Now we can test with the required version.  */		      \
-	if (__LINUX_KERNEL_VERSION > 0 && version < __LINUX_KERNEL_VERSION)   \
+	if (version < __LINUX_KERNEL_VERSION)				      \
 	  /* Not sufficent.  */						      \
 	  FATAL ("FATAL: kernel too old\n");				      \
+									      \
+	GLRO(dl_osversion) = version;					      \
       }									      \
-    else if (__LINUX_KERNEL_VERSION > 0)				      \
-      FATAL ("FATAL: cannot determine kernel version\n");		      \
   } while (0)
-
-static inline uintptr_t __attribute__ ((always_inline))
-_dl_setup_stack_chk_guard (void)
-{
-  uintptr_t ret;
-#ifdef ENABLE_STACKGUARD_RANDOMIZE
-  int fd = __open ("/dev/urandom", O_RDONLY);
-  if (fd >= 0)
-    {
-      ssize_t reslen = __read (fd, &ret, sizeof (ret));
-      __close (fd);
-      if (reslen == (ssize_t) sizeof (ret))
-	return ret;
-    }
-#endif
-  ret = 0;
-  unsigned char *p = (unsigned char *) &ret;
-  p[sizeof (ret) - 1] = 255;
-  p[sizeof (ret) - 2] = '\n';
-#ifdef HP_TIMING_NOW
-  hp_timing_t hpt;
-  HP_TIMING_NOW (hpt);
-  hpt = (hpt & 0xffff) << 8;
-  ret ^= hpt;
-#endif
-  uintptr_t stk;
-  /* Avoid GCC being too smart.  */
-  asm ("" : "=r" (stk) : "r" (p));
-  stk &= 0x7ffff0;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  stk <<= (__WORDSIZE - 23);
-#elif __WORDSIZE == 64
-  stk <<= 31;
-#endif
-  ret ^= stk;
-  /* Avoid GCC being too smart.  */
-  p = (unsigned char *) &errno;
-  asm ("" : "=r" (stk) : "r" (p));
-  stk &= 0x7fff00;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  stk <<= (__WORDSIZE - 29);
-#else
-  stk >>= 8;
-#endif
-  ret ^= stk;
-  return ret;
-}