[BZ #5786]
authorUlrich Drepper <drepper@redhat.com>
Sat, 8 Mar 2008 07:35:10 +0000 (07:35 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 8 Mar 2008 07:35:10 +0000 (07:35 +0000)
* elf/dl-sysdep.c: Undefine ROUND after use.
* sysdeps/generic/ldsodefs.h [HAVE_DL_DISCOVER_OSVERSION]
(struct rtld_global_ro): Add _dl_tls_get_addr_soft element.
* elf/rtld.c (rtld_global_ro): Initialize _dl_discover_osversion.
* sysdeps/unix/sysv/linux/dl-osinfo.h: Move _dl_discover_osversion
to ...
* sysdeps/unix/sysv/linux/dl-sysdep.c: ...here.
* sysdeps/unix/sysv/linux/dl-sysdep.h: Declare _dl_discover_osversion
if necessary.
* sysdeps/unix/sysv/linux/sysconf.c: Handle _SC_ARG_MAX here.

ChangeLog
elf/dl-sysdep.c
elf/dl-tls.c
elf/rtld.c
sysdeps/generic/ldsodefs.h
sysdeps/unix/sysv/linux/dl-osinfo.h
sysdeps/unix/sysv/linux/dl-sysdep.c
sysdeps/unix/sysv/linux/dl-sysdep.h
sysdeps/unix/sysv/linux/sysconf.c

index 7a6db2d..b3746f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-03-07  Ulrich Drepper  <drepper@redhat.com>
 
+       [BZ #5786]
+       * elf/dl-sysdep.c: Undefine ROUND after use.
+       * sysdeps/generic/ldsodefs.h [HAVE_DL_DISCOVER_OSVERSION]
+       (struct rtld_global_ro): Add _dl_tls_get_addr_soft element.
+       * elf/rtld.c (rtld_global_ro): Initialize _dl_discover_osversion.
+       * sysdeps/unix/sysv/linux/dl-osinfo.h: Move _dl_discover_osversion
+       to ...
+       * sysdeps/unix/sysv/linux/dl-sysdep.c: ...here.
+       * sysdeps/unix/sysv/linux/dl-sysdep.h: Declare _dl_discover_osversion
+       if necessary.
+       * sysdeps/unix/sysv/linux/sysconf.c: Handle _SC_ARG_MAX here.
+
        * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Add
        _dl_tls_get_addr_soft element.
        * elf/rtld.c (rtld_global_ro): Initialize _dl_tls_get_addr_soft.
index 85e331a..dd55905 100644 (file)
@@ -1,5 +1,5 @@
 /* Operating system support for run-time dynamic linker.  Generic Unix version.
-   Copyright (C) 1995-1998, 2000-2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000-2007, 2008 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
@@ -398,6 +398,7 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
                  }
                note = ((const void *) (note + 1)
                        + ROUND (note->vendorlen) + ROUND (note->datalen));
+#undef ROUND
              }
            if (dsocaps != NULL)
              break;
index deed472..76a3f25 100644 (file)
@@ -758,7 +758,6 @@ __tls_get_addr (GET_ADDR_ARGS)
 /* Look up the module's TLS block as for __tls_get_addr,
    but never touch anything.  Return null if it's not allocated yet.  */
 void *
-attribute_hidden
 _dl_tls_get_addr_soft (struct link_map *l)
 {
   if (__builtin_expect (l->l_tls_modid == 0, 0))
index 9497e5d..46bece7 100644 (file)
@@ -162,7 +162,10 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
     ._dl_check_caller = _dl_check_caller,
     ._dl_open = _dl_open,
     ._dl_close = _dl_close,
-    ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft
+    ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
+#ifdef HAVE_DL_DISCOVER_OSVERSION
+    ._dl_discover_osversion = _dl_discover_osversion
+#endif
   };
 /* If we would use strong_alias here the compiler would see a
    non-hidden definition.  This would undo the effect of the previous
index 580e1e3..9d1ebdf 100644 (file)
@@ -656,6 +656,9 @@ struct rtld_global_ro
                     Lmid_t nsid, int argc, char *argv[], char *env[]);
   void (*_dl_close) (void *map);
   void *(*_dl_tls_get_addr_soft) (struct link_map *);
+#ifdef HAVE_DL_DISCOVER_OSVERSION
+  int (*_dl_discover_osversion) (void);
+#endif
 
   /* List of auditing interfaces.  */
   struct audit_ifaces *_dl_audit;
index 082790f..b13b6cf 100644 (file)
@@ -1,6 +1,5 @@
 /* Operating system specific code for generic dynamic loader functions.  Linux.
-   Copyright (C) 2000,2001,2002,2004,2005,2006,2007
-       Free Software Foundation, Inc.
+   Copyright (C) 2000-2002,2004-2007,2008 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,9 +17,6 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <string.h>
-#include <fcntl.h>
-#include <sys/utsname.h>
 #include <kernel-features.h>
 #include <dl-sysdep.h>
 #include <stdint.h>
@@ -41,97 +37,6 @@ 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(Nhdr) hdr;
-       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 ElfW(Nhdr) *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 note->n_type - 1) & -sizeof note->n_type)
-               note = ((const void *) (note + 1)
-                       + ROUND (note->n_namesz) + ROUND (note->n_descsz));
-#undef ROUND
-             }
-         }
-    }
-#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++ != '.' || parts == 3)
-       /* Another part following?  */
-       break;
-    }
-
-  if (parts < 3)
-    version <<= 8 * (3 - parts);
-
-  return version;
-}
-
 #define DL_SYSDEP_OSCHECK(FATAL)                                             \
   do {                                                                       \
     /* Test whether the kernel is new enough.  This test is only performed    \
index 42aec77..d4be205 100644 (file)
@@ -1,5 +1,5 @@
 /* Dynamic linker system dependencies for Linux.
-   Copyright (C) 1995,1997,2001,2004,2005,2006 Free Software Foundation, Inc.
+   Copyright (C) 1995,1997,2001,2004,2005,2006, 2008 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
 /* Linux needs some special initialization, but otherwise uses
    the generic dynamic linker system interface code.  */
 
+#include <string.h>
+#include <fcntl.h>
 #include <unistd.h>
+#include <sys/utsname.h>
 #include <ldsodefs.h>
 #include <kernel-features.h>
 
@@ -54,3 +57,96 @@ frob_brk (void)
 }
 
 #include <elf/dl-sysdep.c>
+
+
+int
+attribute_hidden
+_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(Nhdr) hdr;
+       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 ElfW(Nhdr) *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 note->n_type - 1) & -sizeof note->n_type)
+               note = ((const void *) (note + 1)
+                       + ROUND (note->n_namesz) + ROUND (note->n_descsz));
+#undef ROUND
+             }
+         }
+    }
+#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++ != '.' || parts == 3)
+       /* Another part following?  */
+       break;
+    }
+
+  if (parts < 3)
+    version <<= 8 * (3 - parts);
+
+  return version;
+}
index becfc8d..0371fe8 100644 (file)
@@ -1,5 +1,5 @@
 /* System-specific settings for dynamic linker code.  Linux version.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2008 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
    we aren't making direct use of it.  So enable this across the board.  */
 
 #define NEED_DL_SYSINFO_DSO    1
