* 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.
This commit is contained in:
Ulrich Drepper 1999-02-19 00:00:05 +00:00
parent 1a989e004c
commit 61e0617ac3
6 changed files with 128 additions and 5 deletions

View File

@ -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.

View 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
# muwahaha

View 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;
}

View 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 */

78
elf/multiload.c Normal file
View File

@ -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;
}

View File

@ -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. */
}