mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
* Makerules ($(common-objpfx)libc.so): Depend on $(elfobjdir)/ld.so.
* elf/dl-close.c: New file. * elf/link.h: Declare _dl_close. * elf/Makefile (routines): Add dl-close. * elf/dlclose.c (dlclose): Use _dl_close. * elf/Makefile ($(objpfx)librtld.so): Remove libelf from deps. * elf/dl-runtime.c (_dl_global_scope): New variable. (_dl_object_relocation_scope): New function. (fixup): Use it. * elf/rtld.c (dl_main): Use it. * elf/dl-open.c (_dl_open): Use it. If (MODE & RTLD_GLOBAL), set the l_global bit and append the new map to _dl_global_scope. * elf/link.h: Declare _dl_global_scope, _dl_global_scope_alloc, and _dl_object_relocation_scope. * elf/link.h (struct link_map): Add l_loader member. Remove _dl_map_object_from_fd decl. * elf/dl-load.c (_dl_map_object): Pass LOADER to ... (_dl_map_object_from_fd): Take new arg LOADER and set l_loader member. (_dl_map_object): Try DT_RPATH from all loaders up the chain. * elf/dl-object.c (_dl_loaded): Variable removed. (_dl_default_scope): New variable replaces it. * elf/link.h (_dl_loaded): Remove variable decl; instead define as macro for _dl_default_scope[2]. (_dl_default_scope): Declare it. * sysdeps/i386/dl-machine.h (RTLD_START): Use _dl_default_scope[2] instead of _dl_loaded. * sysdeps/m68k/dl-machine.h (RTLD_START): Likewise. * elf/rtld.c (dl_main): Use _dl_default_scope for symbol lookups. * elf/dl-reloc.c (_dl_relocate_object): Remove check for _dl_rtld_map. * elf/rtld.c (dl_main): Pass 0 for LAZY flag when re-relocating self. * elf/link.h (struct link_map.l_type): Remove lt_interpreter. (struct link_map): Add new flag member l_global. * elf/dl-reloc.c (_dl_relocate_object): Check for _dl_rtld_map directly instead of looking for lt_interpreter. * sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise. * elf/rtld.c (_dl_start): Don't bother setting BOOTSTRAP_MAP.l_type. (dl_main): Set _dl_rtld_map.l_type to lt_library. * elf/dl-deps.c (_dl_map_object_deps): Propagate MAP->l_type to dependencies loaded, downgrading lt_executable -> lt_library. * elf/dl-load.c (_dl_map_object_from_fd): Take new arg TYPE and set l_type from that, translating lt_library->lt_executable based on the file's ELF type. (_dl_map_object): Likewise. * elf/link.h: Update prototypes. * elf/dl-open.c: Pass type lt_loaded. * elf/rtld.c: Pass type lt_library. * elf/dl-load.c (_dl_map_object_from_fd): Handle null return from _dl_new_object. (_dl_map_object_from_fd: lose): Unchain and free L if it's not null. Free REALNAME, and just use NAME in error message. * elf/dl-object.c (_dl_new_object): If malloc fails, return null instead of calling _dl_signal_error. * elf/dl-load.c (_dl_map_object_from_fd): Close FD before signalling error for _dl_zerofd setup failure. * elf/dl-object.c (_dl_startup_loaded): Variable removed. * elf/link.h: Remove its decl. * elf/dl-reloc.c (_dl_relocate_object): Take new SCOPE arg and pass it through to _dl_lookup_symbol. * elf/link.h (_dl_relocate_object): Update comment and prototype. * elf/rtld.c (dl_main): Pass scope vector to _dl_relocate_object. * elf/dl-lookup.c (_dl_lookup_symbol): Arg SYMBOL_SCOPE is now a null-terminated vector of pointers, no longer a vector of exactly two. * elf/link.h (_dl_lookup_symbol): Update comment and prototype. * elf/dl-runtime.c (fixup): Set up scope for symbol lookup properly as done in _dl_relocate_object. * elf/dlopen.c: Pass "" to _dl_open when FILE is null.
This commit is contained in:
84
ChangeLog
84
ChangeLog
@ -1,5 +1,89 @@
|
|||||||
Mon Jun 10 06:14:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
|
Mon Jun 10 06:14:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* Makerules ($(common-objpfx)libc.so): Depend on $(elfobjdir)/ld.so.
|
||||||
|
|
||||||
|
* elf/dl-close.c: New file.
|
||||||
|
* elf/link.h: Declare _dl_close.
|
||||||
|
* elf/Makefile (routines): Add dl-close.
|
||||||
|
* elf/dlclose.c (dlclose): Use _dl_close.
|
||||||
|
|
||||||
|
* elf/Makefile ($(objpfx)librtld.so): Remove libelf from deps.
|
||||||
|
|
||||||
|
* elf/dl-runtime.c (_dl_global_scope): New variable.
|
||||||
|
(_dl_object_relocation_scope): New function.
|
||||||
|
(fixup): Use it.
|
||||||
|
* elf/rtld.c (dl_main): Use it.
|
||||||
|
* elf/dl-open.c (_dl_open): Use it. If (MODE & RTLD_GLOBAL), set the
|
||||||
|
l_global bit and append the new map to _dl_global_scope.
|
||||||
|
* elf/link.h: Declare _dl_global_scope, _dl_global_scope_alloc,
|
||||||
|
and _dl_object_relocation_scope.
|
||||||
|
|
||||||
|
* elf/link.h (struct link_map): Add l_loader member.
|
||||||
|
Remove _dl_map_object_from_fd decl.
|
||||||
|
* elf/dl-load.c (_dl_map_object): Pass LOADER to ...
|
||||||
|
(_dl_map_object_from_fd): Take new arg LOADER and set l_loader member.
|
||||||
|
(_dl_map_object): Try DT_RPATH from all loaders up the chain.
|
||||||
|
|
||||||
|
* elf/dl-object.c (_dl_loaded): Variable removed.
|
||||||
|
(_dl_default_scope): New variable replaces it.
|
||||||
|
* elf/link.h (_dl_loaded): Remove variable decl; instead define as
|
||||||
|
macro for _dl_default_scope[2].
|
||||||
|
(_dl_default_scope): Declare it.
|
||||||
|
* sysdeps/i386/dl-machine.h (RTLD_START): Use _dl_default_scope[2]
|
||||||
|
instead of _dl_loaded.
|
||||||
|
* sysdeps/m68k/dl-machine.h (RTLD_START): Likewise.
|
||||||
|
* elf/rtld.c (dl_main): Use _dl_default_scope for symbol lookups.
|
||||||
|
|
||||||
|
* elf/dl-reloc.c (_dl_relocate_object): Remove check for _dl_rtld_map.
|
||||||
|
* elf/rtld.c (dl_main): Pass 0 for LAZY flag when re-relocating self.
|
||||||
|
|
||||||
|
* elf/link.h (struct link_map.l_type): Remove lt_interpreter.
|
||||||
|
(struct link_map): Add new flag member l_global.
|
||||||
|
|
||||||
|
* elf/dl-reloc.c (_dl_relocate_object): Check for _dl_rtld_map
|
||||||
|
directly instead of looking for lt_interpreter.
|
||||||
|
* sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise.
|
||||||
|
* elf/rtld.c (_dl_start): Don't bother setting BOOTSTRAP_MAP.l_type.
|
||||||
|
(dl_main): Set _dl_rtld_map.l_type to lt_library.
|
||||||
|
|
||||||
|
* elf/dl-deps.c (_dl_map_object_deps): Propagate MAP->l_type to
|
||||||
|
dependencies loaded, downgrading lt_executable -> lt_library.
|
||||||
|
|
||||||
|
* elf/dl-load.c (_dl_map_object_from_fd): Take new arg TYPE and set
|
||||||
|
l_type from that, translating lt_library->lt_executable based on the
|
||||||
|
file's ELF type.
|
||||||
|
(_dl_map_object): Likewise.
|
||||||
|
* elf/link.h: Update prototypes.
|
||||||
|
* elf/dl-open.c: Pass type lt_loaded.
|
||||||
|
* elf/rtld.c: Pass type lt_library.
|
||||||
|
|
||||||
|
* elf/dl-load.c (_dl_map_object_from_fd): Handle null return from
|
||||||
|
_dl_new_object.
|
||||||
|
(_dl_map_object_from_fd: lose): Unchain and free L if it's not null.
|
||||||
|
Free REALNAME, and just use NAME in error message.
|
||||||
|
* elf/dl-object.c (_dl_new_object): If malloc fails, return null
|
||||||
|
instead of calling _dl_signal_error.
|
||||||
|
|
||||||
|
* elf/dl-load.c (_dl_map_object_from_fd): Close FD before signalling
|
||||||
|
error for _dl_zerofd setup failure.
|
||||||
|
|
||||||
|
* elf/dl-object.c (_dl_startup_loaded): Variable removed.
|
||||||
|
* elf/link.h: Remove its decl.
|
||||||
|
|
||||||
|
* elf/dl-reloc.c (_dl_relocate_object): Take new SCOPE arg and pass it
|
||||||
|
through to _dl_lookup_symbol.
|
||||||
|
* elf/link.h (_dl_relocate_object): Update comment and prototype.
|
||||||
|
* elf/rtld.c (dl_main): Pass scope vector to _dl_relocate_object.
|
||||||
|
|
||||||
|
* elf/dl-lookup.c (_dl_lookup_symbol): Arg SYMBOL_SCOPE is now a
|
||||||
|
null-terminated vector of pointers, no longer a vector of exactly two.
|
||||||
|
* elf/link.h (_dl_lookup_symbol): Update comment and prototype.
|
||||||
|
|
||||||
|
* elf/dl-runtime.c (fixup): Set up scope for symbol lookup properly as
|
||||||
|
done in _dl_relocate_object.
|
||||||
|
|
||||||
|
* elf/dlopen.c: Pass "" to _dl_open when FILE is null.
|
||||||
|
|
||||||
* elf/link.h: Include elfclass.h to define __ELF_NATIVE_CLASS.
|
* elf/link.h: Include elfclass.h to define __ELF_NATIVE_CLASS.
|
||||||
(ElfW, ELFW): Use it.
|
(ElfW, ELFW): Use it.
|
||||||
* elf/Makefile (headers): Add elfclass.h.
|
* elf/Makefile (headers): Add elfclass.h.
|
||||||
|
@ -496,7 +496,7 @@ LDFLAGS-c.so += -e __libc_print_version
|
|||||||
elfobjdir := $(firstword $(objdir) $(..)elf)
|
elfobjdir := $(firstword $(objdir) $(..)elf)
|
||||||
$(common-objpfx)libc.so: $(elfobjdir)/soinit.so \
|
$(common-objpfx)libc.so: $(elfobjdir)/soinit.so \
|
||||||
$(common-objpfx)libc_pic.a \
|
$(common-objpfx)libc_pic.a \
|
||||||
$(elfobjdir)/sofini.so
|
$(elfobjdir)/sofini.so $(elfobjdir)/ld.so
|
||||||
$(build-shlib)
|
$(build-shlib)
|
||||||
|
|
||||||
ifdef libc.so-version
|
ifdef libc.so-version
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
subdir := elf
|
subdir := elf
|
||||||
|
|
||||||
headers = elf.h elfclass.h link.h dlfcn.h
|
headers = elf.h elfclass.h link.h dlfcn.h
|
||||||
routines = init-first $(dl-routines) dl-open dl-symbol dl-support
|
routines = init-first $(dl-routines) \
|
||||||
|
dl-open dl-close dl-symbol dl-support
|
||||||
|
|
||||||
# The core dynamic linking functions are in libc for the static and
|
# The core dynamic linking functions are in libc for the static and
|
||||||
# profiled libraries.
|
# profiled libraries.
|
||||||
@ -54,7 +55,7 @@ install-bin = ldd
|
|||||||
# to run programs during the `make others' pass.
|
# to run programs during the `make others' pass.
|
||||||
lib-noranlib: $(objpfx)ld.so $(addprefix $(objpfx),$(extra-objs))
|
lib-noranlib: $(objpfx)ld.so $(addprefix $(objpfx),$(extra-objs))
|
||||||
|
|
||||||
ifneq (,$(filter linux%,$(config-os)))
|
ifneq (,$(filter linux% linux,$(config-os)))
|
||||||
extra-objs += linux-compat.so
|
extra-objs += linux-compat.so
|
||||||
install-others += $(slibdir)/ld-linux.so.1
|
install-others += $(slibdir)/ld-linux.so.1
|
||||||
lib-noranlib: $(objpfx)ld-linux.so.1
|
lib-noranlib: $(objpfx)ld-linux.so.1
|
||||||
@ -75,7 +76,7 @@ $(objpfx)dl-allobjs.so: $(rtld-routines:%=$(objpfx)%.so)
|
|||||||
# dynamic linker shared objects below.
|
# dynamic linker shared objects below.
|
||||||
$(objpfx)librtld.so: $(objpfx)dl-allobjs.so \
|
$(objpfx)librtld.so: $(objpfx)dl-allobjs.so \
|
||||||
$(patsubst %,$(common-objpfx)lib%_pic.a,\
|
$(patsubst %,$(common-objpfx)lib%_pic.a,\
|
||||||
elf c $(LDLIBS-c.so:-l%=%))
|
c $(LDLIBS-c.so:-l%=%))
|
||||||
$(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)'
|
$(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)'
|
||||||
|
|
||||||
$(objpfx)ld.so: $(objpfx)librtld.so
|
$(objpfx)ld.so: $(objpfx)librtld.so
|
||||||
|
107
elf/dl-close.c
Normal file
107
elf/dl-close.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/* _dl_close -- Close a shared object opened by `_dl_open'.
|
||||||
|
Copyright (C) 1996 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
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||||
|
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||||
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
#include <link.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
||||||
|
|
||||||
|
void
|
||||||
|
_dl_close (struct link_map *map)
|
||||||
|
{
|
||||||
|
struct link_map **list;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (map->l_opencount == 0)
|
||||||
|
LOSE ("shared object not open");
|
||||||
|
|
||||||
|
/* Decrement the reference count. */
|
||||||
|
if (--map->l_opencount > 0 || map->l_type != lt_loaded)
|
||||||
|
/* There are still references to this object. Do nothing more. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
list = map->l_searchlist;
|
||||||
|
|
||||||
|
/* The search list contains a counted reference to each object it
|
||||||
|
points to, the 0th elt being MAP itself. Decrement the reference
|
||||||
|
counts on all the objects MAP depends on. */
|
||||||
|
for (i = 1; i < map->l_nsearchlist; ++i)
|
||||||
|
--list[i]->l_opencount;
|
||||||
|
|
||||||
|
/* Clear the search list so it doesn't get freed while we are still
|
||||||
|
using it. We have cached it in LIST and will free it when
|
||||||
|
finished. */
|
||||||
|
map->l_searchlist = NULL;
|
||||||
|
|
||||||
|
/* Check each element of the search list to see if all references to
|
||||||
|
it are gone. */
|
||||||
|
for (i = 0; i < map->l_nsearchlist; ++i)
|
||||||
|
{
|
||||||
|
struct link_map *map = list[i];
|
||||||
|
if (map->l_opencount == 0 && map->l_type == lt_loaded)
|
||||||
|
{
|
||||||
|
/* That was the last reference, and this was a dlopen-loaded
|
||||||
|
object. We can unmap it. */
|
||||||
|
const ElfW(Phdr) *ph;
|
||||||
|
|
||||||
|
if (map->l_info[DT_FINI])
|
||||||
|
/* Call its termination function. */
|
||||||
|
(*(void (*) (void)) ((void *) map->l_addr +
|
||||||
|
map->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||||
|
|
||||||
|
if (map->l_global)
|
||||||
|
{
|
||||||
|
/* This object is in the global scope list. Remove it. */
|
||||||
|
struct link_map **tail = _dl_global_scope_end;
|
||||||
|
do
|
||||||
|
--tail;
|
||||||
|
while (*tail != map);
|
||||||
|
--_dl_global_scope_end;
|
||||||
|
memcpy (tail, tail + 1, _dl_global_scope_end - tail);
|
||||||
|
_dl_global_scope_end[0] = NULL;
|
||||||
|
_dl_global_scope_end[1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmap the segments. */
|
||||||
|
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||||
|
if (ph->p_type == PT_LOAD)
|
||||||
|
{
|
||||||
|
ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||||
|
ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz
|
||||||
|
+ ph->p_align - 1)
|
||||||
|
& ~(ph->p_align - 1));
|
||||||
|
__munmap ((caddr_t) mapstart, mapend - mapstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, unlink the data structure and free it. */
|
||||||
|
map->l_prev->l_next = map->l_next;
|
||||||
|
if (map->l_next)
|
||||||
|
map->l_next->l_prev = map->l_prev;
|
||||||
|
if (map->l_searchlist)
|
||||||
|
free (map->l_searchlist);
|
||||||
|
free (map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free (list);
|
||||||
|
}
|
@ -62,7 +62,9 @@ _dl_map_object_deps (struct link_map *map)
|
|||||||
{
|
{
|
||||||
/* Map in the needed object. */
|
/* Map in the needed object. */
|
||||||
struct link_map *dep
|
struct link_map *dep
|
||||||
= _dl_map_object (l, strtab + d->d_un.d_val);
|
= _dl_map_object (l, strtab + d->d_un.d_val,
|
||||||
|
l->l_type == lt_executable ? lt_library :
|
||||||
|
l->l_type);
|
||||||
|
|
||||||
if (dep->l_reserved)
|
if (dep->l_reserved)
|
||||||
/* This object is already in the search list we are
|
/* This object is already in the search list we are
|
||||||
|
312
elf/dl-load.c
312
elf/dl-load.c
@ -63,152 +63,14 @@ int _dl_zerofd = -1;
|
|||||||
size_t _dl_pagesize;
|
size_t _dl_pagesize;
|
||||||
|
|
||||||
|
|
||||||
/* Try to open NAME in one of the directories in DIRPATH.
|
|
||||||
Return the fd, or -1. If successful, fill in *REALNAME
|
|
||||||
with the malloc'd full directory name. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
open_path (const char *name, size_t namelen,
|
|
||||||
const char *dirpath,
|
|
||||||
char **realname)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
const char *p;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
p = dirpath;
|
|
||||||
if (p == NULL || *p == '\0')
|
|
||||||
{
|
|
||||||
errno = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = __alloca (strlen (dirpath) + 1 + namelen);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
size_t buflen;
|
|
||||||
|
|
||||||
dirpath = p;
|
|
||||||
p = strpbrk (dirpath, ":;");
|
|
||||||
if (p == NULL)
|
|
||||||
p = strchr (dirpath, '\0');
|
|
||||||
|
|
||||||
if (p == dirpath)
|
|
||||||
{
|
|
||||||
/* Two adjacent colons, or a colon at the beginning or the end of
|
|
||||||
the path means to search the current directory. */
|
|
||||||
(void) memcpy (buf, name, namelen);
|
|
||||||
buflen = namelen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Construct the pathname to try. */
|
|
||||||
(void) memcpy (buf, dirpath, p - dirpath);
|
|
||||||
buf[p - dirpath] = '/';
|
|
||||||
(void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
|
|
||||||
buflen = p - dirpath + 1 + namelen;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = __open (buf, O_RDONLY);
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
|
||||||
*realname = malloc (buflen);
|
|
||||||
if (*realname)
|
|
||||||
{
|
|
||||||
memcpy (*realname, buf, buflen);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No memory for the name, we certainly won't be able
|
|
||||||
to load and link it. */
|
|
||||||
__close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (errno != ENOENT && errno != EACCES)
|
|
||||||
/* The file exists and is readable, but something went wrong. */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while (*p++ != '\0');
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map in the shared object file NAME. */
|
|
||||||
|
|
||||||
struct link_map *
|
|
||||||
_dl_map_object (struct link_map *loader, const char *name)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
char *realname;
|
|
||||||
struct link_map *l;
|
|
||||||
|
|
||||||
/* Look for this name among those already loaded. */
|
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
|
||||||
if (! strcmp (name, l->l_libname))
|
|
||||||
{
|
|
||||||
/* The object is already loaded.
|
|
||||||
Just bump its reference count and return it. */
|
|
||||||
++l->l_opencount;
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strchr (name, '/') == NULL)
|
|
||||||
{
|
|
||||||
/* Search for NAME in several places. */
|
|
||||||
|
|
||||||
size_t namelen = strlen (name) + 1;
|
|
||||||
|
|
||||||
inline void trypath (const char *dirpath)
|
|
||||||
{
|
|
||||||
fd = open_path (name, namelen, dirpath, &realname);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = -1;
|
|
||||||
if (loader && loader->l_info[DT_RPATH])
|
|
||||||
trypath ((const char *) (loader->l_addr +
|
|
||||||
loader->l_info[DT_STRTAB]->d_un.d_ptr +
|
|
||||||
loader->l_info[DT_RPATH]->d_un.d_val));
|
|
||||||
if (fd == -1 && ! _dl_secure)
|
|
||||||
trypath (getenv ("LD_LIBRARY_PATH"));
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
extern const char *_dl_rpath; /* Set in rtld.c. */
|
|
||||||
trypath (_dl_rpath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fd = __open (name, O_RDONLY);
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
|
||||||
size_t len = strlen (name) + 1;
|
|
||||||
realname = malloc (len);
|
|
||||||
if (realname)
|
|
||||||
memcpy (realname, name, len);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__close (fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1)
|
|
||||||
_dl_signal_error (errno, name, "cannot open shared object file");
|
|
||||||
|
|
||||||
return _dl_map_object_from_fd (name, fd, realname);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||||
opened on FD. */
|
opened on FD. */
|
||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
_dl_map_object_from_fd (const char *name, int fd, char *realname)
|
_dl_map_object_from_fd (const char *name, int fd, char *realname,
|
||||||
|
struct link_map *loader, int l_type)
|
||||||
{
|
{
|
||||||
struct link_map *l = NULL;
|
struct link_map *l;
|
||||||
void *file_mapping = NULL;
|
void *file_mapping = NULL;
|
||||||
size_t mapping_size = 0;
|
size_t mapping_size = 0;
|
||||||
|
|
||||||
@ -218,7 +80,17 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
(void) __close (fd);
|
(void) __close (fd);
|
||||||
if (file_mapping)
|
if (file_mapping)
|
||||||
__munmap (file_mapping, mapping_size);
|
__munmap (file_mapping, mapping_size);
|
||||||
_dl_signal_error (code, l ? l->l_name : name, msg);
|
if (l)
|
||||||
|
{
|
||||||
|
/* Remove the stillborn object from the list and free it. */
|
||||||
|
if (l->l_prev)
|
||||||
|
l->l_prev->l_next = l->l_next;
|
||||||
|
if (l->l_next)
|
||||||
|
l->l_next->l_prev = l->l_prev;
|
||||||
|
free (l);
|
||||||
|
}
|
||||||
|
free (realname);
|
||||||
|
_dl_signal_error (code, name, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
|
inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len,
|
||||||
@ -304,16 +176,22 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
if (header->e_phentsize != sizeof (ElfW(Phdr)))
|
if (header->e_phentsize != sizeof (ElfW(Phdr)))
|
||||||
LOSE ("ELF file's phentsize not the expected size");
|
LOSE ("ELF file's phentsize not the expected size");
|
||||||
|
|
||||||
/* Enter the new object in the list of loaded objects. */
|
|
||||||
l = _dl_new_object (realname, name, lt_loaded);
|
|
||||||
l->l_opencount = 1;
|
|
||||||
|
|
||||||
if (_dl_zerofd == -1)
|
if (_dl_zerofd == -1)
|
||||||
{
|
{
|
||||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||||
if (_dl_zerofd == -1)
|
if (_dl_zerofd == -1)
|
||||||
|
{
|
||||||
|
__close (fd);
|
||||||
_dl_signal_error (errno, NULL, "cannot open zero fill device");
|
_dl_signal_error (errno, NULL, "cannot open zero fill device");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter the new object in the list of loaded objects. */
|
||||||
|
l = _dl_new_object (realname, name, l_type);
|
||||||
|
if (! l)
|
||||||
|
lose (ENOMEM, "cannot create shared object descriptor");
|
||||||
|
l->l_opencount = 1;
|
||||||
|
l->l_loader = loader;
|
||||||
|
|
||||||
/* Extract the remaining details we need from the ELF header
|
/* Extract the remaining details we need from the ELF header
|
||||||
and then map in the program header table. */
|
and then map in the program header table. */
|
||||||
@ -464,7 +342,8 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
/* We are done mapping in the file. We no longer need the descriptor. */
|
/* We are done mapping in the file. We no longer need the descriptor. */
|
||||||
__close (fd);
|
__close (fd);
|
||||||
|
|
||||||
l->l_type = type == ET_EXEC ? lt_executable : lt_library;
|
if (l->l_type == lt_library && type == ET_EXEC)
|
||||||
|
l->l_type = lt_executable;
|
||||||
|
|
||||||
if (l->l_ld == 0)
|
if (l->l_ld == 0)
|
||||||
{
|
{
|
||||||
@ -484,3 +363,142 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to open NAME in one of the directories in DIRPATH.
|
||||||
|
Return the fd, or -1. If successful, fill in *REALNAME
|
||||||
|
with the malloc'd full directory name. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_path (const char *name, size_t namelen,
|
||||||
|
const char *dirpath,
|
||||||
|
char **realname)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
const char *p;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
p = dirpath;
|
||||||
|
if (p == NULL || *p == '\0')
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = __alloca (strlen (dirpath) + 1 + namelen);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t buflen;
|
||||||
|
|
||||||
|
dirpath = p;
|
||||||
|
p = strpbrk (dirpath, ":;");
|
||||||
|
if (p == NULL)
|
||||||
|
p = strchr (dirpath, '\0');
|
||||||
|
|
||||||
|
if (p == dirpath)
|
||||||
|
{
|
||||||
|
/* Two adjacent colons, or a colon at the beginning or the end of
|
||||||
|
the path means to search the current directory. */
|
||||||
|
(void) memcpy (buf, name, namelen);
|
||||||
|
buflen = namelen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Construct the pathname to try. */
|
||||||
|
(void) memcpy (buf, dirpath, p - dirpath);
|
||||||
|
buf[p - dirpath] = '/';
|
||||||
|
(void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
|
||||||
|
buflen = p - dirpath + 1 + namelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = __open (buf, O_RDONLY);
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
*realname = malloc (buflen);
|
||||||
|
if (*realname)
|
||||||
|
{
|
||||||
|
memcpy (*realname, buf, buflen);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No memory for the name, we certainly won't be able
|
||||||
|
to load and link it. */
|
||||||
|
__close (fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errno != ENOENT && errno != EACCES)
|
||||||
|
/* The file exists and is readable, but something went wrong. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while (*p++ != '\0');
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map in the shared object file NAME. */
|
||||||
|
|
||||||
|
struct link_map *
|
||||||
|
_dl_map_object (struct link_map *loader, const char *name, int type)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char *realname;
|
||||||
|
struct link_map *l;
|
||||||
|
|
||||||
|
/* Look for this name among those already loaded. */
|
||||||
|
for (l = _dl_loaded; l; l = l->l_next)
|
||||||
|
if (! strcmp (name, l->l_libname))
|
||||||
|
{
|
||||||
|
/* The object is already loaded.
|
||||||
|
Just bump its reference count and return it. */
|
||||||
|
++l->l_opencount;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr (name, '/') == NULL)
|
||||||
|
{
|
||||||
|
/* Search for NAME in several places. */
|
||||||
|
|
||||||
|
size_t namelen = strlen (name) + 1;
|
||||||
|
|
||||||
|
inline void trypath (const char *dirpath)
|
||||||
|
{
|
||||||
|
fd = open_path (name, namelen, dirpath, &realname);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = -1;
|
||||||
|
for (l = loader; l; l = l->l_loader)
|
||||||
|
if (l && l->l_info[DT_RPATH])
|
||||||
|
trypath ((const char *) (l->l_addr +
|
||||||
|
l->l_info[DT_STRTAB]->d_un.d_ptr +
|
||||||
|
l->l_info[DT_RPATH]->d_un.d_val));
|
||||||
|
if (fd == -1 && ! _dl_secure)
|
||||||
|
trypath (getenv ("LD_LIBRARY_PATH"));
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
extern const char *_dl_rpath; /* Set in rtld.c. */
|
||||||
|
trypath (_dl_rpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd = __open (name, O_RDONLY);
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
size_t len = strlen (name) + 1;
|
||||||
|
realname = malloc (len);
|
||||||
|
if (realname)
|
||||||
|
memcpy (realname, name, len);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__close (fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
_dl_signal_error (errno, name, "cannot open shared object file");
|
||||||
|
|
||||||
|
return _dl_map_object_from_fd (name, fd, realname, loader, type);
|
||||||
|
}
|
||||||
|
@ -50,7 +50,7 @@ _dl_elf_hash (const char *name)
|
|||||||
|
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
struct link_map *symbol_scope[2],
|
struct link_map *symbol_scope[],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
ElfW(Addr) reloc_addr,
|
ElfW(Addr) reloc_addr,
|
||||||
int noplt)
|
int noplt)
|
||||||
@ -65,8 +65,7 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
|||||||
struct link_map **scope, *map;
|
struct link_map **scope, *map;
|
||||||
|
|
||||||
/* Search the relevant loaded objects for a definition. */
|
/* Search the relevant loaded objects for a definition. */
|
||||||
for (scope = symbol_scope; scope < &symbol_scope[2]; ++scope)
|
for (scope = symbol_scope; *scope; ++scope)
|
||||||
if (*scope)
|
|
||||||
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
|
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
|
||||||
{
|
{
|
||||||
const ElfW(Sym) *symtab;
|
const ElfW(Sym) *symtab;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Storage management for the chain of loaded shared objects.
|
/* Storage management for the chain of loaded shared objects.
|
||||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996 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,11 +24,8 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
/* List of objects currently loaded. */
|
/* List of objects currently loaded is [2] of this, aka _dl_loaded. */
|
||||||
struct link_map *_dl_loaded;
|
struct link_map *_dl_default_scope[5];
|
||||||
|
|
||||||
/* Tail of that list which were loaded at startup. */
|
|
||||||
struct link_map *_dl_startup_loaded;
|
|
||||||
|
|
||||||
/* Allocate a `struct link_map' for a new object being loaded,
|
/* Allocate a `struct link_map' for a new object being loaded,
|
||||||
and enter it into the _dl_loaded list. */
|
and enter it into the _dl_loaded list. */
|
||||||
@ -38,8 +35,7 @@ _dl_new_object (char *realname, const char *libname, int type)
|
|||||||
{
|
{
|
||||||
struct link_map *new = malloc (sizeof *new);
|
struct link_map *new = malloc (sizeof *new);
|
||||||
if (! new)
|
if (! new)
|
||||||
_dl_signal_error (ENOMEM, libname,
|
return NULL;
|
||||||
"cannot allocate shared object descriptor");
|
|
||||||
|
|
||||||
memset (new, 0, sizeof *new);
|
memset (new, 0, sizeof *new);
|
||||||
new->l_name = realname;
|
new->l_name = realname;
|
||||||
|
@ -19,6 +19,10 @@ Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
size_t _dl_global_scope_alloc;
|
||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
_dl_open (struct link_map *parent, const char *file, int mode)
|
_dl_open (struct link_map *parent, const char *file, int mode)
|
||||||
@ -26,16 +30,83 @@ _dl_open (struct link_map *parent, const char *file, int mode)
|
|||||||
struct link_map *new, *l;
|
struct link_map *new, *l;
|
||||||
ElfW(Addr) init;
|
ElfW(Addr) init;
|
||||||
|
|
||||||
|
|
||||||
/* Load the named object. */
|
/* Load the named object. */
|
||||||
new = _dl_map_object (parent, file);
|
new = _dl_map_object (parent, file, lt_loaded);
|
||||||
|
if (new->l_searchlist)
|
||||||
|
/* It was already open. */
|
||||||
|
return new;
|
||||||
|
|
||||||
/* Load that object's dependencies. */
|
/* Load that object's dependencies. */
|
||||||
_dl_map_object_deps (new);
|
_dl_map_object_deps (new);
|
||||||
|
|
||||||
/* Relocate the objects loaded. */
|
|
||||||
for (l = new; l; l = l->l_next)
|
/* Relocate the objects loaded. We do this in reverse order so that copy
|
||||||
|
relocs of earlier objects overwrite the data written by later objects. */
|
||||||
|
|
||||||
|
l = new;
|
||||||
|
while (l->l_next)
|
||||||
|
l = l->l_next;
|
||||||
|
do
|
||||||
|
{
|
||||||
if (! l->l_relocated)
|
if (! l->l_relocated)
|
||||||
_dl_relocate_object (l, (mode & RTLD_BINDING_MASK) == RTLD_LAZY);
|
{
|
||||||
|
_dl_relocate_object (l, _dl_object_relocation_scope (l),
|
||||||
|
(mode & RTLD_BINDING_MASK) == RTLD_LAZY);
|
||||||
|
*_dl_global_scope_end = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = l->l_prev;
|
||||||
|
} while (l != new);
|
||||||
|
|
||||||
|
new->l_global = (mode & RTLD_GLOBAL);
|
||||||
|
if (new->l_global)
|
||||||
|
{
|
||||||
|
/* The symbols of the new object and its dependencies are to be
|
||||||
|
introduced into the global scope that will be used to resolve
|
||||||
|
references from other dynamically-loaded objects. */
|
||||||
|
|
||||||
|
if (_dl_global_scope_alloc == 0)
|
||||||
|
{
|
||||||
|
/* This is the first dynamic object given global scope. */
|
||||||
|
_dl_global_scope_alloc = 8;
|
||||||
|
_dl_global_scope = malloc (8 * sizeof (struct link_map *));
|
||||||
|
if (! _dl_global_scope)
|
||||||
|
{
|
||||||
|
_dl_global_scope = _dl_default_scope;
|
||||||
|
nomem:
|
||||||
|
_dl_close (new);
|
||||||
|
_dl_signal_error (ENOMEM, file, "cannot extend global scope");
|
||||||
|
}
|
||||||
|
_dl_global_scope[2] = _dl_default_scope[2];
|
||||||
|
_dl_global_scope[3] = new;
|
||||||
|
_dl_global_scope[4] = NULL;
|
||||||
|
_dl_global_scope[5] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_dl_global_scope_alloc <
|
||||||
|
_dl_global_scope_end - _dl_global_scope + 2)
|
||||||
|
{
|
||||||
|
/* Must extend the list. */
|
||||||
|
struct link_map **new = realloc (_dl_global_scope,
|
||||||
|
_dl_global_scope_alloc * 2);
|
||||||
|
if (! new)
|
||||||
|
goto nomem;
|
||||||
|
_dl_global_scope_end = new + (_dl_global_scope_end -
|
||||||
|
_dl_global_scope);
|
||||||
|
_dl_global_scope = new;
|
||||||
|
_dl_global_scope_alloc *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the new object and re-terminate the list. */
|
||||||
|
*_dl_global_scope_end++ = new;
|
||||||
|
/* We keep the list double-terminated so the last element
|
||||||
|
can be filled in for symbol lookups. */
|
||||||
|
_dl_global_scope_end[0] = NULL;
|
||||||
|
_dl_global_scope_end[1] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Run the initializer functions of new objects. */
|
/* Run the initializer functions of new objects. */
|
||||||
while (init = _dl_init_next (new))
|
while (init = _dl_init_next (new))
|
||||||
|
@ -26,7 +26,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_dl_relocate_object (struct link_map *l, int lazy)
|
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
|
||||||
{
|
{
|
||||||
if (l->l_relocated)
|
if (l->l_relocated)
|
||||||
return;
|
return;
|
||||||
@ -52,44 +52,26 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct link_map *scope[2];
|
/* Do the actual relocation of the object's GOT and other data. */
|
||||||
|
|
||||||
const char *strtab
|
const char *strtab /* String table object symbols. */
|
||||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
|
|
||||||
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||||
ElfW(Addr) reloc_addr, int noplt)
|
ElfW(Addr) reloc_addr, int noplt)
|
||||||
{
|
{
|
||||||
|
/* Look up the referenced symbol in the specified scope. */
|
||||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
||||||
l->l_name, reloc_addr, noplt);
|
l->l_name, reloc_addr, noplt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->l_info[DT_SYMBOLIC])
|
|
||||||
{
|
|
||||||
scope[0] = l;
|
|
||||||
scope[1] = _dl_loaded;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scope[0] = _dl_loaded;
|
|
||||||
scope[1] = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l->l_type == lt_interpreter)
|
|
||||||
/* We cannot be lazy when relocating the dynamic linker itself. It
|
|
||||||
was previously relocated eagerly (allowing us to be running now),
|
|
||||||
and needs always to be fully relocated so it can run without the
|
|
||||||
aid of run-time fixups (because it's the one to do them), so we
|
|
||||||
must always re-relocate its PLT eagerly. */
|
|
||||||
lazy = 0;
|
|
||||||
|
|
||||||
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
|
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the PLT so its unrelocated entries will
|
/* Set up the PLT so its unrelocated entries will jump to
|
||||||
jump to _dl_runtime_resolve, which will relocate them. */
|
_dl_runtime_resolve (dl-runtime.c), which will relocate them. */
|
||||||
elf_machine_runtime_setup (l, lazy);
|
elf_machine_runtime_setup (l, lazy);
|
||||||
|
|
||||||
|
/* Mark the object so we know ths work has been done. */
|
||||||
l->l_relocated = 1;
|
l->l_relocated = 1;
|
||||||
|
|
||||||
if (l->l_info[DT_TEXTREL])
|
if (l->l_info[DT_TEXTREL])
|
||||||
@ -114,5 +96,4 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
"can't restore segment prot after reloc");
|
"can't restore segment prot after reloc");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,54 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* The global scope we will use for symbol lookups.
|
||||||
|
This will be modified by _dl_open if RTLD_GLOBAL is used. */
|
||||||
|
struct link_map **_dl_global_scope = _dl_default_scope;
|
||||||
|
struct link_map **_dl_global_scope_end = &_dl_default_scope[3];
|
||||||
|
|
||||||
|
|
||||||
|
/* Hack _dl_global_scope[0] and [1] as necessary, and return a pointer into
|
||||||
|
_dl_global_scope that should be passed to _dl_lookup_symbol for symbol
|
||||||
|
references made in the object L's relocations. */
|
||||||
|
inline struct link_map **
|
||||||
|
_dl_object_relocation_scope (struct link_map *l)
|
||||||
|
{
|
||||||
|
if (l->l_info[DT_SYMBOLIC])
|
||||||
|
{
|
||||||
|
/* This object's global references are to be resolved first
|
||||||
|
in the object itself, and only secondarily in more global
|
||||||
|
scopes. */
|
||||||
|
|
||||||
|
if (! l->l_searchlist)
|
||||||
|
/* We must construct the searchlist for this object. */
|
||||||
|
_dl_map_object_deps (l);
|
||||||
|
|
||||||
|
/* The primary scope is this object itself and its
|
||||||
|
dependencies. */
|
||||||
|
_dl_global_scope[0] = l;
|
||||||
|
|
||||||
|
/* Secondary is the dependency tree that reached L; the object
|
||||||
|
requested directly by the user is at the root of that tree. */
|
||||||
|
while (l->l_loader)
|
||||||
|
l = l->l_loader;
|
||||||
|
_dl_global_scope[1] = l;
|
||||||
|
|
||||||
|
/* Finally, the global scope follows. */
|
||||||
|
|
||||||
|
return _dl_global_scope;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use first the global scope, and then the scope of the root of the
|
||||||
|
dependency tree that first caused this object to be loaded. */
|
||||||
|
while (l->l_loader)
|
||||||
|
l = l->l_loader;
|
||||||
|
*_dl_global_scope_end = l;
|
||||||
|
return &_dl_global_scope[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Figure out the right type, Rel or Rela. */
|
/* Figure out the right type, Rel or Rela. */
|
||||||
#define elf_machine_rel 1
|
#define elf_machine_rel 1
|
||||||
#define elf_machine_rela 2
|
#define elf_machine_rela 2
|
||||||
@ -67,17 +115,21 @@ fixup (
|
|||||||
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
||||||
reloc_offset);
|
reloc_offset);
|
||||||
|
|
||||||
|
/* Set up the scope to find symbols referenced by this object. */
|
||||||
|
struct link_map **scope = _dl_object_relocation_scope (l);
|
||||||
|
|
||||||
|
/* Perform the specified relocation. */
|
||||||
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||||
ElfW(Addr) reloc_addr, int noplt)
|
ElfW(Addr) reloc_addr, int noplt)
|
||||||
{
|
{
|
||||||
struct link_map *scope[2] = { _dl_loaded, NULL };
|
|
||||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
|
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
|
||||||
scope, l->l_name, reloc_addr, noplt);
|
scope, l->l_name, reloc_addr, noplt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the specified relocation. */
|
|
||||||
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve);
|
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve);
|
||||||
|
|
||||||
|
*_dl_global_scope_end = NULL;
|
||||||
|
|
||||||
|
/* Return the address that was written by the relocation. */
|
||||||
return *(ElfW(Addr) *) (l->l_addr + reloc->r_offset);
|
return *(ElfW(Addr) *) (l->l_addr + reloc->r_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,81 +19,13 @@ Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dlclose (void *handle)
|
dlclose (void *handle)
|
||||||
{
|
{
|
||||||
void doit (void)
|
void doit (void)
|
||||||
{
|
{
|
||||||
struct link_map *map = handle;
|
_dl_close (handle);
|
||||||
struct link_map **list;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (map->l_opencount == 0)
|
|
||||||
LOSE ("shared object not open");
|
|
||||||
|
|
||||||
/* Decrement the reference count. */
|
|
||||||
if (--map->l_opencount > 0 || map->l_type != lt_loaded)
|
|
||||||
/* There are still references to this object. Do nothing more. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
list = map->l_searchlist;
|
|
||||||
|
|
||||||
/* The search list contains a counted reference to each object it
|
|
||||||
points to, the 0th elt being MAP itself. Decrement the reference
|
|
||||||
counts on all the objects MAP depends on. */
|
|
||||||
for (i = 1; i < map->l_nsearchlist; ++i)
|
|
||||||
--list[i]->l_opencount;
|
|
||||||
|
|
||||||
/* Clear the search list so it doesn't get freed while we are still
|
|
||||||
using it. We have cached it in LIST and will free it when
|
|
||||||
finished. */
|
|
||||||
map->l_searchlist = NULL;
|
|
||||||
|
|
||||||
/* Check each element of the search list to see if all references to
|
|
||||||
it are gone. */
|
|
||||||
for (i = 0; i < map->l_nsearchlist; ++i)
|
|
||||||
{
|
|
||||||
struct link_map *map = list[i];
|
|
||||||
if (map->l_opencount == 0 && map->l_type == lt_loaded)
|
|
||||||
{
|
|
||||||
/* That was the last reference, and this was a dlopen-loaded
|
|
||||||
object. We can unmap it. */
|
|
||||||
const ElfW(Phdr) *ph;
|
|
||||||
|
|
||||||
if (map->l_info[DT_FINI])
|
|
||||||
/* Call its termination function. */
|
|
||||||
(*(void (*) (void)) ((void *) map->l_addr +
|
|
||||||
map->l_info[DT_FINI]->d_un.d_ptr)) ();
|
|
||||||
|
|
||||||
/* Unmap the segments. */
|
|
||||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
|
||||||
if (ph->p_type == PT_LOAD)
|
|
||||||
{
|
|
||||||
ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
|
||||||
ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz
|
|
||||||
+ ph->p_align - 1)
|
|
||||||
& ~(ph->p_align - 1));
|
|
||||||
munmap ((caddr_t) mapstart, mapend - mapstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, unlink the data structure and free it. */
|
|
||||||
map->l_prev->l_next = map->l_next;
|
|
||||||
if (map->l_next)
|
|
||||||
map->l_next->l_prev = map->l_prev;
|
|
||||||
if (map->l_searchlist)
|
|
||||||
free (map->l_searchlist);
|
|
||||||
free (map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free (list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _dlerror_run (doit) ? -1 : 0;
|
return _dlerror_run (doit) ? -1 : 0;
|
||||||
|
@ -28,7 +28,7 @@ dlopen (const char *file, int mode)
|
|||||||
|
|
||||||
void doit (void)
|
void doit (void)
|
||||||
{
|
{
|
||||||
new = _dl_open (_dl_loaded, file, mode);
|
new = _dl_open (_dl_loaded, file ?: "", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _dlerror_run (doit) ? NULL : new;
|
return _dlerror_run (doit) ? NULL : new;
|
||||||
|
68
elf/link.h
68
elf/link.h
@ -106,6 +106,9 @@ struct link_map
|
|||||||
struct link_map **l_searchlist;
|
struct link_map **l_searchlist;
|
||||||
unsigned int l_nsearchlist;
|
unsigned int l_nsearchlist;
|
||||||
|
|
||||||
|
/* Dependent object that first caused this object to be loaded. */
|
||||||
|
struct link_map *l_loader;
|
||||||
|
|
||||||
/* Symbol hash table. */
|
/* Symbol hash table. */
|
||||||
ElfW(Word) l_nbuckets;
|
ElfW(Word) l_nbuckets;
|
||||||
const ElfW(Word) *l_buckets, *l_chain;
|
const ElfW(Word) *l_buckets, *l_chain;
|
||||||
@ -114,14 +117,14 @@ struct link_map
|
|||||||
enum /* Where this object came from. */
|
enum /* Where this object came from. */
|
||||||
{
|
{
|
||||||
lt_executable, /* The main executable program. */
|
lt_executable, /* The main executable program. */
|
||||||
lt_interpreter, /* The interpreter: the dynamic linker. */
|
|
||||||
lt_library, /* Library needed by main executable. */
|
lt_library, /* Library needed by main executable. */
|
||||||
lt_loaded, /* Extra run-time loaded shared object. */
|
lt_loaded, /* Extra run-time loaded shared object. */
|
||||||
} l_type:2;
|
} l_type:2;
|
||||||
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
|
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
|
||||||
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
|
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
|
||||||
unsigned int l_init_running:1; /* Nonzero while DT_INIT function runs. */
|
unsigned int l_init_running:1; /* Nonzero while DT_INIT function runs. */
|
||||||
unsigned int l_reserved:3; /* Reserved for internal use. */
|
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
|
||||||
|
unsigned int l_reserved:2; /* Reserved for internal use. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal functions of the run-time dynamic linker.
|
/* Internal functions of the run-time dynamic linker.
|
||||||
@ -188,12 +191,7 @@ extern int _dlerror_run (void (*operate) (void));
|
|||||||
LOADER's DT_RPATH is used in searching for NAME.
|
LOADER's DT_RPATH is used in searching for NAME.
|
||||||
If the object is already opened, returns its existing map. */
|
If the object is already opened, returns its existing map. */
|
||||||
extern struct link_map *_dl_map_object (struct link_map *loader,
|
extern struct link_map *_dl_map_object (struct link_map *loader,
|
||||||
const char *name);
|
const char *name, int type);
|
||||||
|
|
||||||
/* Similar, but file found at REALNAME and opened on FD.
|
|
||||||
REALNAME must malloc'd storage and is used in internal data structures. */
|
|
||||||
extern struct link_map *_dl_map_object_from_fd (const char *name,
|
|
||||||
int fd, char *realname);
|
|
||||||
|
|
||||||
/* Call _dl_map_object on the dependencies of MAP, and
|
/* Call _dl_map_object on the dependencies of MAP, and
|
||||||
set up MAP->l_searchlist. */
|
set up MAP->l_searchlist. */
|
||||||
@ -210,21 +208,24 @@ extern void _dl_setup_hash (struct link_map *map);
|
|||||||
extern struct link_map *_dl_open (struct link_map *loader,
|
extern struct link_map *_dl_open (struct link_map *loader,
|
||||||
const char *name, int mode);
|
const char *name, int mode);
|
||||||
|
|
||||||
|
/* Close an object previously opened by _dl_open. */
|
||||||
|
extern void _dl_close (struct link_map *map);
|
||||||
|
|
||||||
|
|
||||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||||
referred to by UNDEF. *SYM is the symbol table entry containing the
|
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||||
reference; it is replaced with the defining symbol, and the base load
|
reference; it is replaced with the defining symbol, and the base load
|
||||||
address of the defining object is returned. Each of SYMBOL_SCOPE[0] and
|
address of the defining object is returned. SYMBOL_SCOPE is a
|
||||||
SYMBOL_SCOPE[1] that is not null and their dependencies are searched to
|
null-terminated list of object scopes to search; each object's
|
||||||
resolve the name. REFERENCE_NAME should name the object containing the
|
l_searchlist (i.e. the segment of the dependency tree starting at that
|
||||||
reference; it is used in error messages. RELOC_ADDR is the address
|
object) is searched in turn. REFERENCE_NAME should name the object
|
||||||
being fixed up and the chosen symbol cannot be one with this value. If
|
containing the reference; it is used in error messages. RELOC_ADDR is
|
||||||
NOPLT is nonzero, then the reference must not be resolved to a PLT
|
the address being fixed up and the chosen symbol cannot be one with this
|
||||||
entry. */
|
value. If NOPLT is nonzero, then the reference must not be resolved to
|
||||||
|
a PLT entry. */
|
||||||
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct link_map *symbol_scope[2],
|
struct link_map *symbol_scope[],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
ElfW(Addr) reloc_addr,
|
ElfW(Addr) reloc_addr,
|
||||||
int noplt);
|
int noplt);
|
||||||
@ -236,11 +237,33 @@ extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
|
|||||||
/* Structure describing the dynamic linker itself. */
|
/* Structure describing the dynamic linker itself. */
|
||||||
extern struct link_map _dl_rtld_map;
|
extern struct link_map _dl_rtld_map;
|
||||||
|
|
||||||
/* List of objects currently loaded. */
|
/* The list of objects currently loaded is the third element of the
|
||||||
extern struct link_map *_dl_loaded;
|
`_dl_default_scope' array, and the fourth element is always null.
|
||||||
|
This leaves two slots before it that are used when resolving
|
||||||
|
DT_SYMBOLIC objects' references one after it for normal references
|
||||||
|
(see below). */
|
||||||
|
#define _dl_loaded (_dl_default_scope[2])
|
||||||
|
extern struct link_map *_dl_default_scope[5];
|
||||||
|
|
||||||
|
/* Null-terminated list of objects in the dynamic `global scope'. The
|
||||||
|
list starts at [2]; i.e. &_dl_global_scope[2] is the argument
|
||||||
|
passed to _dl_lookup_symbol to search the global scope. To search
|
||||||
|
a specific object and its dependencies in preference to the global
|
||||||
|
scope, fill in the [1] slot and pass its address; for two specific
|
||||||
|
object scopes, fill [0] and [1]. The list is double-terminated; to
|
||||||
|
search the global scope and then a specific object and its
|
||||||
|
dependencies, set *_dl_global_scope_end. This variable initially
|
||||||
|
points to _dl_default_scope, and _dl_loaded is always kept in [2]
|
||||||
|
of this list. A new list is malloc'd when new objects are loaded
|
||||||
|
with RTLD_GLOBAL. */
|
||||||
|
extern struct link_map **_dl_global_scope, **_dl_global_scope_end;
|
||||||
|
extern size_t _dl_global_scope_alloc; /* Number of slots malloc'd. */
|
||||||
|
|
||||||
|
/* Hack _dl_global_scope[0] and [1] as necessary, and return a pointer into
|
||||||
|
_dl_global_scope that should be passed to _dl_lookup_symbol for symbol
|
||||||
|
references made in the object MAP's relocations. */
|
||||||
|
extern struct link_map **_dl_object_relocation_scope (struct link_map *map);
|
||||||
|
|
||||||
/* Tail of that list which were loaded at startup. */
|
|
||||||
extern struct link_map *_dl_startup_loaded;
|
|
||||||
|
|
||||||
/* Allocate a `struct link_map' for a new object being loaded,
|
/* Allocate a `struct link_map' for a new object being loaded,
|
||||||
and enter it into the _dl_loaded list. */
|
and enter it into the _dl_loaded list. */
|
||||||
@ -248,8 +271,11 @@ extern struct link_map *_dl_new_object (char *realname, const char *libname,
|
|||||||
int type);
|
int type);
|
||||||
|
|
||||||
/* Relocate the given object (if it hasn't already been).
|
/* Relocate the given object (if it hasn't already been).
|
||||||
|
SCOPE is passed to _dl_lookup_symbol in symbol lookups.
|
||||||
If LAZY is nonzero, don't relocate its PLT. */
|
If LAZY is nonzero, don't relocate its PLT. */
|
||||||
extern void _dl_relocate_object (struct link_map *map, int lazy);
|
extern void _dl_relocate_object (struct link_map *map,
|
||||||
|
struct link_map *scope[],
|
||||||
|
int lazy);
|
||||||
|
|
||||||
/* Return the address of the next initializer function for MAP or one of
|
/* Return the address of the next initializer function for MAP or one of
|
||||||
its dependencies that has not yet been run. When there are no more
|
its dependencies that has not yet been run. When there are no more
|
||||||
|
39
elf/rtld.c
39
elf/rtld.c
@ -75,13 +75,6 @@ _dl_start (void *arg)
|
|||||||
/* Relocate ourselves so we can do normal function calls and
|
/* Relocate ourselves so we can do normal function calls and
|
||||||
data access using the global offset table. */
|
data access using the global offset table. */
|
||||||
|
|
||||||
/* We must initialize `l_type' to make sure it is not `lt_interpreter'.
|
|
||||||
That is the type to describe us, but not during bootstrapping--it
|
|
||||||
indicates to elf_machine_rel{,a} that we were already relocated during
|
|
||||||
bootstrapping, so it must anti-perform each bootstrapping relocation
|
|
||||||
before applying the final relocation when ld.so is linked in as
|
|
||||||
normal a shared library. */
|
|
||||||
bootstrap_map.l_type = lt_library;
|
|
||||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, NULL);
|
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, NULL);
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +171,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
--_dl_argc;
|
--_dl_argc;
|
||||||
++_dl_argv;
|
++_dl_argv;
|
||||||
|
|
||||||
l = _dl_map_object (NULL, _dl_argv[0]);
|
l = _dl_map_object (NULL, _dl_argv[0], lt_library);
|
||||||
phdr = l->l_phdr;
|
phdr = l->l_phdr;
|
||||||
phent = l->l_phnum;
|
phent = l->l_phnum;
|
||||||
l->l_name = (char *) "";
|
l->l_name = (char *) "";
|
||||||
@ -188,7 +181,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
{
|
{
|
||||||
/* Create a link_map for the executable itself.
|
/* Create a link_map for the executable itself.
|
||||||
This will be what dlopen on "" returns. */
|
This will be what dlopen on "" returns. */
|
||||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
l = _dl_new_object ((char *) "", "", lt_library);
|
||||||
l->l_phdr = phdr;
|
l->l_phdr = phdr;
|
||||||
l->l_phnum = phent;
|
l->l_phnum = phent;
|
||||||
interpreter_name = 0;
|
interpreter_name = 0;
|
||||||
@ -245,7 +238,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
/* Put the link_map for ourselves on the chain so it can be found by
|
/* Put the link_map for ourselves on the chain so it can be found by
|
||||||
name. */
|
name. */
|
||||||
_dl_rtld_map.l_name = (char *) _dl_rtld_map.l_libname = interpreter_name;
|
_dl_rtld_map.l_name = (char *) _dl_rtld_map.l_libname = interpreter_name;
|
||||||
_dl_rtld_map.l_type = lt_interpreter;
|
_dl_rtld_map.l_type = lt_library;
|
||||||
while (l->l_next)
|
while (l->l_next)
|
||||||
l = l->l_next;
|
l = l->l_next;
|
||||||
l->l_next = &_dl_rtld_map;
|
l->l_next = &_dl_rtld_map;
|
||||||
@ -293,9 +286,9 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
for (i = 1; i < _dl_argc; ++i)
|
for (i = 1; i < _dl_argc; ++i)
|
||||||
{
|
{
|
||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
struct link_map *scope[2] ={ _dl_loaded, NULL };
|
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
|
||||||
ElfW(Addr) loadbase
|
&_dl_default_scope[2],
|
||||||
= _dl_lookup_symbol (_dl_argv[i], &ref, scope, "argument", 0, 0);
|
"argument", 0, 0);
|
||||||
char buf[20], *bp;
|
char buf[20], *bp;
|
||||||
buf[sizeof buf - 1] = '\0';
|
buf[sizeof buf - 1] = '\0';
|
||||||
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
|
||||||
@ -314,21 +307,26 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
|
|
||||||
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||||
|
|
||||||
|
{
|
||||||
/* Now we have all the objects loaded. Relocate them all except for
|
/* Now we have all the objects loaded. Relocate them all except for
|
||||||
the dynamic linker itself. We do this in reverse order so that
|
the dynamic linker itself. We do this in reverse order so that copy
|
||||||
copy relocs of earlier objects overwrite the data written by later
|
relocs of earlier objects overwrite the data written by later
|
||||||
objects. We do not re-relocate the dynamic linker itself in this
|
objects. We do not re-relocate the dynamic linker itself in this
|
||||||
loop because that could result in the GOT entries for functions we
|
loop because that could result in the GOT entries for functions we
|
||||||
call being changed, and that would break us. It is safe to
|
call being changed, and that would break us. It is safe to relocate
|
||||||
relocate the dynamic linker out of order because it has no copy
|
the dynamic linker out of order because it has no copy relocs (we
|
||||||
relocs (we know that because it is self-contained). */
|
know that because it is self-contained). */
|
||||||
|
|
||||||
l = _dl_loaded;
|
l = _dl_loaded;
|
||||||
while (l->l_next)
|
while (l->l_next)
|
||||||
l = l->l_next;
|
l = l->l_next;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (l != &_dl_rtld_map)
|
if (l != &_dl_rtld_map)
|
||||||
_dl_relocate_object (l, lazy);
|
{
|
||||||
|
_dl_relocate_object (l, _dl_object_relocation_scope (l), lazy);
|
||||||
|
*_dl_global_scope_end = NULL;
|
||||||
|
}
|
||||||
l = l->l_prev;
|
l = l->l_prev;
|
||||||
} while (l);
|
} while (l);
|
||||||
|
|
||||||
@ -342,7 +340,8 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
if (_dl_rtld_map.l_opencount > 0)
|
if (_dl_rtld_map.l_opencount > 0)
|
||||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||||
Re-relocate ourselves with user-controlled symbol definitions. */
|
Re-relocate ourselves with user-controlled symbol definitions. */
|
||||||
_dl_relocate_object (&_dl_rtld_map, lazy);
|
_dl_relocate_object (&_dl_rtld_map, &_dl_default_scope[2], 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the debugger where to find the map of loaded objects. */
|
/* Tell the debugger where to find the map of loaded objects. */
|
||||||
_dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
_dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||||
|
@ -100,7 +100,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (map->l_type == lt_interpreter)
|
if (resolve && map == &_dl_rtld_map)
|
||||||
{
|
{
|
||||||
/* Undo the relocation done here during bootstrapping. Now we will
|
/* Undo the relocation done here during bootstrapping. Now we will
|
||||||
relocate it anew, possibly using a binding found in the user
|
relocate it anew, possibly using a binding found in the user
|
||||||
@ -117,7 +117,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
*reloc_addr += sym ? (loadbase + sym->st_value) : 0;
|
*reloc_addr += sym ? (loadbase + sym->st_value) : 0;
|
||||||
break;
|
break;
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
if (map->l_type != lt_interpreter) /* Already done in dynamic linker. */
|
if (!resolve || map != &_dl_rtld_map) /* Already done in rtld itself. */
|
||||||
*reloc_addr += map->l_addr;
|
*reloc_addr += map->l_addr;
|
||||||
break;
|
break;
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
@ -229,9 +229,9 @@ _dl_start_user:\n\
|
|||||||
leal (%esp,%eax,4), %esp\n\
|
leal (%esp,%eax,4), %esp\n\
|
||||||
# Push back the modified argument count.\n\
|
# Push back the modified argument count.\n\
|
||||||
pushl %ecx\n\
|
pushl %ecx\n\
|
||||||
# Push _dl_loaded as argument in _dl_init_next call below.\n\
|
# Push _dl_default_scope[2] as argument in _dl_init_next call below.\n\
|
||||||
movl _dl_loaded@GOT(%ebx), %eax\n\
|
movl _dl_default_scope@GOT(%ebx), %eax\n\
|
||||||
movl (%eax), %esi\n\
|
movl 8(%eax), %esi\n\
|
||||||
0: pushl %esi\n\
|
0: pushl %esi\n\
|
||||||
# Call _dl_init_next to return the address of an initializer\n\
|
# Call _dl_init_next to return the address of an initializer\n\
|
||||||
# function to run.\n\
|
# function to run.\n\
|
||||||
|
@ -252,9 +252,9 @@ _dl_start_user:
|
|||||||
lea (%sp, %d0*4), %sp
|
lea (%sp, %d0*4), %sp
|
||||||
| Push back the modified argument count.
|
| Push back the modified argument count.
|
||||||
move.l %d1, -(%sp)
|
move.l %d1, -(%sp)
|
||||||
0: | Push _dl_loaded as argument in _dl_init_next call below.
|
0: | Push _dl_default_scope[2] as argument in _dl_init_next call below.
|
||||||
move.l ([_dl_loaded@GOT, %a5]), %d2
|
move.l ([_dl_default_scope@GOT, %a5]), %d2
|
||||||
0: move.l %d2, -(%sp)
|
0: move.l (%d2, 8), -(%sp)
|
||||||
| Call _dl_init_next to return the address of an initializer
|
| Call _dl_init_next to return the address of an initializer
|
||||||
| function to run.
|
| function to run.
|
||||||
bsr.l _dl_init_next@PLTPC
|
bsr.l _dl_init_next@PLTPC
|
||||||
|
Reference in New Issue
Block a user