Testsuite for owrdexp.
authorUlrich Drepper <drepper@redhat.com>
Thu, 5 Mar 1998 16:42:56 +0000 (16:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 5 Mar 1998 16:42:56 +0000 (16:42 +0000)
elf/Makefile
elf/dl-load.c
elf/dl-support.c
elf/genrtldtbl.awk
elf/link.h
elf/rtld.c
posix/Makefile
posix/wordexp-test.c [new file with mode: 0644]
sysdeps/generic/dl-cache.c

index aff64e4b9fe77263e3ae3df17aa0d0ca2a7c7616..fc74fa4c8e08d4e4d5ef0e60a0eccbb417eba1bd 100644 (file)
@@ -142,7 +142,7 @@ $(objpfx)trusted-dirs.h: Makefile
           echo "  \"$$dir\",";                                               \
         done;) > $@T
        mv -f $@T $@
-$(objpfx)rtldtbl.h: Makefile
+$(objpfx)rtldtbl.h: Makefile genrtldtbl.awk
        $(make-target-directory)
        echo "$(default-rpath)" | awk -f genrtldtbl.awk > $@T
        mv -f $@T $@
index 7adb6612d02f230f807375ac96c830b210a05faf..003754bf6048e911dbe935ce4eabd764f45b7bc4 100644 (file)
@@ -92,6 +92,9 @@ ELF_PREFERRED_ADDRESS_DATA;
 
 size_t _dl_pagesize;
 
+/* Arguments passed to the dynamic linker.  */
+extern char **_dl_argv;
+
 extern const char *_dl_platform;
 extern size_t _dl_platformlen;
 
@@ -163,7 +166,7 @@ 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)
+             const char **trusted, const char *what, const char *where)
 {
   char *cp;
   size_t nelems = 0;
@@ -268,6 +271,9 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
                max_dirnamelen = dirp->dirnamelen;
            }
 
+         dirp->what = what;
+         dirp->where = where;
+
          dirp->next = all_dirs;
          all_dirs = dirp;
 
@@ -284,7 +290,8 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
 
 
 static struct r_search_path_elem **
-decompose_rpath (const char *rpath, size_t additional_room)
+decompose_rpath (const char *rpath, size_t additional_room,
+                const char *what, const char *where)
 {
   /* Make a copy we can work with.  */
   char *copy = strdupa (rpath);
@@ -305,7 +312,7 @@ decompose_rpath (const char *rpath, size_t additional_room)
   if (result == NULL)
     _dl_signal_error (ENOMEM, NULL, "cannot create cache for search path");
 
-  return fillin_rpath (copy, result, ":", NULL);
+  return fillin_rpath (copy, result, ":", NULL, what, where);
 }
 
 
@@ -358,7 +365,7 @@ _dl_init_paths (const char *llp)
            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);
+                            nllp, "RPATH", l->l_name);
        }
       else
        {
@@ -394,7 +401,8 @@ _dl_init_paths (const char *llp)
          /* We need to take care that the LD_LIBRARY_PATH environment
             variable can contain a semicolon.  */
          (void) fillin_rpath (copy, result, ":;",
-                              __libc_enable_secure ? trusted_dirs : NULL);
+                              __libc_enable_secure ? trusted_dirs : NULL,
+                              "LD_LIBRARY_PATH", NULL);
        }
     }
   else
@@ -415,7 +423,8 @@ _dl_init_paths (const char *llp)
                              "cannot create cache for search path");
 
          (void) fillin_rpath (local_strdup (llp), fake_path_list, ":;",
-                              __libc_enable_secure ? trusted_dirs : NULL);
+                              __libc_enable_secure ? trusted_dirs : NULL,
+                              "LD_LIBRARY_PATH", NULL);
        }
     }
 
@@ -454,6 +463,9 @@ _dl_init_paths (const char *llp)
          if (max_dirnamelen < relem->dirnamelen)
            max_dirnamelen = relem->dirnamelen;
        }
+
+      relem->what = "system search path";
+      relem->where = NULL;
     }
 }
 
@@ -789,6 +801,41 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
   return l;
 }
 \f
