From 0a54e4010fe0085cd36deaff9442a7e88de3270d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 26 Jul 1997 02:33:30 +0000 Subject: Update. 1997-07-26 04:14 Ulrich Drepper * elf/Makefile (distribute): Add genrtldtbl.awk. (before-compile): Add rtldtbl.h. (GAWK): New variable. (generated): Add trusted-dirs.h and rtldtbl.h. ($(objpfx)rtldtbl.h): New rule. File is needed by dl-load.c. * elf/dl-load.c: Rewrite. Now use cache and look for shared objects in machine dependent directories. * elf/dl-object.c (_dl_new_object): Initialize l_rpath_dirs member. * elf/dl-support.c: Rename function to non_dynamic_init and add initialization for _dl_platform, _dl_platformlen, _dl_pagesize and call to initializer for search path. * elf/elf.h: Add AT_PLATFORM and AT_HWCAP. * elf/genrtldtbl.awk: New file. * elf/link.h: Add type definitions and declarations for search path cache. * elf/rtld.c: Add definitions of variables used for search path cache. * sysdeps/generic/dl-sysdep.c: Let auxiliary vector initialize _dl_platform. Initialize _dl_pagesize early and use this value. * sysdeps/i386/dl-machine.h: Add code for _dl_platform handling. * sysdeps/mach/hurd/dl-sysdep.c: Initialize _dl_pagesize. * sysdeps/unix/sysv/linux/dl-sysdep.c: Use _dl_pagesize instead of calling getpagesize. * elf/dl-error.c (_dl_signal_error): Make message nicer. * nss/libnss_files.map: Fix typo. Reported by Thorsten Kukuk . * sysdeps/generic/strsep.c: Optimize case where separator set contains only one character. * sysdeps/libm-ieee754/s_ccosh.c: Correct sign of result for real == +-Inf. * sysdeps/libm-ieee754/s_ccoshf.c: Likewise. * sysdeps/libm-ieee754/s_ccoshl.c: Likewise. 1997-07-25 09:15 H.J. Lu * sysdeps/sparc/udiv_qrnnd.S: Check PIC instead of __PIC__. * sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S: Likewise. * sysdeps/unix/mips/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/mips/clone.S: Likewise. * sysdeps/mips/bsd-_setjmp.S: Remove __PIC__ comment. * sysdeps/mips/bsd-setjmp.S: Likewise. * sysdeps/mips/dl-machine.h: Remove extra stuff. * sysdeps/mips/mips64/dl-machine.h: Likewise. 1997-07-25 18:55 Philip Blundell * sysdeps/standalone/arm/sysdep.c: New file. 1997-07-25 13:25 Philip Blundell * aout/Makefile: New file. * Makeconfig (binfmt-subdir): Assume a.out when not ELF. * sysdeps/generic/machine-gmon.h: Add warning about limitations of __builtin_return_address(). * sysdeps/arm/machine-gmon.h: New file, use assembly to avoid above problem. 1997-07-25 16:24 H.J. Lu * elf/dl-deps.c (_dl_map_object_deps): Fix a typo. 1997-07-22 Andreas Schwab * math/libm-test.c (ccos_test, ccosh_test): Fix sign in some tests. 1997-07-24 Andreas Schwab * sunrpc/clnt_udp.c (clntudp_call): Rename cu_wait from timeout to not shadow the variable in the outer scope. --- ChangeLog | 79 ++++ Makeconfig | 3 +- db/hash/hash.c | 2 + elf/Makefile | 13 +- elf/dl-deps.c | 9 +- elf/dl-error.c | 2 +- elf/dl-load.c | 465 +++++++++++++++++++----- elf/dl-object.c | 1 + elf/dl-support.c | 31 +- elf/elf.h | 5 + elf/genrtldtbl.awk | 28 ++ elf/link.h | 26 ++ elf/rtld.c | 7 + math/libm-test.c | 24 +- nss/libnss_files.map | 2 +- sunrpc/clnt_udp.c | 4 +- sysdeps/arm/machine-gmon.h | 55 +++ sysdeps/generic/dl-sysdep.c | 37 +- sysdeps/generic/machine-gmon.h | 4 + sysdeps/generic/strsep.c | 23 +- sysdeps/i386/dl-machine.h | 21 +- sysdeps/libm-ieee754/s_ccosh.c | 7 +- sysdeps/libm-ieee754/s_ccoshf.c | 7 +- sysdeps/libm-ieee754/s_ccoshl.c | 7 +- sysdeps/mach/hurd/dl-sysdep.c | 5 +- sysdeps/mips/bsd-_setjmp.S | 1 - sysdeps/mips/bsd-setjmp.S | 1 - sysdeps/mips/dl-machine.h | 10 - sysdeps/mips/mips64/dl-machine.h | 10 - sysdeps/sparc/udiv_qrnnd.S | 4 +- sysdeps/standalone/arm/bits/errno.h | 51 +-- sysdeps/standalone/arm/sysdep.c | 32 ++ sysdeps/unix/mips/sysdep.S | 2 +- sysdeps/unix/sysv/linux/dl-sysdep.c | 16 +- sysdeps/unix/sysv/linux/mips/clone.S | 2 +- sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S | 4 +- 36 files changed, 790 insertions(+), 210 deletions(-) create mode 100644 elf/genrtldtbl.awk create mode 100644 sysdeps/arm/machine-gmon.h create mode 100644 sysdeps/standalone/arm/sysdep.c diff --git a/ChangeLog b/ChangeLog index 9f3ed378a5..842ed6f0dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,82 @@ +1997-07-26 04:14 Ulrich Drepper + + * elf/Makefile (distribute): Add genrtldtbl.awk. + (before-compile): Add rtldtbl.h. + (GAWK): New variable. + (generated): Add trusted-dirs.h and rtldtbl.h. + ($(objpfx)rtldtbl.h): New rule. File is needed by dl-load.c. + * elf/dl-load.c: Rewrite. Now use cache and look for shared + objects in machine dependent directories. + * elf/dl-object.c (_dl_new_object): Initialize l_rpath_dirs member. + * elf/dl-support.c: Rename function to non_dynamic_init and add + initialization for _dl_platform, _dl_platformlen, _dl_pagesize + and call to initializer for search path. + * elf/elf.h: Add AT_PLATFORM and AT_HWCAP. + * elf/genrtldtbl.awk: New file. + * elf/link.h: Add type definitions and declarations for search + path cache. + * elf/rtld.c: Add definitions of variables used for search path cache. + * sysdeps/generic/dl-sysdep.c: Let auxiliary vector initialize + _dl_platform. Initialize _dl_pagesize early and use this value. + * sysdeps/i386/dl-machine.h: Add code for _dl_platform handling. + * sysdeps/mach/hurd/dl-sysdep.c: Initialize _dl_pagesize. + * sysdeps/unix/sysv/linux/dl-sysdep.c: Use _dl_pagesize instead + of calling getpagesize. + + * elf/dl-error.c (_dl_signal_error): Make message nicer. + + * nss/libnss_files.map: Fix typo. + Reported by Thorsten Kukuk . + + * sysdeps/generic/strsep.c: Optimize case where separator set contains + only one character. + + * sysdeps/libm-ieee754/s_ccosh.c: Correct sign of result for real + == +-Inf. + * sysdeps/libm-ieee754/s_ccoshf.c: Likewise. + * sysdeps/libm-ieee754/s_ccoshl.c: Likewise. + +1997-07-25 09:15 H.J. Lu + + * sysdeps/sparc/udiv_qrnnd.S: Check PIC instead of __PIC__. + * sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S: Likewise. + * sysdeps/unix/mips/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/mips/clone.S: Likewise. + + * sysdeps/mips/bsd-_setjmp.S: Remove __PIC__ comment. + * sysdeps/mips/bsd-setjmp.S: Likewise. + + * sysdeps/mips/dl-machine.h: Remove extra stuff. + * sysdeps/mips/mips64/dl-machine.h: Likewise. + +1997-07-25 18:55 Philip Blundell + + * sysdeps/standalone/arm/sysdep.c: New file. + +1997-07-25 13:25 Philip Blundell + + * aout/Makefile: New file. + * Makeconfig (binfmt-subdir): Assume a.out when not ELF. + + * sysdeps/generic/machine-gmon.h: Add warning about limitations of + __builtin_return_address(). + * sysdeps/arm/machine-gmon.h: New file, use assembly to avoid + above problem. + +1997-07-25 16:24 H.J. Lu + + * elf/dl-deps.c (_dl_map_object_deps): Fix a typo. + +1997-07-22 Andreas Schwab + + * math/libm-test.c (ccos_test, ccosh_test): Fix sign in some + tests. + +1997-07-24 Andreas Schwab + + * sunrpc/clnt_udp.c (clntudp_call): Rename cu_wait from timeout to + not shadow the variable in the outer scope. + 1997-07-24 03:14 Ulrich Drepper * elf/dl-deps.c: Complete rewrite to handle DT_AUXILIARY correctly. diff --git a/Makeconfig b/Makeconfig index 0756d91905..4d6e2e6c54 100644 --- a/Makeconfig +++ b/Makeconfig @@ -88,7 +88,8 @@ include $(common-objpfx)config.make ifeq ($(elf),yes) binfmt-subdir = elf else -binfmt-subdir = +# This is probably better than nothing. +binfmt-subdir = aout endif # Complete path to sysdep dirs. diff --git a/db/hash/hash.c b/db/hash/hash.c index 08f2a7e3c8..0267da8c60 100644 --- a/db/hash/hash.c +++ b/db/hash/hash.c @@ -302,7 +302,9 @@ init_hash(hashp, file, info) if (file != NULL) { if (stat(file, &statbuf)) return (NULL); +#if defined _STATBUF_ST_BLKSIZE hashp->BSIZE = statbuf.st_blksize; +#endif hashp->BSHIFT = __hash_log2(hashp->BSIZE); } diff --git a/elf/Makefile b/elf/Makefile index 269a872969..e44711471b 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -35,15 +35,18 @@ elide-routines.so = $(dl-routines) dl-support enbl-secure # interpreter and operating independent of libc. rtld-routines := rtld $(dl-routines) dl-sysdep dl-minimal distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ - dl-hash.h soinit.c sofini.c ldd.sh.in ldd.bash.in eval.c + dl-hash.h soinit.c sofini.c ldd.sh.in ldd.bash.in eval.c \ + genrtldtbl.awk extra-libs = libdl extra-libs-others = $(extra-libs) libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr libdl-map := libdl.map -before-compile = $(objpfx)trusted-dirs.h +before-compile = $(objpfx)trusted-dirs.h $(objpfx)rtldtbl.h +# We need GNU awk for the genrtldtbl.awk script. +GAWK = gawk all: # Make this the default target; it will be defined in Rules. @@ -51,7 +54,7 @@ include ../Makeconfig ifeq (yes,$(build-shared)) extra-objs = $(rtld-routines:=.so) soinit.so sofini.so eval.so -generated = librtld.so dl-allobjs.so +generated = librtld.so dl-allobjs.so trusted-dirs.h rtldtbl.h install-others = $(inst_slibdir)/$(rtld-installed-name) install-bin = ldd endif @@ -143,6 +146,10 @@ $(objpfx)trusted-dirs.h: Makefile echo " \"$$dir\","; \ done;) > $@T mv -f $@T $@ +$(objpfx)rtldtbl.h: Makefile + $(make-target-directory) + echo "$(default-rpath)" | $(GAWK) -f genrtldtbl.awk > $@T + mv -f $@T $@ CPPFLAGS-dl-load.c = -I$(objdir)/$(subdir) CFLAGS-dl-load.c += -Wno-uninitialized diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 36f5ee0606..e990d6965b 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -57,12 +57,9 @@ openaux (void *a) -/* We use a very special kind of list to track the three kinds paths +/* We use a very special kind of list to track the two kinds paths through the list of loaded shared objects. We have to - - go through all objects in the correct order, which includes the - possible recursive loading of auxiliary objects and dependencies - - produce a flat list with unique members of all involved objects - produce a flat list of all shared objects. @@ -141,7 +138,7 @@ _dl_map_object_deps (struct link_map *map, { struct link_map *l = runp->map; - if (runp->done == 0 && (l->l_info[AUXTAG] || l->l_info[DT_NEEDED])) + if (l->l_info[AUXTAG] || l->l_info[DT_NEEDED]) { const char *strtab = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); @@ -371,6 +368,6 @@ _dl_map_object_deps (struct link_map *map, "cannot allocate symbol search list"); for (nlist = 0, runp = head; runp; runp = runp->dup) - map->l_searchlist[nlist++] = runp->map; + map->l_dupsearchlist[nlist++] = runp->map; } } diff --git a/elf/dl-error.c b/elf/dl-error.c index e2565bb348..7ee803ad9b 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -75,7 +75,7 @@ _dl_signal_error (int errcode, /* Lossage while resolving the program's own symbols is always fatal. */ extern char **_dl_argv; /* Set in rtld.c at startup. */ _dl_sysdep_fatal (_dl_argv[0] ?: "", - ": error in loading shared libraries\n", + ": error in loading shared libraries", objname ?: "", objname ? ": " : "", errstring, errcode ? ": " : "", errcode ? strerror (errcode) : "", "\n", NULL); diff --git a/elf/dl-load.c b/elf/dl-load.c index 87859219f1..1301e73996 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1,4 +1,4 @@ -/* _dl_map_object -- Map in a shared object's segments from the file. +/* Map in a shared object's segments from the file. Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,14 +17,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include #include -#include -#include +#include #include -#include #include -#include -#include +#include +#include +#include #include "dynamic-link.h" @@ -90,6 +91,8 @@ ELF_PREFERRED_ADDRESS_DATA; size_t _dl_pagesize; +extern const char *_dl_platform; +extern size_t _dl_platformlen; /* Local version of `strdup' function. */ static inline char * @@ -105,6 +108,292 @@ local_strdup (const char *s) } +/* Implement cache for search path lookup. */ +#if 0 +/* This is how generated should look like. I'll remove this once I'm + sure everything works correctly. */ +static struct r_search_path_elem rtld_search_dir1 = + { "/lib/", 5, unknown, 0, unknown, NULL }; +static struct r_search_path_elem rtld_search_dir2 = + { "/usr/lib/", 9, unknown, 0, unknown, &r ld_search_dir1 }; + +static struct r_search_path_elem *rtld_search_dirs[] = +{ + &rtld_search_dir1, + &rtld_search_dir2, + NULL +}; + +static struct r_search_path_elem *all_dirs = &rtld_search_dir2; +#else +# include "rtldtbl.h" +#endif + +static size_t max_dirnamelen; + +static inline struct r_search_path_elem ** +fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, + const char **trusted) +{ + char *cp; + size_t nelems = 0; + + while ((cp = __strsep (&rpath, sep)) != NULL) + { + struct r_search_path_elem *dirp; + size_t len = strlen (cp); + /* Remove trailing slashes. */ + while (len > 1 && cp[len - 1] == '/') + --len; + + /* Make sure we don't use untrusted directories if we run SUID. */ + if (trusted != NULL) + { + const char **trun = trusted; + + /* All trusted directory must be complete name. */ + if (cp[0] != '/') + continue; + + while (*trun != NULL + && (memcmp (*trun, cp, len) != 0 || (*trun)[len] != '\0')) + ++trun; + + if (*trun == NULL) + /* It's no trusted directory, skip it. */ + continue; + } + + /* Now add one. */ + if (len > 0) + cp[len++] = '/'; + + /* See if this directory is already known. */ + for (dirp = all_dirs; dirp != NULL; dirp = dirp->next) + if (dirp->dirnamelen == len && strcmp (cp, dirp->dirname) == 0) + break; + + if (dirp != NULL) + { + /* It is available, see whether it's in our own list. */ + size_t cnt; + for (cnt = 0; cnt < nelems; ++cnt) + if (result[cnt] == dirp) + break; + + if (cnt == nelems) + result[nelems++] = dirp; + } + else + { + /* It's a new directory. Create an entry and add it. */ + dirp = (struct r_search_path_elem *) malloc (sizeof (*dirp)); + if (dirp == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + + dirp->dirnamelen = len; + dirp->dirstatus = unknown; + + /* Add the name of the machine dependent directory if a machine + is defined. */ + if (_dl_platform != NULL) + { + char *tmp; + + dirp->machdirnamelen = len + _dl_platformlen + 1; + tmp = (char *) malloc (len + _dl_platformlen + 2); + if (tmp == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + memcpy (tmp, cp, len); + memcpy (tmp + len, _dl_platform, _dl_platformlen); + tmp[len + _dl_platformlen] = '/'; + tmp[len + _dl_platformlen + 1] = '\0'; + + dirp->dirname = tmp; + dirp->machdirstatus = unknown; + + if (max_dirnamelen < dirp->machdirnamelen) + max_dirnamelen = dirp->machdirnamelen; + } + else + { + char *tmp; + + dirp->machdirnamelen = len; + dirp->machdirstatus = nonexisting; + + tmp = (char *) malloc (len + 1); + if (tmp == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + memcpy (tmp, cp, len); + tmp[len] = '\0'; + + if (max_dirnamelen < dirp->dirnamelen) + max_dirnamelen = dirp->dirnamelen; + + dirp->dirname = tmp; + } + + dirp->next = all_dirs; + all_dirs = dirp; + + /* Put it in the result array. */ + result[nelems++] = dirp; + } + } + + /* Terminate the array. */ + result[nelems] = NULL; + + return result; +} + + +static struct r_search_path_elem ** +decompose_rpath (const char *rpath, size_t additional_room) +{ + /* Make a copy we can work with. */ + char *copy = strdupa (rpath); + char *cp; + struct r_search_path_elem **result; + /* First count the number of necessary elements in the result array. */ + size_t nelems = 0; + + for (cp = copy; *cp != '\0'; ++cp) + if (*cp == ':') + ++nelems; + + /* Allocate room for the result. NELEMS + 1 + ADDITIONAL_ROOM is an upper + limit for the number of necessary entries. */ + result = (struct r_search_path_elem **) malloc ((nelems + 1 + + additional_room + 1) + * sizeof (*result)); + if (result == NULL) + _dl_signal_error (ENOMEM, NULL, "cannot create cache for search path"); + + return fillin_rpath (copy, result, ":", NULL); +} + + +void +_dl_init_paths (void) +{ + struct r_search_path_elem **pelem; + + /* We have in `search_path' the information about the RPATH of the + dynamic loader. Now fill in the information about the applications + RPATH and the directories addressed by the LD_LIBRARY_PATH environment + variable. */ + struct link_map *l; + + /* First determine how many elements the LD_LIBRARY_PATH contents has. */ + const char *llp = getenv ("LD_LIBRARY_PATH"); + size_t nllp; + + if (llp != NULL && *llp != '\0') + { + /* Simply count the number of colons. */ + const char *cp = llp; + nllp = 1; + while (*cp) + if (*cp++ == ':') + ++nllp; + } + else + nllp = 0; + + l = _dl_loaded; + if (l && l->l_type != lt_loaded && l->l_info[DT_RPATH]) + { + /* Allocate room for the search path and fill in information from + RPATH. */ + l->l_rpath_dirs = + decompose_rpath ((const char *) (l->l_addr + + l->l_info[DT_STRTAB]->d_un.d_ptr + + l->l_info[DT_RPATH]->d_un.d_val), + nllp); + } + else + { + /* If we have no LD_LIBRARY_PATH and no RPATH we must tell this + somehow to prevent we look this up again and again. */ + if (nllp == 0) + l->l_rpath_dirs = (struct r_search_path_elem **) -1l; + else + { + l->l_rpath_dirs = + (struct r_search_path_elem **) malloc ((nllp + 1) + * sizeof (*l->l_rpath_dirs)); + if (l->l_rpath_dirs == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + l->l_rpath_dirs[0] = NULL; + } + } + + if (nllp > 0) + { + static const char *trusted_dirs[] = + { +#include "trusted-dirs.h" + NULL + }; + char *copy = strdupa (llp); + + /* Decompose the LD_LIBRARY_PATH and fill in the result. + First search for the next place to enter elements. */ + struct r_search_path_elem **result = l->l_rpath_dirs; + while (*result != NULL) + ++result; + + /* We need to take care that the LD_LIBRARY_PATH environement + variable can contain a semicolon. */ + (void) fillin_rpath (copy, result, ":;", + __libc_enable_secure ? trusted_dirs : NULL); + } + + /* Now set up the rest of the rtld_search_dirs. */ + for (pelem = rtld_search_dirs; *pelem != NULL; ++pelem) + { + struct r_search_path_elem *relem = *pelem; + + if (_dl_platform != NULL) + { + char *tmp; + + relem->machdirnamelen = relem->dirnamelen + _dl_platformlen + 1; + tmp = (char *) malloc (relem->machdirnamelen + 1); + if (tmp == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + + memcpy (tmp, relem->dirname, relem->dirnamelen); + memcpy (tmp + relem->dirnamelen, _dl_platform, _dl_platformlen); + tmp[relem->dirnamelen + _dl_platformlen] = '/'; + tmp[relem->dirnamelen + _dl_platformlen + 1] = '\0'; + + relem->dirname = tmp; + + relem->machdirstatus = unknown; + + if (max_dirnamelen < relem->machdirnamelen) + max_dirnamelen = relem->machdirnamelen; + } + else + { + relem->machdirnamelen = relem->dirnamelen; + relem->machdirstatus = nonexisting; + + if (max_dirnamelen < relem->dirnamelen) + max_dirnamelen = relem->dirnamelen; + } + } +} + + /* Map in the shared object NAME, actually located in REALNAME, and already opened on FD. */ @@ -131,7 +420,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, l->l_next->l_prev = l->l_prev; free (l); } - free (name); + free (name); /* XXX Can this be correct? --drepper */ free (realname); _dl_signal_error (code, name, msg); } @@ -207,9 +496,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, return l; } - if (_dl_pagesize == 0) - _dl_pagesize = __getpagesize (); - /* Map in the first page to read the header. */ header = map (0, sizeof *header); @@ -458,83 +744,87 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, return l; } -/* Try to open NAME in one of the directories in DIRPATH. +/* Try to open NAME in one of the directories in DIRS. Return the fd, or -1. If successful, fill in *REALNAME with the malloc'd full directory name. */ static int open_path (const char *name, size_t namelen, - const char *dirpath, - char **realname, - const char *trusted_dirs[]) + struct r_search_path_elem **dirs, + char **realname) { char *buf; - const char *p; - int fd; + int fd = -1; - p = dirpath; - if (p == NULL || *p == '\0') + if (dirs == NULL || *dirs == NULL) { __set_errno (ENOENT); return -1; } - buf = __alloca (strlen (dirpath) + 1 + namelen); + buf = __alloca (max_dirnamelen + namelen); do { - size_t buflen; - size_t this_len; + struct r_search_path_elem *this_dir = *dirs; + size_t buflen = 0; - dirpath = p; - p = strpbrk (dirpath, ":;"); - if (p == NULL) - p = strchr (dirpath, '\0'); - - this_len = p - dirpath; - - /* When we run a setuid program we do not accept any directory. */ - if (__libc_enable_secure) + if (this_dir->machdirstatus != nonexisting) { - /* All trusted directory must be complete name. */ - if (dirpath[0] != '/') - continue; + /* Construct the pathname to try. */ + (void) memcpy (buf, this_dir->dirname, this_dir->machdirnamelen); + (void) memcpy (buf + this_dir->machdirnamelen, name, namelen); + buflen = this_dir->machdirnamelen + namelen; + + fd = __open (buf, O_RDONLY); + if (this_dir->machdirstatus == unknown) + if (fd != -1) + this_dir->machdirstatus = existing; + else + { + /* We failed to open machine dependent library. Let's + test whether there is any directory at all. */ + struct stat st; - /* If we got a list of trusted directories only accept one - of these. */ - if (trusted_dirs != NULL) - { - const char **trust = trusted_dirs; + buf[this_dir->machdirnamelen - 1] = '\0'; - while (*trust != NULL) - if (memcmp (dirpath, *trust, this_len) == 0 - && (*trust)[this_len] == '\0') - break; + if (stat (buf, &st) != 0 || ! S_ISDIR (st.st_mode)) + /* The directory does not exist ot it is no directory. */ + this_dir->machdirstatus = nonexisting; else - ++trust; - - /* If directory is not trusted, ignore this directory. */ - if (*trust == NULL) - continue; - } + this_dir->machdirstatus = existing; + } } - if (this_len == 0) - { - /* 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 + if (fd == -1 && this_dir->dirstatus != nonexisting) { /* Construct the pathname to try. */ - (void) memcpy (buf, dirpath, this_len); - buf[this_len] = '/'; - (void) memcpy (&buf[this_len + 1], name, namelen); - buflen = this_len + 1 + namelen; + (void) memcpy (buf, this_dir->dirname, this_dir->dirnamelen); + (void) memcpy (buf + this_dir->dirnamelen, name, namelen); + buflen = this_dir->dirnamelen + namelen; + + fd = __open (buf, O_RDONLY); + if (this_dir->dirstatus == unknown) + if (fd != -1) + this_dir->dirstatus = existing; + else + /* We failed to open library. Let's test whether there + is any directory at all. */ + if (this_dir->dirnamelen <= 1) + this_dir->dirstatus = existing; + else + { + struct stat st; + + buf[this_dir->dirnamelen - 1] = '\0'; + + if (stat (buf, &st) != 0 || ! S_ISDIR (st.st_mode)) + /* The directory does not exist ot it is no directory. */ + this_dir->dirstatus = nonexisting; + else + this_dir->dirstatus = existing; + } } - fd = __open (buf, O_RDONLY); if (fd != -1) { *realname = malloc (buflen); @@ -555,7 +845,7 @@ open_path (const char *name, size_t namelen, /* The file exists and is readable, but something went wrong. */ return -1; } - while (*p++ != '\0'); + while (*++dirs != NULL); return -1; } @@ -593,39 +883,34 @@ _dl_map_object (struct link_map *loader, const char *name, int type, size_t namelen = strlen (name) + 1; - inline void trypath (const char *dirpath, const char *trusted[]) - { - fd = open_path (name, namelen, dirpath, &realname, trusted); - } - fd = -1; /* First try the DT_RPATH of the dependent object that caused NAME to be loaded. Then that object's dependent, and on up. */ for (l = loader; fd == -1 && l; l = l->l_loader) if (l && l->l_info[DT_RPATH]) - trypath ((const char *) (l->l_addr + - l->l_info[DT_STRTAB]->d_un.d_ptr + - l->l_info[DT_RPATH]->d_un.d_val), NULL); - /* If dynamically linked, try the DT_RPATH of the executable itself. */ - l = _dl_loaded; - if (fd == -1 && l && l->l_type != lt_loaded && l->l_info[DT_RPATH]) - trypath ((const char *) (l->l_addr + - l->l_info[DT_STRTAB]->d_un.d_ptr + - l->l_info[DT_RPATH]->d_un.d_val), NULL); - /* Try an environment variable (unless setuid). */ - if (fd == -1) - { - static const char *trusted_dirs[] = { -#include "trusted-dirs.h" - NULL - }; - const char *ld_library_path = getenv ("LD_LIBRARY_PATH"); + /* Make sure the cache information is available. */ + if (l->l_rpath_dirs == NULL) + { + size_t ptrval = (l->l_addr + + l->l_info[DT_STRTAB]->d_un.d_ptr + + l->l_info[DT_RPATH]->d_un.d_val); + l->l_rpath_dirs = + decompose_rpath ((const char *) ptrval, 0); + } + + if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l) + fd = open_path (name, namelen, l->l_rpath_dirs, &realname); + } + + /* If dynamically linked, try the DT_RPATH of the executable itself + and the LD_LIBRARY_PATH environment variable. */ + l = _dl_loaded; + if (fd == -1 && l && l->l_type != lt_loaded + && l->l_rpath_dirs != (struct r_search_path_elem **) -1l) + fd = open_path (name, namelen, l->l_rpath_dirs, &realname); - if (ld_library_path != NULL && *ld_library_path != '\0') - trypath (ld_library_path, trusted_dirs); - } if (fd == -1) { /* Check the list of libraries in the file /etc/ld.so.cache, @@ -646,12 +931,10 @@ _dl_map_object (struct link_map *loader, const char *name, int type, } } } + /* Finally, try the default path. */ if (fd == -1) - { - extern const char *_dl_rpath; /* Set in rtld.c. */ - trypath (_dl_rpath, NULL); - } + fd = open_path (name, namelen, rtld_search_dirs, &realname); } else { diff --git a/elf/dl-object.c b/elf/dl-object.c index 941bfa34cc..65f80d1a7e 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -44,6 +44,7 @@ _dl_new_object (char *realname, const char *libname, int type) newname->next = NULL; new->l_libname = newname; new->l_type = type; + new->l_rpath_dirs = NULL; if (_dl_loaded == NULL) { diff --git a/elf/dl-support.c b/elf/dl-support.c index 21cd13e5cf..3333bf10fb 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -20,8 +20,10 @@ /* This file defines some things that for the dynamic linker are defined in rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ +#include #include - +#include +#include extern char *__progname; char **_dl_argv = &__progname; /* This is checked for some error messages. */ @@ -30,15 +32,36 @@ char **_dl_argv = &__progname; /* This is checked for some error messages. */ For the dynamic linker it is set by -rpath when linking. */ const char *_dl_rpath = DEFAULT_RPATH; +/* Name of the architecture. */ +const char *_dl_platform; +size_t _dl_platformlen; + /* If nonzero print warnings about problematic situations. */ int _dl_verbose; +/* Structure to store information about search paths. */ +struct r_search_path *_dl_search_paths; -static void init_verbose (void) __attribute__ ((unused)); + +static void non_dynamic_init (void) __attribute__ ((unused)); static void -init_verbose (void) +non_dynamic_init (void) { _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1; + + /* Initialize the data structures for the search paths for shared + objects. */ + _dl_init_paths (); + +#ifdef DL_PLATFORM_INIT + DL_PLATFORM_INIT; +#endif + + /* Now determine the length of the platform string. */ + if (_dl_platform != NULL) + _dl_platformlen = strlen (_dl_platform); + + _dl_pagesize = __getpagesize (); } -text_set_element (__libc_subinit, init_verbose); +text_set_element (__libc_subinit, non_dynamic_init); diff --git a/elf/elf.h b/elf/elf.h index d01bc90c90..02d092ffac 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -654,6 +654,11 @@ typedef struct #define AT_GID 13 /* Real gid */ #define AT_EGID 14 /* Effective gid */ +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + /* Motorola 68k specific definitions. */ /* m68k relocs. */ diff --git a/elf/genrtldtbl.awk b/elf/genrtldtbl.awk new file mode 100644 index 0000000000..50f81c8c34 --- /dev/null +++ b/elf/genrtldtbl.awk @@ -0,0 +1,28 @@ +#! /usr/bin/awk +BEGIN { + FS=":"; + count=0; +} +{ + for (i = 1; i <= NF; ++i) { + dir[count++] = gensub(/((.*)[^/])?[/]*/, "\\1", "", $i); + } +} +END { + for (i = 0; i < count; ++i) { + printf ("static struct r_search_path_elem rtld_search_dir%d =\n", i+1); + printf (" { \"%s/\", %d, unknown, 0, unknown, ", + dir[i], length (dir[i]) + 1); + if (i== 0) + printf ("NULL };\n"); + else + printf ("&rtld_search_dir%d };\n", i); + } + printf ("\nstatic struct r_search_path_elem *rtld_search_dirs[] =\n{\n"); + for (i = 0; i < count; ++i) { + printf (" &rtld_search_dir%d,\n", i + 1); + } + printf (" NULL\n};\n\n"); + printf ("static struct r_search_path_elem *all_dirs = &rtld_search_dir%d;\n", + count); +} diff --git a/elf/link.h b/elf/link.h index f457174df5..e0fccd0fca 100644 --- a/elf/link.h +++ b/elf/link.h @@ -91,6 +91,25 @@ struct r_found_version const char *filename; }; +/* We want to cache information about the searches for shared objects. */ + +enum r_dir_status { unknown, nonexisting, existing }; + +struct r_search_path_elem + { + const char *dirname; + + size_t dirnamelen; + enum r_dir_status dirstatus; + + size_t machdirnamelen; + enum r_dir_status machdirstatus; + + /* This link is only used in the `all_dirs' member of `r_search_path'. */ + struct r_search_path_elem *next; + }; + + /* Structure describing a loaded shared object. The `l_next' and `l_prev' members form a chain of all the shared objects loaded at startup. @@ -163,6 +182,9 @@ struct link_map /* Array with version names. */ unsigned int l_nversions; struct r_found_version *l_versions; + + /* Collected information about own RPATH directories. */ + struct r_search_path_elem **l_rpath_dirs; }; @@ -407,6 +429,10 @@ extern void _dl_debug_state (void); in the `r_ldbase' member. Returns the address of the structure. */ extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase); +/* Initialize the basic data structure for the search paths. */ +void _dl_init_paths (void); + + __END_DECLS #endif /* link.h */ diff --git a/elf/rtld.c b/elf/rtld.c index a025757e05..7189ca6b2b 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -58,6 +58,9 @@ int _dl_argc; char **_dl_argv; const char *_dl_rpath; int _dl_verbose; +const char *_dl_platform; +size_t _dl_platformlen; +struct r_search_path *_dl_search_paths; /* Set nonzero during loading and initialization of executable and libraries, cleared before the executable's entry point runs. This @@ -526,6 +529,10 @@ of this helper program; chances are you did not intend to run this program.\n", assert (i == npreloads); } + /* Initialize the data structures for the search paths for shared + objects. */ + _dl_init_paths (); + /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD specified some libraries to load, these are inserted before the actual dependencies in the executable's searchlist for symbol resolution. */ diff --git a/math/libm-test.c b/math/libm-test.c index 72c09a7b8e..2ea0bf83cf 100644 --- a/math/libm-test.c +++ b/math/libm-test.c @@ -2907,10 +2907,10 @@ ccos_test (void) result = FUNC(ccos) (BUILD_COMPLEX (0.0, 0.0)); check ("real(ccos(0 + 0i)) = 1.0", __real__ result, 1.0); - check ("imag(ccos(0 + 0i)) = 0", __imag__ result, 0); + check ("imag(ccos(0 + 0i)) = -0", __imag__ result, minus_zero); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, 0.0)); check ("real(ccos(-0 + 0i)) = 1.0", __real__ result, 1.0); - check ("imag(ccos(-0 + 0i)) = -0", __imag__ result, minus_zero); + check ("imag(ccos(-0 + 0i)) = 0", __imag__ result, 0.0); result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_zero)); check ("real(ccos(0 - 0i)) = 1.0", __real__ result, 1.0); check ("imag(ccos(0 - 0i)) = 0", __imag__ result, 0.0); @@ -2941,13 +2941,13 @@ ccos_test (void) result = FUNC(ccos) (BUILD_COMPLEX (0.0, plus_infty)); check_isinfp ("real(ccos(0 + i Inf)) = +Inf", __real__ result); - check ("imag(ccos(0 + i Inf)) = 0", __imag__ result, 0); + check ("imag(ccos(0 + i Inf)) = -0", __imag__ result, minus_zero); result = FUNC(ccos) (BUILD_COMPLEX (0.0, minus_infty)); check_isinfp ("real(ccos(0 - i Inf)) = +Inf", __real__ result); check ("imag(ccos(0 - i Inf)) = 0", __imag__ result, 0); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, plus_infty)); check_isinfp ("real(ccos(-0 + i Inf)) = +Inf", __real__ result); - check ("imag(ccos(-0 + i Inf)) = -0", __imag__ result, minus_zero); + check ("imag(ccos(-0 + i Inf)) = 0", __imag__ result, 0.0); result = FUNC(ccos) (BUILD_COMPLEX (minus_zero, minus_infty)); check_isinfp ("real(ccos(-0 - i Inf)) = +Inf", __real__ result); check ("imag(ccos(-0 - i Inf)) = -0", __imag__ result, minus_zero); @@ -2975,13 +2975,13 @@ ccos_test (void) result = FUNC(ccos) (BUILD_COMPLEX (4.625, plus_infty)); check_isinfn ("real(ccos(4.625 + i Inf)) = -Inf", __real__ result); - check_isinfn ("imag(ccos(4.625 + i Inf)) = -Inf", __imag__ result); + check_isinfp ("imag(ccos(4.625 + i Inf)) = +Inf", __imag__ result); result = FUNC(ccos) (BUILD_COMPLEX (4.625, minus_infty)); check_isinfn ("real(ccos(4.625 - i Inf)) = -Inf", __real__ result); check_isinfn ("imag(ccos(4.625 - i Inf)) = -Inf", __imag__ result); result = FUNC(ccos) (BUILD_COMPLEX (-4.625, plus_infty)); check_isinfn ("real(ccos(-4.625 + i Inf)) = -Inf", __real__ result); - check_isinfp ("imag(ccos(-4.625 + i Inf)) = +Inf", __imag__ result); + check_isinfn ("imag(ccos(-4.625 + i Inf)) = -Inf", __imag__ result); result = FUNC(ccos) (BUILD_COMPLEX (-4.625, minus_infty)); check_isinfn ("real(ccos(-4.625 - i Inf)) = -Inf", __real__ result); check_isinfp ("imag(ccos(-4.625 - i Inf)) = +Inf", __imag__ result); @@ -3077,13 +3077,13 @@ ccosh_test (void) check ("imag(ccosh(0 + 0i)) = 0", __imag__ result, 0); result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, 0.0)); check ("real(ccosh(-0 + 0i)) = 1.0", __real__ result, 1.0); - check ("imag(ccosh(-0 + 0i)) = 0", __imag__ result, 0); + check ("imag(ccosh(-0 + 0i)) = -0", __imag__ result, minus_zero); result = FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_zero)); check ("real(ccosh(0 - 0i)) = 1.0", __real__ result, 1.0); check ("imag(ccosh(0 - 0i)) = -0", __imag__ result, minus_zero); result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_zero)); check ("real(ccosh(-0 - 0i)) = 1.0", __real__ result, 1.0); - check ("imag(ccosh(-0 - 0i)) = -0", __imag__ result, minus_zero); + check ("imag(ccosh(-0 - 0i)) = 0", __imag__ result, 0.0); result = FUNC(ccosh) (BUILD_COMPLEX (0.0, plus_infty)); check_isnan_exc ("real(ccosh(0 + i Inf)) = NaN plus invalid exception", @@ -3111,13 +3111,13 @@ ccosh_test (void) check ("imag(ccosh(+Inf + 0i)) = 0", __imag__ result, 0); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 0.0)); check_isinfp ("real(ccosh(-Inf + 0i)) = +Inf", __real__ result); - check ("imag(ccosh(-Inf + 0i)) = 0", __imag__ result, 0); + check ("imag(ccosh(-Inf + 0i)) = -0", __imag__ result, minus_zero); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_zero)); check_isinfp ("real(ccosh(+Inf - 0i)) = +Inf", __real__ result); check ("imag(ccosh(+Inf - 0i)) = -0", __imag__ result, minus_zero); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_zero)); check_isinfp ("real(ccosh(-Inf - 0i)) = +Inf", __real__ result); - check ("imag(ccosh(-Inf - 0i)) = -0", __imag__ result, minus_zero); + check ("imag(ccosh(-Inf - 0i)) = 0", __imag__ result, 0.0); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, plus_infty)); check_isinfp_exc ("real(ccosh(+Inf + i Inf)) = +Inf plus invalid exception", @@ -3145,13 +3145,13 @@ ccosh_test (void) check_isinfn ("imag(ccosh(+Inf + i4.625)) = -Inf", __imag__ result); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 4.625)); check_isinfn ("real(ccosh(-Inf + i4.625)) = -Inf", __real__ result); - check_isinfn ("imag(ccosh(-Inf + i4.625)) = -Inf", __imag__ result); + check_isinfp ("imag(ccosh(-Inf + i4.625)) = Inf", __imag__ result); result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, -4.625)); check_isinfn ("real(ccosh(+Inf - i4.625)) = -Inf", __real__ result); check_isinfp ("imag(ccosh(+Inf - i4.625)) = +Inf", __imag__ result); result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, -4.625)); check_isinfn ("real(ccosh(-Inf - i4.625)) = -Inf", __real__ result); - check_isinfp ("imag(ccosh(-Inf - i4.625)) = +Inf", __imag__ result); + check_isinfn ("imag(ccosh(-Inf - i4.625)) = -Inf", __imag__ result); result = FUNC(ccosh) (BUILD_COMPLEX (6.75, plus_infty)); check_isnan_exc ("real(ccosh(6.75 + i Inf)) = NaN plus invalid exception", diff --git a/nss/libnss_files.map b/nss/libnss_files.map index de023668f0..07e5c9aabb 100644 --- a/nss/libnss_files.map +++ b/nss/libnss_files.map @@ -22,7 +22,7 @@ GLIBC_2.0 { _nss_files_setgrent; _nss_files_sethostent; _nss_files_setnetent; _nss_files_setnetgrent; _nss_files_setprotoent; _nss_files_setpwent; _nss_files_setrpcent; _nss_files_setservent; _nss_files_setspent; - __nss_netgroup_parseline; + _nss_netgroup_parseline; local: *; diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c index a54e1d5665..28aa6ef4fd 100644 --- a/sunrpc/clnt_udp.c +++ b/sunrpc/clnt_udp.c @@ -309,10 +309,10 @@ send_again: #endif /* def FD_SETSIZE */ for (;;) { - struct timeval timeout = cu->cu_wait; + struct timeval cu_wait = cu->cu_wait; readfds = mask; switch (select (_rpc_dtablesize (), &readfds, (fd_set*) NULL, - (fd_set*) NULL, &timeout)) + (fd_set*) NULL, &cu_wait)) { case 0: diff --git a/sysdeps/arm/machine-gmon.h b/sysdeps/arm/machine-gmon.h new file mode 100644 index 0000000000..27643df884 --- /dev/null +++ b/sysdeps/arm/machine-gmon.h @@ -0,0 +1,55 @@ +/* Machine-dependent definitions for profiling support. ARM version. + Copyright (C) 1996, 1997 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* GCC for the ARM cannot compile __builtin_return_address(N) for N != 0, + so we must use an assembly stub. */ + +#include +#ifndef NO_UNDERSCORES +/* The asm symbols for C functions are `_function'. + The canonical name for the counter function is `mcount', no _. */ +void _mcount (void) asm ("mcount"); +#else +/* The canonical name for the function is `_mcount' in both C and asm, + but some old asm code might assume it's `mcount'. */ +void _mcount (void); +weak_alias (_mcount, mcount) +#endif + +static void mcount_internal (u_long frompc, u_long selfpc); + +#define _MCOUNT_DECL(frompc, selfpc) \ +static void mcount_internal (u_long frompc, u_long selfpc) + +#define MCOUNT \ +void _mcount (void) \ +{ \ + register unsigned long int frompc, selfpc; \ + __asm__("movs fp, fp; " \ + "moveq %0, $0; " \ + "ldrne %0, [fp, $-4]; " \ + "ldrne %1, [fp, $-12]; " \ + "movnes %1, %1; " \ + "ldrne %1, [%1, $-4]; " \ + : "=g" (selfpc), "=g" (frompc) \ + : : "cc" \ + ); \ + if (selfpc) \ + mcount_internal(frompc, selfpc); \ +} diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c index e18f0b89a4..4f97f8547b 100644 --- a/sysdeps/generic/dl-sysdep.c +++ b/sysdeps/generic/dl-sysdep.c @@ -26,11 +26,14 @@ #include #include +#include extern int _dl_argc; extern char **_dl_argv; extern char **_environ; extern size_t _dl_pagesize; +extern const char *_dl_platform; +extern size_t _dl_platformlen; extern void _end; extern void ENTRY_POINT (void); @@ -57,6 +60,7 @@ _dl_sysdep_start (void **start_argptr, _dl_argc = *(long *) start_argptr; _dl_argv = (char **) start_argptr + 1; _environ = &_dl_argv[_dl_argc + 1]; + _dl_platform = NULL; /* Default to nothing known about the platform. */ start_argptr = (void **) _environ; while (*start_argptr) ++start_argptr; @@ -93,6 +97,12 @@ _dl_sysdep_start (void **start_argptr, case AT_EGID: egid = av->a_un.a_val; break; + case AT_PLATFORM: + _dl_platform = av->a_un.a_ptr; + break; + case AT_HWCAP: + /* Well, what shall we use? A string or an integer with bits? */ + break; } /* Linux doesn't provide us with any of these values on the stack @@ -107,21 +117,28 @@ _dl_sysdep_start (void **start_argptr, __libc_enable_secure = uid != euid || gid != egid; + if (_dl_pagesize == 0) + _dl_pagesize = __getpagesize (); + #ifdef DL_SYSDEP_INIT DL_SYSDEP_INIT; #endif +#ifdef DL_PLATFORM_INIT + DL_PLATFORM_INIT; +#endif + + /* Determine the length of the platform name. */ + if (_dl_platform != NULL) + _dl_platformlen = strlen (_dl_platform); + if (__sbrk (0) == &_end) - { - /* The dynamic linker was run as a program, and so the initial break - starts just after our bss, at &_end. The malloc in dl-minimal.c - will consume the rest of this page, so tell the kernel to move the - break up that far. When the user program examines its break, it - will see this new value and not clobber our data. */ - size_t pg = __getpagesize (); - - __sbrk (pg - ((&_end - (void *) 0) & (pg - 1))); - } + /* The dynamic linker was run as a program, and so the initial break + starts just after our bss, at &_end. The malloc in dl-minimal.c + will consume the rest of this page, so tell the kernel to move the + break up that far. When the user program examines its break, it + will see this new value and not clobber our data. */ + __sbrk (_dl_pagesize - ((&_end - (void *) 0) & (_dl_pagesize - 1))); (*dl_main) (phdr, phnum, &user_entry); return user_entry; diff --git a/sysdeps/generic/machine-gmon.h b/sysdeps/generic/machine-gmon.h index c4a2168322..3b63707eaf 100644 --- a/sysdeps/generic/machine-gmon.h +++ b/sysdeps/generic/machine-gmon.h @@ -22,6 +22,10 @@ void *__builtin_return_address (unsigned int N) returns the return address of the frame N frames up. */ +/* Be warned that GCC cannot usefully compile __builtin_return_address(N) + for N != 0 on all machines. In this case, you may have to write + your own version of _mcount(). */ + #if __GNUC__ < 2 #error "This file uses __builtin_return_address, a GCC 2 extension." #endif diff --git a/sysdeps/generic/strsep.c b/sysdeps/generic/strsep.c index d17e53a772..b2c7e90c39 100644 --- a/sysdeps/generic/strsep.c +++ b/sysdeps/generic/strsep.c @@ -27,8 +27,27 @@ __strsep (char **stringp, const char *delim) if (! begin || *begin == '\0') return NULL; - /* Find the end of the token. */ - end = strpbrk (begin, delim); + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; + + if (ch == '\0') + end = NULL; + else + { + while (*begin == ch) + ++begin; + + end = strchr (begin, delim[0]); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + if (end) { /* Terminate the token and set *STRINGP past NUL character. */ diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 0388cbe510..d6fc038411 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -44,7 +44,7 @@ elf_machine_matches_host (Elf32_Half e_machine) /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ -static inline Elf32_Addr +static inline Elf32_Addr __attribute__ ((unused)) elf_machine_dynamic (void) { register Elf32_Addr *got asm ("%ebx"); @@ -86,7 +86,7 @@ static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset) /* Set up the loaded object described by L so its unrelocated PLT entries will jump to the on-demand fixup code in dl-runtime.c. */ -static inline int +static inline int __attribute__ ((unused)) elf_machine_runtime_setup (struct link_map *l, int lazy) { Elf32_Addr *got; @@ -233,6 +233,23 @@ _dl_start_user:\n\ /* The i386 never uses Elf32_Rela relocations. */ #define ELF_MACHINE_NO_RELA 1 +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +extern const char *_dl_platform; + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (_dl_platform == NULL) + /* We default to i386 since all instructions understood by the i386 + are also understood by later processors. */ + _dl_platform = "i386"; + else if (*_dl_platform == '\0') + _dl_platform = NULL; +} + #endif /* !dl_machine_h */ #ifdef RESOLVE diff --git a/sysdeps/libm-ieee754/s_ccosh.c b/sysdeps/libm-ieee754/s_ccosh.c index 1e92f03771..394101f23a 100644 --- a/sysdeps/libm-ieee754/s_ccosh.c +++ b/sysdeps/libm-ieee754/s_ccosh.c @@ -32,8 +32,6 @@ __ccosh (__complex__ double x) int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); - __real__ x = fabs (__real__ x); - if (rcls >= FP_ZERO) { /* Real part is finite. */ @@ -67,7 +65,7 @@ __ccosh (__complex__ double x) { /* Imaginary part is 0.0. */ __real__ retval = HUGE_VAL; - __imag__ retval = __imag__ x; + __imag__ retval = __imag__ x * __copysign (1.0, __real__ x); } else if (icls > FP_ZERO) { @@ -77,7 +75,8 @@ __ccosh (__complex__ double x) __sincos (__imag__ x, &sinix, &cosix); __real__ retval = __copysign (HUGE_VAL, cosix); - __imag__ retval = __copysign (HUGE_VAL, sinix); + __imag__ retval = (__copysign (HUGE_VAL, sinix) + * __copysign (1.0, __real__ x)); } else { diff --git a/sysdeps/libm-ieee754/s_ccoshf.c b/sysdeps/libm-ieee754/s_ccoshf.c index 573a63367b..a8043fdd39 100644 --- a/sysdeps/libm-ieee754/s_ccoshf.c +++ b/sysdeps/libm-ieee754/s_ccoshf.c @@ -32,8 +32,6 @@ __ccoshf (__complex__ float x) int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); - __real__ x = fabsf (__real__ x); - if (rcls >= FP_ZERO) { /* Real part is finite. */ @@ -67,7 +65,7 @@ __ccoshf (__complex__ float x) { /* Imaginary part is 0.0. */ __real__ retval = HUGE_VALF; - __imag__ retval = __imag__ x; + __imag__ retval = __imag__ x * __copysignf (1.0, __real__ x); } else if (icls > FP_ZERO) { @@ -77,7 +75,8 @@ __ccoshf (__complex__ float x) __sincosf (__imag__ x, &sinix, &cosix); __real__ retval = __copysignf (HUGE_VALF, cosix); - __imag__ retval = __copysignf (HUGE_VALF, sinix); + __imag__ retval = (__copysignf (HUGE_VALF, sinix) + * __copysignf (1.0, __real__ x)); } else { diff --git a/sysdeps/libm-ieee754/s_ccoshl.c b/sysdeps/libm-ieee754/s_ccoshl.c index feb1351917..9301a9e10d 100644 --- a/sysdeps/libm-ieee754/s_ccoshl.c +++ b/sysdeps/libm-ieee754/s_ccoshl.c @@ -32,8 +32,6 @@ __ccoshl (__complex__ long double x) int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); - __real__ x = fabsl (__real__ x); - if (rcls >= FP_ZERO) { /* Real part is finite. */ @@ -67,7 +65,7 @@ __ccoshl (__complex__ long double x) { /* Imaginary part is 0.0. */ __real__ retval = HUGE_VALL; - __imag__ retval = __imag__ x; + __imag__ retval = __imag__ x * __copysignl (1.0, __real__ x); } else if (icls > FP_ZERO) { @@ -77,7 +75,8 @@ __ccoshl (__complex__ long double x) __sincosl (__imag__ x, &sinix, &cosix); __real__ retval = __copysignl (HUGE_VALL, cosix); - __imag__ retval = __copysignl (HUGE_VALL, sinix); + __imag__ retval = (__copysignl (HUGE_VALL, sinix) + * __copysignl (1.0, __real__ x)); } else { diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index 68c4cb3103..69dd55ad39 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -29,7 +29,7 @@ #include #include "hurdstartup.h" #include -#include "../stdio-common/_itoa.h" +#include #include #include #include @@ -188,6 +188,9 @@ unfmh(); /* XXX */ /* Set up so we can do RPCs. */ __mach_init (); + /* Initialize frequently used global variable. */ + _dl_pagesize = __getpagesize (); + fmh(); /* XXX */ /* See hurd/hurdstartup.c; this deals with getting information diff --git a/sysdeps/mips/bsd-_setjmp.S b/sysdeps/mips/bsd-_setjmp.S index 819a7018c4..6d841fc237 100644 --- a/sysdeps/mips/bsd-_setjmp.S +++ b/sysdeps/mips/bsd-_setjmp.S @@ -23,7 +23,6 @@ #include -/* XXX Must this be __PIC__ ? --drepper */ #ifdef PIC .option pic2 #endif diff --git a/sysdeps/mips/bsd-setjmp.S b/sysdeps/mips/bsd-setjmp.S index f220404c2c..000aee436a 100644 --- a/sysdeps/mips/bsd-setjmp.S +++ b/sysdeps/mips/bsd-setjmp.S @@ -23,7 +23,6 @@ #include -/* XXX Must this be __PIC__ ? --drepper */ #ifdef PIC .option pic2 #endif diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h index 7456ae0b7a..fce7cffb4a 100644 --- a/sysdeps/mips/dl-machine.h +++ b/sysdeps/mips/dl-machine.h @@ -96,16 +96,6 @@ elf_machine_matches_host (ElfW(Half) e_machine) } } -/* Return the link-time address of _DYNAMIC. Conveniently, this is the -+ first element of the GOT. This must be inlined in a function which -+ uses global data. */ -+static inline ElfW(Addr) -+elf_machine_dynamic (void) -+{ -+ register ElfW(Addr) gp asm ("$28"); -+ return * (ElfW(Addr) *) (gp - 0x7ff0); -+} -+ static inline ElfW(Addr) * elf_mips_got_from_gpreg (ElfW(Addr) gpreg) { diff --git a/sysdeps/mips/mips64/dl-machine.h b/sysdeps/mips/mips64/dl-machine.h index 3277b109d9..a20835af35 100644 --- a/sysdeps/mips/mips64/dl-machine.h +++ b/sysdeps/mips/mips64/dl-machine.h @@ -96,16 +96,6 @@ elf_machine_matches_host (ElfW(Half) e_machine) } } -/* Return the link-time address of _DYNAMIC. Conveniently, this is the -+ first element of the GOT. This must be inlined in a function which -+ uses global data. */ -+static inline ElfW(Addr) -+elf_machine_dynamic (void) -+{ -+ register ElfW(Addr) gp asm ("$28"); -+ return * (ElfW(Addr) *) (gp - 0x7ff0); -+} -+ static inline ElfW(Addr) * elf_mips_got_from_gpreg (ElfW(Addr) gpreg) { diff --git a/sysdeps/sparc/udiv_qrnnd.S b/sysdeps/sparc/udiv_qrnnd.S index 74b932d34b..437d66e9ea 100644 --- a/sysdeps/sparc/udiv_qrnnd.S +++ b/sysdeps/sparc/udiv_qrnnd.S @@ -44,7 +44,7 @@ ENTRY(__udiv_qrnnd) !#PROLOGUE# 1 st %i1,[%fp-8] ld [%fp-8],%f10 -#ifdef __PIC__ +#ifdef PIC ._XL11: call ._XL1 fitod %f10,%f4 @@ -78,7 +78,7 @@ L249: faddd %f4,%f8,%f4 L250: fdivd %f2,%f4,%f2 -#ifdef __PIC__ +#ifdef PIC ._XL22: call ._XL2 nop diff --git a/sysdeps/standalone/arm/bits/errno.h b/sysdeps/standalone/arm/bits/errno.h index 49a4998cf8..362b43dacf 100644 --- a/sysdeps/standalone/arm/bits/errno.h +++ b/sysdeps/standalone/arm/bits/errno.h @@ -19,35 +19,36 @@ /* This file defines the `errno' constants for standalone ARM machines. These constants are essentially arbitrary. */ -#if !defined(__Emath_defined) && (defined(_ERRNO_H) || defined(__need_Emath)) -#undef __need_Emath -#define __Emath_defined 1 +#if !defined __Emath_defined && (defined _ERRNO_H || defined __need_Emath) +# undef __need_Emath +# define __Emath_defined 1 -#define EDOM 1 -#define ERANGE 2 +# define EDOM 1 +# define ERANGE 2 #endif #ifdef _ERRNO_H -#define ENOSYS 3 -#define EINVAL 4 -#define ESPIPE 5 -#define EBADF 6 -#define ENOMEM 7 -#define EACCES 8 -#define ENFILE 9 -#define EMFILE 10 -#define ENAMETOOLONG 11 /* File name too long */ -#define ELOOP 12 /* Too many symbolic links encountered */ -#define ENOMSG 13 /* No message of desired type */ -#define E2BIG 14 /* Arg list too long */ -#define EINTR 15 -#define EILSEQ 16 -#define ENOEXEC 17 -#define ENOENT 18 -#define EPROTOTYPE 19 -#define ESRCH 20 -#define EPERM 21 -#define ENOTDIR 22 +# define ENOSYS 3 +# define EINVAL 4 +# define ESPIPE 5 +# define EBADF 6 +# define ENOMEM 7 +# define EACCES 8 +# define ENFILE 9 +# define EMFILE 10 +# define ENAMETOOLONG 11 /* File name too long */ +# define ELOOP 12 /* Too many symbolic links encountered */ +# define ENOMSG 13 /* No message of desired type */ +# define E2BIG 14 /* Arg list too long */ +# define EINTR 15 +# define EILSEQ 16 +# define ENOEXEC 17 +# define ENOENT 18 +# define EPROTOTYPE 19 +# define ESRCH 20 +# define EPERM 21 +# define ENOTDIR 22 +# define ESTALE 23 #endif #define __set_errno(val) errno = (val) diff --git a/sysdeps/standalone/arm/sysdep.c b/sysdeps/standalone/arm/sysdep.c new file mode 100644 index 0000000000..d2564204ea --- /dev/null +++ b/sysdeps/standalone/arm/sysdep.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995, 1996, 1997 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +/* errno has to be defined somewhere, and it might as well be here. */ +int errno = 0; + +/* The same goes for these magic signal functions. This is a standalone + environment so we do nothing. */ +void _sig_dfl(int sig) +{ +} + +void _sig_ign(int sig) +{ +} diff --git a/sysdeps/unix/mips/sysdep.S b/sysdeps/unix/mips/sysdep.S index ac8335fe5b..4275d664ec 100644 --- a/sysdeps/unix/mips/sysdep.S +++ b/sysdeps/unix/mips/sysdep.S @@ -29,7 +29,7 @@ .set noreorder ENTRY(__syscall_error) -#ifdef __PIC__ +#ifdef PIC .set noat move $1, $31 bltzal $0, 0f diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index a1abbdcae0..18b989cc74 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -27,18 +27,16 @@ static inline void frob_brk (void) { + extern size_t _dl_pagesize; extern void _end; __brk (0); /* Initialize the break. */ if (__sbrk (0) == &_end) - { - /* The dynamic linker was run as a program, and so the initial break - starts just after our bss, at &_end. The malloc in dl-minimal.c - will consume the rest of this page, so tell the kernel to move the - break up that far. When the user program examines its break, it - will see this new value and not clobber our data. */ - size_t pg = __getpagesize (); - __sbrk (pg - ((&_end - (void *) 0) & pg)); - } + /* The dynamic linker was run as a program, and so the initial break + starts just after our bss, at &_end. The malloc in dl-minimal.c + will consume the rest of this page, so tell the kernel to move the + break up that far. When the user program examines its break, it + will see this new value and not clobber our data. */ + __sbrk (_dl_pagesize - ((&_end - (void *) 0) & _dl_pagesize)); } #include diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S index 357f70e47f..4d6408dc97 100644 --- a/sysdeps/unix/sysv/linux/mips/clone.S +++ b/sysdeps/unix/sysv/linux/mips/clone.S @@ -37,7 +37,7 @@ .text NESTED(__clone,4*SZREG,sp) -#ifdef __PIC__ +#ifdef PIC .set noreorder .cpload $25 .set reorder diff --git a/sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S b/sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S index 2dd13062fc..a639511f3e 100644 --- a/sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S +++ b/sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S @@ -72,7 +72,7 @@ ENTRY(____sparc_signal_trampoline) or %g0,%g0,%g1 /*Call sys_setup */ t 0x10 1: -#ifdef __PIC__ +#ifdef PIC /* Save return address */ mov %o7,%o4 ___sxx: @@ -89,7 +89,7 @@ ___syy: #endif sethi %hi(C_SYMBOL_NAME(____sig_table)),%o5 or %o5,%lo(C_SYMBOL_NAME(____sig_table)),%o5 -#ifdef __PIC__ +#ifdef PIC add %o5,%o4,%o4 ld [%o4],%o5 #endif -- cgit v1.2.3