+
+
+/* The _dl_discover_osversion function is so far only needed in sysconf
+   to check for kernels later than 2.6.23.  */
+#if !defined ASSEMBLER && __LINUX_KERNEL_VERSION < 0x020617
+/* Get version of the OS.  */
+extern int _dl_discover_osversion (void) attribute_hidden;
+# define HAVE_DL_DISCOVER_OSVERSION    1
+#endif
index f9f6f1b..ab9cddc 100644 (file)
@@ -1,5 +1,5 @@
 /* Get file-specific information about a file.  Linux version.
-   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006, 2008 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
@@ -23,7 +23,9 @@
 #include <sysdep.h>
 #include <time.h>
 #include <unistd.h>
+#include <sys/resource.h>
 #include <not-cancel.h>
+#include <ldsodefs.h>
 
 static long int posix_sysconf (int name);
 
@@ -70,6 +72,22 @@ __sysconf (int name)
       }
 #endif
 
+    case _SC_ARG_MAX:
+#if __LINUX_KERNEL_VERSION < 0x020617
+      /* Determine whether this is a kernel 2.6.23 or later.  Only
+        then do we have an argument limit determined by the stack
+        size.  */
+      if (GLRO(dl_discover_osversion) () >= 0x020617)
+#endif
+       {
+         /* Use getrlimit to get the stack limit.  */
+         struct rlimit rlimit;
+         if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
+           return MAX (ARG_MAX, rlimit.rlim_cur / 4);
+       }
+
+      return ARG_MAX;
+
     case _SC_NGROUPS_MAX:
       /* Try to read the information from the /proc/sys/kernel/ngroups_max
         file.  */