mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
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.
This commit is contained in:
parent
1a989e004c
commit
61e0617ac3
@ -1,5 +1,14 @@
|
|||||||
1999-02-18 Ulrich Drepper <drepper@cygnus.com>
|
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 *
|
* nss/nsswitch.h (service_user): Change name field from const char *
|
||||||
to char[0].
|
to char[0].
|
||||||
(name_database_entry): Likewise.
|
(name_database_entry): Likewise.
|
||||||
|
10
elf/Makefile
10
elf/Makefile
@ -77,7 +77,7 @@ others += ldconfig
|
|||||||
install-rootsbin += ldconfig
|
install-rootsbin += ldconfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
tests = loadtest restest1 preloadtest loadfail
|
tests = loadtest restest1 preloadtest loadfail multiload
|
||||||
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
testobj1_1 failobj
|
testobj1_1 failobj
|
||||||
extra-objs += $(modules-names:=.os)
|
extra-objs += $(modules-names:=.os)
|
||||||
@ -244,7 +244,13 @@ preloadtest-ENV = \
|
|||||||
$(objpfx)loadfail: $(libdl)
|
$(objpfx)loadfail: $(libdl)
|
||||||
LDFLAGS-loadfail = -rdynamic
|
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
|
# muwahaha
|
||||||
|
|
||||||
|
@ -602,10 +602,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
|
|||||||
int type;
|
int type;
|
||||||
char *readbuf;
|
char *readbuf;
|
||||||
ssize_t readlength;
|
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. */
|
/* Look again to see if the real name matched another already loaded. */
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
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.
|
/* The object is already loaded.
|
||||||
Just bump its reference count and return it. */
|
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;
|
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;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Data structure for communication from the run-time dynamic linker for
|
/* Data structure for communication from the run-time dynamic linker for
|
||||||
loaded ELF shared objects.
|
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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include <features.h>
|
#include <features.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
/* We use this macro to refer to ELF types independent of the native wordsize.
|
/* 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'. */
|
`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
|
/* A similar array, this time only with the local scope. This is
|
||||||
used occasionally. */
|
used occasionally. */
|
||||||
struct r_scope_elem *l_local_scope[2];
|
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 */
|
#endif /* link.h */
|
||||||
|
78
elf/multiload.c
Normal file
78
elf/multiload.c
Normal 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;
|
||||||
|
}
|
17
elf/rtld.c
17
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);
|
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);
|
||||||
HP_TIMING_NOW (stop);
|
HP_TIMING_NOW (stop);
|
||||||
|
|
||||||
HP_TIMING_DIFF (load_time, start, 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_entry = *user_entry;
|
||||||
_dl_loaded->l_opencount = 1;
|
_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
|
/* We delay initializing the path structure until we got the dynamic
|
||||||
information for the program. */
|
information for the program. */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user