Update. cvs/libc-ud-970725
authorUlrich Drepper <drepper@redhat.com>
Sat, 26 Jul 1997 02:33:30 +0000 (02:33 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 26 Jul 1997 02:33:30 +0000 (02:33 +0000)
1997-07-26 04:14  Ulrich Drepper  <drepper@cygnus.com>

* 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 <kukuk@vt.uni-paderborn.de>.

* 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  <hjl@gnu.ai.mit.edu>

* 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  <Philip.Blundell@pobox.com>

* sysdeps/standalone/arm/sysdep.c: New file.

1997-07-25 13:25  Philip Blundell  <Philip.Blundell@pobox.com>

* 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  <hjl@gnu.ai.mit.edu>

* elf/dl-deps.c (_dl_map_object_deps): Fix a typo.

1997-07-22  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* math/libm-test.c (ccos_test, ccosh_test): Fix sign in some
tests.

1997-07-24  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

* sunrpc/clnt_udp.c (clntudp_call): Rename cu_wait from timeout to
not shadow the variable in the outer scope.

36 files changed:
ChangeLog
Makeconfig
db/hash/hash.c
elf/Makefile
elf/dl-deps.c
elf/dl-error.c
elf/dl-load.c
elf/dl-object.c
elf/dl-support.c
elf/elf.h
elf/genrtldtbl.awk [new file with mode: 0644]
elf/link.h
elf/rtld.c
math/libm-test.c
nss/libnss_files.map
sunrpc/clnt_udp.c
sysdeps/arm/machine-gmon.h [new file with mode: 0644]
sysdeps/generic/dl-sysdep.c
sysdeps/generic/machine-gmon.h
sysdeps/generic/strsep.c
sysdeps/i386/dl-machine.h
sysdeps/libm-ieee754/s_ccosh.c
sysdeps/libm-ieee754/s_ccoshf.c
sysdeps/libm-ieee754/s_ccoshl.c
sysdeps/mach/hurd/dl-sysdep.c
sysdeps/mips/bsd-_setjmp.S
sysdeps/mips/bsd-setjmp.S
sysdeps/mips/dl-machine.h
sysdeps/mips/mips64/dl-machine.h
sysdeps/sparc/udiv_qrnnd.S
sysdeps/standalone/arm/bits/errno.h
sysdeps/standalone/arm/sysdep.c [new file with mode: 0644]
sysdeps/unix/mips/sysdep.S
sysdeps/unix/sysv/linux/dl-sysdep.c
sysdeps/unix/sysv/linux/mips/clone.S
sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S

index 9f3ed37..842ed6f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@
+1997-07-26 04:14  Ulrich Drepper  <drepper@cygnus.com>
+
+       * 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 <kukuk@vt.uni-paderborn.de>.
+
+       * 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  <hjl@gnu.ai.mit.edu>
+
+       * 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  <Philip.Blundell@pobox.com>
+
+       * sysdeps/standalone/arm/sysdep.c: New file.
+
+1997-07-25 13:25  Philip Blundell  <Philip.Blundell@pobox.com>
+
+       * 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  <hjl@gnu.ai.mit.edu>
+
+       * elf/dl-deps.c (_dl_map_object_deps): Fix a typo.
+
+1997-07-22  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * math/libm-test.c (ccos_test, ccosh_test): Fix sign in some
+       tests.
+
+1997-07-24  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * 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  <drepper@cygnus.com>
 
        * elf/dl-deps.c: Complete rewrite to handle DT_AUXILIARY correctly.
index 0756d91..4d6e2e6 100644 (file)
@@ -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.
index 08f2a7e..0267da8 100644 (file)
@@ -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);
        }
 
index 269a872..e447114 100644 (file)
@@ -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
 
index 36f5ee0..e990d69 100644 (file)
@@ -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;
     }
 }
