Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 20 Jul 2000 22:53:54 +0000 (22:53 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 20 Jul 2000 22:53:54 +0000 (22:53 +0000)
* elf/elf.h: Add various DF_1_*, DTF_1_*, and DF_P1_* entries.
* elf/dl-close.c (_dl_close): Don't close an object if it is marked
with nodelete.
* elf/dl-open.c (dl_open_worker): Pass RTLD_NOLOAD as new parameter
to _dl_map_object.  Return immediately if no object loaded.
Set DF_1_NODELETE bit in l_flags_1 if RTLD_NODELETE was passed.
* elf/dynamic-link.h (elf_get_dynamic_info): Copy DT_FLAGS_1 entry
if it exists into l_flags_1 word.
* elf/dl-load.c (_dl_map_object_from_fd): Take no parameter and use
it to determine whether loading is wanted or not.
(_dl_map_object): Likewise.
Call _dl_map_object_from_fd with new parameter.
* sysdeps/generic/ldsodefs.h: Update prototype.
* elf/dl-deps.c: Add new parameter to _dl_map_object calls.
* elf/rtld.c: Likewise.
* elf/Makefile (tests): Add noload.  Add rules to generate noload.
* elf/noload.c: New file.
* include/link.h (struct link_map): Add l_feature_1 and l_flags_1.
* sysdeps/generic/bits/dlfcn.h: Define RTLD_NOLOAD and RTLD_NODELETE.
* sysdeps/mips/bits/dlfcn.h: Likewise.

14 files changed:
ChangeLog
bits/dlfcn.h
elf/dl-close.c
elf/dl-deps.c
elf/dl-load.c
elf/dl-open.c
elf/dynamic-link.h
elf/elf.h
elf/noload.c [new file with mode: 0644]
elf/rtld.c
include/link.h
sysdeps/generic/bits/dlfcn.h
sysdeps/generic/ldsodefs.h
sysdeps/mips/bits/dlfcn.h

index ac87df4..7758f19 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2000-07-20  Ulrich Drepper  <drepper@redhat.com>
 
+       * elf/elf.h: Add various DF_1_*, DTF_1_*, and DF_P1_* entries.
+       * elf/dl-close.c (_dl_close): Don't close an object if it is marked
+       with nodelete.
+       * elf/dl-open.c (dl_open_worker): Pass RTLD_NOLOAD as new parameter
+       to _dl_map_object.  Return immediately if no object loaded.
+       Set DF_1_NODELETE bit in l_flags_1 if RTLD_NODELETE was passed.
+       * elf/dynamic-link.h (elf_get_dynamic_info): Copy DT_FLAGS_1 entry
+       if it exists into l_flags_1 word.
+       * elf/dl-load.c (_dl_map_object_from_fd): Take no parameter and use
+       it to determine whether loading is wanted or not.
+       (_dl_map_object): Likewise.
+       Call _dl_map_object_from_fd with new parameter.
+       * sysdeps/generic/ldsodefs.h: Update prototype.
+       * elf/dl-deps.c: Add new parameter to _dl_map_object calls.
+       * elf/rtld.c: Likewise.
+       * elf/Makefile (tests): Add noload.  Add rules to generate noload.
+       * elf/noload.c: New file.
+       * include/link.h (struct link_map): Add l_feature_1 and l_flags_1.
+       * sysdeps/generic/bits/dlfcn.h: Define RTLD_NOLOAD and RTLD_NODELETE.
+       * sysdeps/mips/bits/dlfcn.h: Likewise.
+
        * libio/Makefile (tests): Add tst_wprintf2.
        (tst_wprintf2-ARGS): Define.
        * libio/tst_wprintf2.c: New file.
index 99d5448..0039eda 100644 (file)
 #endif
 
 /* The MODE argument to `dlopen' contains one of the following: */
-#define RTLD_LAZY      0x001   /* Lazy function call binding.  */
-#define RTLD_NOW       0x002   /* Immediate function call binding.  */
-#define        RTLD_BINDING_MASK 0x3   /* Mask of binding time value.  */
+#define RTLD_LAZY      0x00001 /* Lazy function call binding.  */
+#define RTLD_NOW       0x00002 /* Immediate function call binding.  */
+#define        RTLD_BINDING_MASK   0x3 /* Mask of binding time value.  */
+#define RTLD_NOLOAD    0x00004 /* Do not load the object.  */
 
 /* If the following bit is set in the MODE argument to `dlopen',
    the symbols of the loaded object and its dependencies are made
    visible as if the object were linked directly into the program.  */
-#define RTLD_GLOBAL    0x100
+#define RTLD_GLOBAL    0x00100
 
 /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
    The implementation does this by default and so we can define the
    value to zero.  */
 #define RTLD_LOCAL     0
 
+/* Do not delete object when closed.  */
+#define RTLD_NODELETE  0x01000
+
 #ifdef __USE_GNU
 /* To support profiling of shared objects it is a good idea to call
    the function found using `dlsym' using the following macro since
index ec563ed..99d52d0 100644 (file)
@@ -48,6 +48,11 @@ _dl_close (void *_map)
   unsigned int nrellist;
   unsigned int i;
 
+  /* First see whether we can remove the object at all.  */
+  if (map->l_flags_1 & DF_1_NODELETE)
+    /* Nope.  Do nothing.  */
+    return;
+
   if (map->l_opencount == 0)
     _dl_signal_error (0, map->l_name, N_("shared object not open"));
 
@@ -112,7 +117,8 @@ _dl_close (void *_map)
      points to, the 0th elt being MAP itself.  Decrement the reference
      counts on all the objects MAP depends on.  */
   for (i = 0; i < nsearchlist; ++i)
-    --list[i]->l_opencount;
+    if (! (list[i]->l_flags_1 & DF_1_NODELETE))
+      --list[i]->l_opencount;
 
   /* Check each element of the search list to see if all references to
      it are gone.  */
index 1d3779f..5bc048e 100644 (file)
@@ -67,7 +67,7 @@ openaux (void *a)
   args->aux = _dl_map_object (args->map, args->name, 0,
                              (args->map->l_type == lt_executable
                               ? lt_library : args->map->l_type),
-                             args->trace_mode);
+                             args->trace_mode, 0);
 }
 
 
