From 61e0617ac34c4daaeb2f07f89a05c9f9353b8879 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 19 Feb 1999 00:00:05 +0000 Subject: Update. * 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. --- elf/Makefile | 10 ++++++-- elf/dl-load.c | 11 +++++++- elf/link.h | 8 +++++- elf/multiload.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ elf/rtld.c | 17 ++++++++++++- 5 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 elf/multiload.c (limited to 'elf') diff --git a/elf/Makefile b/elf/Makefile index 1706efc..ef5b831 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -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 # muwahaha diff --git a/elf/dl-load.c b/elf/dl-load.c index 84951ea..bf3e419 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -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; } diff --git a/elf/link.h b/elf/link.h index ecf0469..4abcb49 100644 --- a/elf/link.h +++ b/elf/link.h @@ -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 #include #include +#include /* 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 index 0000000..724c1ed --- /dev/null +++ b/elf/multiload.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/elf/rtld.c b/elf/rtld.c index df6a945..6aa3a65 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -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. */ } -- cgit v1.1