summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-03-08 07:35:10 +0000
committerUlrich Drepper <drepper@redhat.com>2008-03-08 07:35:10 +0000
commit7c22c7ec9a8170f3d1006ddf21d74cd9d2316332 (patch)
treefba9543f411d48001c40e81cd32b0ed44c0d5928 /sysdeps
parent93025f9373f4efde62aab31aa03c4744fd3bed62 (diff)
[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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/ldsodefs.h3
-rw-r--r--sysdeps/unix/sysv/linux/dl-osinfo.h97
-rw-r--r--sysdeps/unix/sysv/linux/dl-sysdep.c98
-rw-r--r--sysdeps/unix/sysv/linux/dl-sysdep.h11
-rw-r--r--sysdeps/unix/sysv/linux/sysconf.c20
5 files changed, 130 insertions, 99 deletions
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 580e1e3953..9d1ebdf615 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -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;
diff --git a/sysdeps/unix/sysv/linux/dl-osinfo.h b/sysdeps/unix/sysv/linux/dl-osinfo.h
index 082790f63b..b13b6cf1db 100644
--- a/sysdeps/unix/sysv/linux/dl-osinfo.h
+++ b/sysdeps/unix/sysv/linux/dl-osinfo.h
@@ -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 \
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index 42aec77e82..d4be205cde 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -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
@@ -20,7 +20,10 @@
/* 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;
+}
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.h b/sysdeps/unix/sysv/linux/dl-sysdep.h
index becfc8df3f..0371fe87a1 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.h
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.h
@@ -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
@@ -25,3 +25,12 @@
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
diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
index f9f6f1bfa5..ab9cddc306 100644
--- a/sysdeps/unix/sysv/linux/sysconf.c
+++ b/sysdeps/unix/sysv/linux/sysconf.c
@@ -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. */