Update.
authorUlrich Drepper <drepper@redhat.com>
Fri, 19 Feb 1999 00:00:05 +0000 (00:00 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 19 Feb 1999 00:00:05 +0000 (00:00 +0000)
* elf/link.h (link_map): Add l_dev and l_ino.
* elf/dl-load.c (_dl_map_object_from_fd): Test dev/ino of newly
loaded shared object with all laoded objects.  Initialize l_ino
and l_dev in case it's new.
* elf/rtld.c (dl_main): Explain situation is l_dev/l_ino with main
object.
* elf/Makefile: Compile and run new test.
* elf/multiload.c: New file.

ChangeLog
elf/Makefile
elf/dl-load.c
elf/link.h
elf/multiload.c [new file with mode: 0644]
elf/rtld.c

index c1a0036..ff83c31 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 1999-02-18  Ulrich Drepper  <drepper@cygnus.com>
 
+       * elf/link.h (link_map): Add l_dev and l_ino.
+       * elf/dl-load.c (_dl_map_object_from_fd): Test dev/ino of newly
+       loaded shared object with all laoded objects.  Initialize l_ino
+       and l_dev in case it's new.
+       * elf/rtld.c (dl_main): Explain situation is l_dev/l_ino with main
+       object.
+       * elf/Makefile: Compile and run new test.
+       * elf/multiload.c: New file.
+
        * nss/nsswitch.h (service_user): Change name field from const char *
        to char[0].
        (name_database_entry): Likewise.
index 1706efc..ef5b831 100644 (file)
@@ -77,7 +77,7 @@ others                += ldconfig
 install-rootsbin += ldconfig
 endif
 
-tests = loadtest restest1 preloadtest loadfail
+tests = loadtest restest1 preloadtest loadfail multiload
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                testobj1_1 failobj
 extra-objs += $(modules-names:=.os)
@@ -244,7 +244,13 @@ preloadtest-ENV = \
 $(objpfx)loadfail: $(libdl)
 LDFLAGS-loadfail = -rdynamic
 
-$(objpfx)loadfile.out: $(objpfx)failobj.so
+$(objpfx)loadfail.out: $(objpfx)failobj.so
+
+$(objpfx)multiload: $(libdl)
+LDFLAGS-multiload = -rdynamic
+CFLAGS-multiload.c = -DOBJDIR=\"$(objdir)/$(subdir)\"
+
+$(objpfx)multiload.out: $(objpfx)testobj1.so
 \f
 # muwahaha
 
index 84951ea..bf3e419 100644 (file)
@@ -602,10 +602,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
   int type;
   char *readbuf;
   ssize_t readlength;
+  struct stat st;
+
+  /* Get file information.  */
+  if (__fstat (fd, &st) < 0)
+    lose (errno, "cannot stat shared object");
 
   /* Look again to see if the real name matched another already loaded.  */
   for (l = _dl_loaded; l; l = l->l_next)
-    if (! strcmp (realname, l->l_name))
+    if (l->l_ino == st.st_ino && l->l_dev == st.st_dev)
       {
        /* The object is already loaded.
           Just bump its reference count and return it.  */
@@ -961,6 +966,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
       l->l_scope[0] = &l->l_symbolic_searchlist;
     }
 
+  /* Finally the file information.  */
+  l->l_dev = st.st_dev;
+  l->l_ino = st.st_ino;
+
   return l;
 }
 \f
index ecf0469..4abcb49 100644 (file)
@@ -1,6 +1,6 @@
 /* Data structure for communication from the run-time dynamic linker for
    loaded ELF shared objects.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -24,6 +24,7 @@
 #include <features.h>
 #include <elf.h>
 #include <dlfcn.h>
+#include <sys/types.h>
 
 /* We use this macro to refer to ELF types independent of the native wordsize.
    `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'.  */
@@ -193,6 +194,11 @@ struct link_map
     /* A similar array, this time only with the local scope.  This is
        used occasionally.  */
     struct r_scope_elem *l_local_scope[2];
+
+    /* This information is kept to check for sure whether a shared
+       object is the same as one already loaded.  */
+    dev_t l_dev;
+    ino_t l_ino;
   };
 
 #endif /* link.h */
diff --git a/elf/multiload.c b/elf/multiload.c
new file mode 100644 (file)
index 0000000..724c1ed
--- /dev/null
@@ -0,0 +1,78 @@
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main (void)
+{
+  void *a;
+  void *b;
+  void *c;
+  void *d;
+  char *wd;
+  char *base;
+  char *buf;
+
+  /* Change to the binary directory.  */
+  if (chdir (OBJDIR) != 0)
+    {
+      printf ("cannot change to `%s': %m", OBJDIR);
+      exit (EXIT_FAILURE);
+    }
+
+  wd = getcwd (NULL, 0);
+  base = basename (wd);
+  buf = alloca (strlen (wd) + strlen (base) + 5 + sizeof "testobj1.so");
+
+  printf ("loading `%s'\n", "./testobj1.so");
+  a = dlopen ("./testobj1.so", RTLD_NOW);
+  if (a == NULL)
+    {
+      printf ("cannot load `./testobj1.so': %s\n", dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (stpcpy (buf, "../"), base), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  b = dlopen (buf, RTLD_NOW);
+  if (b == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (buf, wd), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  c = dlopen (buf, RTLD_NOW);
+  if (c == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  stpcpy (stpcpy (stpcpy (stpcpy (buf, wd), "/../"), base), "/testobj1.so");
+  printf ("loading `%s'\n", buf);
+  d = dlopen (buf, RTLD_NOW);
+  if (d == NULL)
+    {
+      printf ("cannot load `%s': %s\n", buf, dlerror ());
+      exit (EXIT_FAILURE);
+    }
+
+  if (a != b || b != c || c != d)
+    {
+      puts ("shared object loaded more than once");
+      exit (EXIT_FAILURE);
+    }
+
+  return 0;
+}
+
+int
+foo (int a)
+{
+  return a;
+}
index df6a945..6aa3a65 100644 (file)
@@ -461,7 +461,7 @@ of this helper program; chances are you did not intend to run this program.\n\
          HP_TIMING_NOW (start);
          _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
          HP_TIMING_NOW (stop);
-         
+
          HP_TIMING_DIFF (load_time, start, stop);
        }
 
@@ -486,6 +486,21 @@ of this helper program; chances are you did not intend to run this program.\n\
       _dl_loaded->l_entry = *user_entry;
       _dl_loaded->l_opencount = 1;
 
+      /* At this point we are in a bit of trouble.  We would have to
+        fill in the values for l_dev and l_ino.  But in general we
+        do not know where the file is.  We also do not handle AT_EXECFD
+        even if it would be passed up.
+
+        We leave the values here defined to 0.  This is normally no
+        problem as the program code itself is normally no shared
+        object and therefore cannot be loaded dynamically.  Nothing
+        prevent the use of dynamic binaries and in these situations
+        we might get problems.  We might not be able to find out
+        whether the object is already loaded.  But since there is no
+        easy way out and because the dynamic binary must also not
+        have an SONAME we ignore this program for now.  If it becomes
+        a problem we can force people using SONAMEs.  */
+
       /* We delay initializing the path structure until we got the dynamic
         information for the program.  */
     }