index e2565bb..7ee803a 100644 (file)
@@ -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] ?: "<program name unknown>",
-                       ": error in loading shared libraries\n",
+                       ": error in loading shared libraries",
                        objname ?: "", objname ? ": " : "",
                        errstring, errcode ? ": " : "",
                        errcode ? strerror (errcode) : "", "\n", NULL);
index 8785921..1301e73 100644 (file)
@@ -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.
 
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <errno.h>
+#include <fcntl.h>
 #include <link.h>
-#include <sys/types.h>
-#include <sys/mman.h>
+#include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
 #include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #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;
 }
 \f
-/* 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
     {
index 941bfa3..65f80d1 100644 (file)
@@ -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)
     {
index 21cd13e..3333bf1 100644 (file)
 /* 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 <link.h>
 #include <stdlib.h>
-
+#include <unistd.h>
+#include <dl-machine.h>
 
 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);
index d01bc90..02d092f 100644 (file)
--- 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 (file)
index 0000000..50f81c8
--- /dev/null
@@ -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);
+}
index f457174..e0fccd0 100644 (file)
@@ -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 */
index a025757..7189ca6 100644 (file)
@@ -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.  */
index 72c09a7..2ea0bf8 100644 (file)
@@ -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",
index de02366..07e5c9a 100644 (file)
@@ -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:
     *;
index a54e1d5..28aa6ef 100644 (file)
@@ -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 (file)
index 0000000..27643df
--- /dev/null
@@ -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 <sysdep.h>
+#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);                                         \
+}
index e18f0b8..4f97f85 100644 (file)
 #include <link.h>
 #include <unistd.h>
 
+#include <dl-machine.h>
 
 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;
index c4a2168..3b63707 100644 (file)
      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
index d17e53a..b2c7e90 100644 (file)
@@ -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.  */
index 0388cbe..d6fc038 100644 (file)
@@ -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
index 1e92f03..394101f 100644 (file)
@@ -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
        {
index 573a633..a8043fd 100644 (file)
@@ -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
        {
index feb1351..9301a9e 100644 (file)
@@ -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
        {
index 68c4cb3..69dd55a 100644 (file)
@@ -29,7 +29,7 @@
 #include <mach/mig_support.h>
 #include "hurdstartup.h"
 #include <mach/host_info.h>
-#include "../stdio-common/_itoa.h"
+#include <stdio-common/_itoa.h>
 #include <hurd/auth.h>
 #include <hurd/term.h>
 #include <stdarg.h>
@@ -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
index 819a701..6d841fc 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sysdep.h>
 
-/* XXX Must this be __PIC__ ? --drepper */
 #ifdef PIC
        .option pic2
 #endif
index f220404..000aee4 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sysdep.h>
 
-/* XXX Must this be __PIC__ ? --drepper */
 #ifdef PIC
        .option pic2
 #endif
index 7456ae0..fce7cff 100644 (file)
@@ -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)
 {
index 3277b10..a20835a 100644 (file)
@@ -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)
 {
index 74b932d..437d66e 100644 (file)
@@ -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
index 49a4998..362b43d 100644 (file)
 /* 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 (file)
index 0000000..d256420
--- /dev/null
@@ -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 <sysdep.h>
+
+/* 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)
+{
+}
index ac8335f..4275d66 100644 (file)
@@ -29,7 +29,7 @@
        .set noreorder
 
 ENTRY(__syscall_error)
-#ifdef __PIC__
+#ifdef PIC
        .set    noat
        move    $1, $31
        bltzal  $0, 0f
index a1abbdc..18b989c 100644 (file)
 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 <sysdeps/generic/dl-sysdep.c>
index 357f70e..4d6408d 100644 (file)
@@ -37,7 +37,7 @@
 
        .text
 NESTED(__clone,4*SZREG,sp)
-#ifdef __PIC__
+#ifdef PIC
        .set            noreorder
        .cpload         $25
        .set            reorder
index 2dd1306..a639511 100644 (file)
@@ -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