+/* Print search path.  */
+static void
+print_search_path (struct r_search_path_elem **list,
+                   const char *what, const char *name)
+{
+  int first = 1;
+
+  _dl_sysdep_message ("\t search path=", NULL);
+
+  while (*list != NULL && (*list)->what == what) /* Yes, ==.  */
+    {
+      char *buf = strdupa ((*list)->dirname);
+
+      if ((*list)->machdirstatus != nonexisting)
+       {
+         buf[(*list)->machdirnamelen - 1] = '\0';
+         _dl_sysdep_message (first ? "" : ":", buf, NULL);
+         first = 0;
+       }
+      if ((*list)->dirstatus != nonexisting)
+       {
+         buf[(*list)->dirnamelen - 1] = '\0';
+         _dl_sysdep_message (first ? "" : ":", buf, NULL);
+         first = 0;
+       }
+      ++list;
+    }
+
+  if (name != NULL)
+    _dl_sysdep_message ("\t\t(", what, " from file ",
+                       name[0] ? name : _dl_argv[0], ")\n", NULL);
+  else
+    _dl_sysdep_message ("\t\t(", what, ")\n", NULL);
+}
+\f
 /* 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.  */
@@ -800,6 +847,7 @@ open_path (const char *name, size_t namelen, int preloaded,
 {
   char *buf;
   int fd = -1;
+  const char *current_what = NULL;
 
   if (dirs == NULL || *dirs == NULL)
     {
@@ -813,6 +861,14 @@ open_path (const char *name, size_t namelen, int preloaded,
       struct r_search_path_elem *this_dir = *dirs;
       size_t buflen = 0;
 
+      /* If we are debugging the search for libraries print the path
+        now if it hasn't happened now.  */
+      if (_dl_debug_libs && current_what != this_dir->what)
+       {
+         current_what = this_dir->what;
+         print_search_path (dirs, current_what, this_dir->where);
+       }
+
       if (this_dir->machdirstatus != nonexisting)
        {
          /* Construct the pathname to try.  */
@@ -821,6 +877,10 @@ open_path (const char *name, size_t namelen, int preloaded,
                                        name, namelen)
                    - buf);
 
+          /* Print name we try if this is wanted.  */
+         if (_dl_debug_libs)
+           _dl_sysdep_message ("\t  trying file=", buf, "\n", NULL);
+
          fd = __open (buf, O_RDONLY);
          if (this_dir->machdirstatus == unknown)
            if (fd != -1)
@@ -872,6 +932,10 @@ open_path (const char *name, size_t namelen, int preloaded,
                                        name, namelen)
                    - buf);
 
+         /* Print name we try if this is wanted.  */
+         if (_dl_debug_libs)
+           _dl_sysdep_message ("\t  trying file=", buf, "\n", NULL);
+
          fd = __open (buf, O_RDONLY);
          if (this_dir->dirstatus == unknown)
            if (fd != -1)
@@ -988,6 +1052,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 
       size_t namelen = strlen (name) + 1;
 
+      if (_dl_debug_libs)
+       _dl_sysdep_message ("\tfind library=", name, "; searching\n", NULL);
+
       fd = -1;
 
       /* First try the DT_RPATH of the dependent object that caused NAME
@@ -1002,7 +1069,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
                                 + 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);
+                 decompose_rpath ((const char *) ptrval, 0,
+                                  "RPATH", l->l_name);
              }
 
            if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
@@ -1046,6 +1114,10 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
       /* Finally, try the default path.  */
       if (fd == -1)
        fd = open_path (name, namelen, preloaded, rtld_search_dirs, &realname);
+
+      /* Add another newline when we a tracing the library loading.  */
+      if (_dl_debug_libs)
+        _dl_sysdep_message ("\n", NULL);
     }
   else
     {
index 5868656c4e02bab4d7166bd9264578188dfa7fd4..9d28d2b64049e915f970e5cfe567651e10840c59 100644 (file)
@@ -35,6 +35,7 @@ const char *_dl_rpath = DEFAULT_RPATH;
 /* Name of the architecture.  */
 const char *_dl_platform;
 size_t _dl_platformlen;
+int _dl_debug_libs;
 
 /* If nonzero print warnings about problematic situations.  */
 int _dl_verbose;
index 63ada003f6b11f0902d919d8eb6c939647c5c275..54cdc8c5896a33db05c5e933c3c1969481bca474 100644 (file)
@@ -12,7 +12,7 @@ BEGIN {
 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, nonexisting, ",
+    printf ("  { \"%s/\", %d, unknown, 0, nonexisting, NULL, NULL, ",
            dir[i], length (dir[i]) + 1);
     if (i== 0)
       printf ("NULL };\n");
index d056e65617c255637b9503283954442b06196730..b8bce5839dc425a928a093d0df86a7559b9907ca 100644 (file)
@@ -106,6 +106,10 @@ struct r_search_path_elem
     size_t machdirnamelen;
     enum r_dir_status machdirstatus;
 
+    /* Strings saying where the definition came from.  */
+    const char *what;
+    const char *where;
+
     /* This link is only used in the `all_dirs' member of `r_search_path'.  */
     struct r_search_path_elem *next;
   };
@@ -238,6 +242,9 @@ extern const char *_dl_profile;
 /* Map of shared object to be profiled.  */
 extern struct link_map *_dl_profile_map;
 
+/* If nonzero the appropriate debug information if printed.  */
+extern int _dl_debug_libs;
+
 /* OS-dependent function to open the zero-fill device.  */
 extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
 
@@ -461,6 +468,10 @@ extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
 /* Show the members of the auxiliary array passed up from the kernel.  */
 extern void _dl_show_auxv (void);
 
+/* Return all environment variables starting with `LD_', one after the
+   other.  */
+extern char *_dl_next_ld_env_entry (char ***position);
+
 __END_DECLS
 
 #endif /* link.h */
index 2707da60df3a12d5f9f0ae7b48ced2f4577fbb48..72316905b4cb8d7406796b841dee265a7df3d253 100644 (file)
@@ -73,6 +73,7 @@ struct r_search_path *_dl_search_paths;
 const char *_dl_profile;
 const char *_dl_profile_output;
 struct link_map *_dl_profile_map;
+int _dl_debug_libs;
 
 /* Set nonzero during loading and initialization of executable and
    libraries, cleared before the executable's entry point runs.  This
@@ -906,6 +907,45 @@ print_missing_version (int errcode __attribute__ ((unused)),
                    objname, ": ", errstring, "\n", NULL);
 }
 \f
+/* Process the string given as the parameter which explains which debugging
+   options are enabled.  */
+static void
+process_dl_debug (char *dl_debug)
+{
+  do
+    {
+#define issep(Ch) ((Ch) == ' ' || (Ch) == ',')
+      /* Skip separating white spaces and commas.  */
+      while (issep (*dl_debug))
+       ++dl_debug;
+      if (*dl_debug != '\0')
+       {
+         if (strncmp (dl_debug, "libs", 4) == 0
+             && (issep (dl_debug[4]) || dl_debug[4] == '\0'))
+           {
+             _dl_debug_libs = 1;
+             dl_debug += 4;
+           }
+         else if (strncmp (dl_debug, "help", 4) == 0
+                  && (issep (dl_debug[4]) || dl_debug[4] == '\0'))
+           {
+             _dl_sysdep_message ("\
+Valid options for the DL_DEBUG environment variable are:\n\
+\n\
+  help    display this help message and exit
+  libs    display library search paths\n", NULL);
+             _exit (0);
+           }
+         else
+           /* Skip everything until next separator.  */
+           do
+             ++dl_debug;
+           while (*dl_debug != '\0' && !issep (*dl_debug));
+       }
+    }
+  while (*dl_debug != '\0');
+}
+\f
 /* Process all environments variables the dynamic linker must recognize.
    Since all of them start with `LD_' we are a bit smarter while finding
    all the entries.  */
@@ -934,6 +974,16 @@ process_envvars (enum mode *modep, int *lazyp)
       if (result < 0)
        continue;
 
+      /* Debugging of the dynamic linker?  */
+      result = strncmp (&envline[3], "DEBUG=", 6);
+      if (result == 0)
+       {
+         process_dl_debug (&envline[9]);
+         continue;
+       }
+      if (result < 0)
+       continue;
+
       /* Which shared object shall be profiled.  */
       result = strncmp (&envline[3], "PROFILE=", 8);
       if (result == 0)
index 5927f313356f1309929e114362fdf2c146857708..a9b78aa6067cdbeab6cae650cc87a58be3b1a163 100644 (file)
@@ -52,7 +52,7 @@ routines :=                                                                 \
        pread pwrite pread64 pwrite64
 
 aux            := init-posix environ
-tests          := tstgetopt testfnm runtests
+tests          := tstgetopt testfnm runtests wordexp-test
 test-srcs      := globtest
 others         := getconf
 install-bin    := getconf
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
new file mode 100644 (file)
index 0000000..2e403ca
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (C) 1997, 1998 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 <wordexp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct test_case_struct
+{
+  int retval;
+  const char *env;
+  const char *words;
+  int flags;
+  int wordc;
+  const char *wordv[10];
+} test_case[] =
+  {
+    { 0, NULL, "one", 0, 1, { "one", } },
+    { 0, NULL, "one two", 0, 2, { "one", "two", } },
+    { 0, NULL, "one two three", 0, 3, { "one", "two", "three", } },
+    { 0, NULL, "~root", 0, 1, { "/root", } },
+    { 0, "foo", "${var}", 0, 1, { "foo", } },
+    { 0, "foo", "$var", 0, 1, { "foo", } },
+    { 0, NULL, "\"quoted\"", 0, 1, { "quoted", } },
+    { -1, NULL, NULL, 0, 0, { NULL, } },
+  };
+
+int
+main (int argc, char * argv[])
+{
+  wordexp_t we;
+  int test;
+  int fail = 0;
+  int retval;
+  int i;
+
+  setenv ("IFS", " \t\n", 1);
+  for (test = 0; test_case[test].retval != -1; test++)
+    {
+      int bzzzt = 0;
+
+      if (test_case[test].env)
+       setenv ("var", test_case[test].env, 1);
+      else
+       unsetenv ("var");
+
+      printf ("Test %d: ", test);
+      retval = wordexp (test_case[test].words, &we, test_case[test].flags);
+
+      if (retval != test_case[test].retval ||
+         we.we_wordc != test_case[test].wordc)
+       bzzzt = 1;
+      else
+       for (i = 0; i < we.we_wordc; i++)
+         if (strcmp (test_case[test].wordv[i], we.we_wordv[i]) != 0)
+           {
+             bzzzt = 1;
+             break;
+           }
+
+      if (bzzzt)
+       {
+         ++fail;
+         printf ("FAILED\n");
+         printf ("Test words: <%s>, need retval %d, wordc %d\n",
+                 test_case[test].words, test_case[test].retval,
+                 test_case[test].wordc);
+         printf ("Got retval %d, wordc %d: ", retval, we.we_wordc);
+         for (i = 0; i < we.we_wordc; i++)
+           printf ("<%s> ", we.we_wordv[i]);
+         printf ("\n");
+       }
+      else
+       printf ("OK\n");
+
+      wordfree (&we);
+    }
+
+  return fail;
+}
index 8eb18b79cc05e9c9531a706f7c87b21cf755e11d..43a987a1fd8611f7579dc32ee27a1ed556c46e72 100644 (file)
@@ -55,6 +55,10 @@ _dl_load_cache_lookup (const char *name)
   unsigned int i;
   const char *best;
 
+  /* Print a message if the loading of libs is traced.  */
+  if (_dl_debug_libs)
+    _dl_sysdep_message ("\t search cache=", LD_SO_CACHE, "\n", NULL);
+
   if (cache == NULL)
     {
       /* Read the contents of the file.  */
@@ -99,5 +103,10 @@ _dl_load_cache_lookup (const char *name)
              break;
          }
       }
+
+  /* Print our result if wanted.  */
+  if (_dl_debug_libs && best != NULL)
+    _dl_sysdep_message ("\t  trying file=", best, "\n", NULL);
+
   return best;
 }