@@ -232,7 +232,7 @@ _dl_map_object_deps (struct link_map *map,
 
                dep = _dl_map_object (l, name, 0,
                                      l->l_type == lt_executable ? lt_library :
-                                     l->l_type, trace_mode);
+                                     l->l_type, trace_mode, 0);
 
                /* Add it in any case to the duplicate list.  */
                newp = alloca (sizeof (struct list));
@@ -316,7 +316,7 @@ _dl_map_object_deps (struct link_map *map,
                    args.aux = _dl_map_object (l, name, 0,
                                               (l->l_type == lt_executable
                                                ? lt_library : l->l_type),
-                                              trace_mode);
+                                              trace_mode, 0);
                  }
 
                /* The auxiliary object is actually available.
index 2c506b5..fbf82e2 100644 (file)
@@ -688,7 +688,7 @@ static
 #endif
 struct link_map *
 _dl_map_object_from_fd (const char *name, int fd, char *realname,
-                       struct link_map *loader, int l_type)
+                       struct link_map *loader, int l_type, int noload)
 {
   /* This is the expected ELF header.  */
 #define ELF32_CLASS ELFCLASS32
@@ -752,6 +752,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
        return l;
       }
 
+  if (noload)
+    /* We are not supposed to load the object unless it is already
+       loaded.  So return now.  */
+    return NULL;
+
   /* Print debugging message.  */
   if (__builtin_expect (_dl_debug_files, 0))
     _dl_debug_message (1, "file=", name, ";  generating link map\n", NULL);
@@ -1301,7 +1306,7 @@ open_path (const char *name, size_t namelen, int preloaded,
 struct link_map *
 internal_function
 _dl_map_object (struct link_map *loader, const char *name, int preloaded,
-               int type, int trace_mode)
+               int type, int trace_mode, int noload)
 {
   int fd;
   char *realname;
@@ -1501,5 +1506,5 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
        _dl_signal_error (errno, name, N_("cannot open shared object file"));
     }
 
-  return _dl_map_object_from_fd (name, fd, realname, loader, type);
+  return _dl_map_object_from_fd (name, fd, realname, loader, type, noload);
 }
index 680377b..477ecdf 100644 (file)
@@ -144,7 +144,17 @@ dl_open_worker (void *a)
     }
 
   /* Load the named object.  */
-  args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
+  args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0,
+                                   mode & RTLD_NOLOAD);
+
+  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
+     set and the object is not already loaded.  */
+  if (new == NULL)
+    {
+      assert (mode & RTLD_NOLOAD);
+      return;
+    }
+
   if (new->l_searchlist.r_list)
     /* It was already open.  */
     return;
@@ -279,6 +289,11 @@ dl_open_worker (void *a)
       /* XXX Do we have to add something to r_dupsearchlist???  --drepper */
     }
 
+  /* Mark the object as not deletable if the RTLD_NODELETE flags was
+     passed.  */
+  if (__builtin_expect (mode & RTLD_NODELETE, 0))
+    new->l_flags_1 |= DF_1_NODELETE;
+
   if (_dl_sysdep_start == NULL)
     /* We must be the static _dl_open in libc.a.  A static program that
        has loaded a dynamic object now has competition.  */
index 79e17ed..c6fa3e1 100644 (file)
@@ -114,6 +114,8 @@ elf_get_dynamic_info (struct link_map *l)
       if (flags & DF_BIND_NOW)
        info[DT_BIND_NOW] = info[DT_FLAGS];
     }
+  if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
+    l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
   if (info[DT_RUNPATH] != NULL)
     /* If both RUNPATH and RPATH are given, the latter is ignored.  */
     info[DT_RPATH] = NULL;
index 2005bdc..ce04184 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -622,7 +622,7 @@ typedef struct
 #define DT_PLTPADSZ    0x6ffffdf9
 #define DT_MOVEENT     0x6ffffdfa
 #define DT_MOVESZ      0x6ffffdfb
-#define DT_FEATURE_1   0x6ffffdfc
+#define DT_FEATURE_1   0x6ffffdfc      /* Feature selection (DTF_*).  */
 #define DT_POSFLAG_1   0x6ffffdfd      /* Flags for DT_* entries, effecting
                                           the following DT_* entry.  */
 #define DT_SYMINSZ     0x6ffffdfe      /* Size of syminfo table (in bytes) */
@@ -678,6 +678,23 @@ typedef struct
 #define DF_1_LOADFLTR  0x00000010      /* Trigger filtee loading at runtime.*/
 #define DF_1_INITFIRST 0x00000020      /* Set RTLD_INITFIRST for this object*/
 #define DF_1_NOOPEN    0x00000040      /* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN    0x00000080      /* $ORIGIN must be handled.  */
+#define DF_1_DIRECT    0x00000100      /* Direct binding enabled.  */
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400      /* Object is used to interpose.  */
+#define DF_1_NODEFLIB  0x00000800      /* Ignore default lib search path.  */
+#define DF_1_NODUMP    0x00001000
+#define DF_1_CONFALT   0x00002000
+#define DF_1_ENDFILTEE 0x00004000
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT  0x00000001
+#define DTF_1_CONFEXP  0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD 0x00000001      /* Lazyload following object.  */
+#define DF_P1_GROUPPERM        0x00000002      /* Symbols from next object are not
+                                          generally available.  */
 
 /* Version definition sections.  */
 
diff --git a/elf/noload.c b/elf/noload.c
new file mode 100644 (file)
index 0000000..826427f
--- /dev/null
@@ -0,0 +1,70 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  int result = 0;
+
+  /* First try to load an object which is a dependency.  This should
+     succeed.  */
+  if (dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
+    {
+      printf ("cannot open \"testobj1.so\": %s\n", dlerror ());
+      result = 1;
+    }
+  else
+    puts ("loading \"testobj1.so\" succeeded, OK");
+
+  /* Now try loading an object which is not already loaded.  */
+  if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
+    {
+      puts ("succeeded in loading \"testobj5.so\"");
+      result = 1;
+    }
+  else
+    {
+      /* Load the object and run the same test again.  */
+      void *p;
+
+      puts ("\"testobj5.so\" wasn't loaded and RTLD_NOLOAD prevented it, OK");
+
+      p = dlopen ("testobj5.so", RTLD_LAZY);
+
+      if (p == NULL)
+       {
+         printf ("cannot open \"testobj5.so\" without RTLD_NOLOAD: %s\n",
+                 dlerror ());
+         result = 1;
+       }
+      else
+       {
+         puts ("loading \"testobj5.so\" succeeded, OK");
+
+         if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
+           {
+             printf ("cannot open \"testobj5.so\": %s\n", dlerror ());
+             result = 1;
+           }
+         else
+           puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK");
+
+         if (dlclose (p) != 0)
+           {
+             printf ("cannot close \"testobj5.so\": %s\n", dlerror ());
+             result = 1;
+           }
+         else
+           puts ("closing \"testobj5.so\" succeeded, OK");
+       }
+    }
+
+  return result;
+}
+
+
+int
+foo (int a)
+{
+  return 42 + a;
+}
index 1db9699..8276b79 100644 (file)
@@ -313,7 +313,7 @@ static void
 map_doit (void *a)
 {
   struct map_args *args = (struct map_args *) a;
-  args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0);
+  args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0, 0);
 }
 
 static void
@@ -514,7 +514,7 @@ of this helper program; chances are you did not intend to run this program.\n\
       else
        {
          HP_TIMING_NOW (start);
-         _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
+         _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0, 0);
          HP_TIMING_NOW (stop);
 
          HP_TIMING_DIFF (load_time, start, stop);
@@ -694,7 +694,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                || strchr (p, '/') == NULL))
          {
            struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
-                                                      lt_library, 0);
+                                                      lt_library, 0, 0);
            if (new_map->l_opencount == 1)
              /* It is no duplicate.  */
              ++npreloads;
@@ -762,7 +762,7 @@ of this helper program; chances are you did not intend to run this program.\n\
            if (p[0] != '\0')
              {
                struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
-                                                          lt_library, 0);
+                                                          lt_library, 0, 0);
                if (new_map->l_opencount == 1)
                  /* It is no duplicate.  */
                  ++npreloads;
@@ -773,7 +773,7 @@ of this helper program; chances are you did not intend to run this program.\n\
        {
          char *p = strndupa (problem, file_size - (problem - file));
          struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
-                                                    lt_library, 0);
+                                                    lt_library, 0, 0);
          if (new_map->l_opencount == 1)
            /* It is no duplicate.  */
            ++npreloads;
index 38652ca..375d5d1 100644 (file)
@@ -214,6 +214,10 @@ struct link_map
     unsigned int l_reldepsmax;
     unsigned int l_reldepsact;
     struct link_map **l_reldeps;
+
+    /* Various flag words.  */
+    ElfW(Word) l_feature_1;
+    ElfW(Word) l_flags_1;
   };
 
 #endif /* link.h */
index 99d5448..0039eda 100644 (file)
 #endif
 
 /* The MODE argument to `dlopen' contains one of the following: */
-#define RTLD_LAZY      0x001   /* Lazy function call binding.  */
-#define RTLD_NOW       0x002   /* Immediate function call binding.  */
-#define        RTLD_BINDING_MASK 0x3   /* Mask of binding time value.  */
+#define RTLD_LAZY      0x00001 /* Lazy function call binding.  */
+#define RTLD_NOW       0x00002 /* Immediate function call binding.  */
+#define        RTLD_BINDING_MASK   0x3 /* Mask of binding time value.  */
+#define RTLD_NOLOAD    0x00004 /* Do not load the object.  */
 
 /* If the following bit is set in the MODE argument to `dlopen',
    the symbols of the loaded object and its dependencies are made
    visible as if the object were linked directly into the program.  */
-#define RTLD_GLOBAL    0x100
+#define RTLD_GLOBAL    0x00100
 
 /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
    The implementation does this by default and so we can define the
    value to zero.  */
 #define RTLD_LOCAL     0
 
+/* Do not delete object when closed.  */
+#define RTLD_NODELETE  0x01000
+
 #ifdef __USE_GNU
 /* To support profiling of shared objects it is a good idea to call
    the function found using `dlsym' using the following macro since
index fc9a9d1..a850107 100644 (file)
@@ -271,7 +271,7 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
    value to allow additional security checks.  */
 extern struct link_map *_dl_map_object (struct link_map *loader,
                                        const char *name, int preloaded,
-                                       int type, int trace_mode)
+                                       int type, int trace_mode, int noload)
      internal_function;
 
 /* Call _dl_map_object on the dependencies of MAP, and set up
index 0da3a67..006eeb6 100644 (file)
 #endif
 
 /* The MODE argument to `dlopen' contains one of the following: */
-#define RTLD_LAZY      0x001   /* Lazy function call binding.  */
-#define RTLD_NOW       0x002   /* Immediate function call binding.  */
-#define        RTLD_BINDING_MASK 0x3   /* Mask of binding time value.  */
+#define RTLD_LAZY      0x0001  /* Lazy function call binding.  */
+#define RTLD_NOW       0x0002  /* Immediate function call binding.  */
+#define        RTLD_BINDING_MASK  0x3  /* Mask of binding time value.  */
+#define RTLD_NOLOAD    0x00008 /* Do not load the object.  */
 
 /* If the following bit is set in the MODE argument to `dlopen',
    the symbols of the loaded object and its dependencies are made
    visible as if the object were linked directly into the program.  */
-#define RTLD_GLOBAL    0x004
+#define RTLD_GLOBAL    0x0004
 
 /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
    The implementation does this by default and so we can define the
    value to zero.  */
 #define RTLD_LOCAL      0
 
+/* Do not delete object when closed.  */
+#define RTLD_NODELETE  0x01000
+
 #ifdef __USE_GNU
 /* To support profiling of shared objects it is a good idea to call
    the function found using `dlsym' using the following macro since