1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

Tue Jun 4 02:25:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>

* elf/linux-compat.c (_init): Pass reloc_addr arg to _dl_lookup_symbol.

	* elf/dl-lookup.c (_dl_lookup_symbol): Use l_searchlist.

	* elf/dl-deps.c: New file.
	* elf/Makefile (rtld-routines): Add dl-deps.
	* elf/link.h: Declare _dl_map_object_deps, _dl_open.
	* elf/rtld.c (dl_main): Use _dl_map_object_deps.
	* elf/dlopen.c: Use _dl_open.

	* elf/rtld.c (dl_main): Remove BEFORE_RTLD variable and list
	frobnication based on its value.  Detach RTLD_MAP from the chain if
	its l_opencount is zero after loading deps.

	* elf/dlfcn.h (RTLD_BINDING_MASK): New macro.

	* elf/link.h (struct link_map): Replace l_deps_loaded flag member with
	`struct link_map **l_searchlist' and `unsigned int l_nsearchlist'.
	* elf/dl-lookup.c (_dl_lookup_symbol): Make SYMBOL_SCOPE arg an array
	of two link_map ptrs.  Search the maps in the l_searchlist of each
	elt that is not null.
	* elf/dl-reloc.c (_dl_relocate_object): Pass proper SCOPE array.
	* elf/dl-runtime.c: Likewise.
	* elf/dlsym.c: Likewise.
	* elf/rtld.c (dl_main): Likewise.

	* elf/dl-minimal.c (realloc): Support realloc of the block most
	recently returned by the minimal malloc.

	* intl/localealias.c, intl/dcgettext.c [_LIBC]: Define HAVE_ALLOCA.
This commit is contained in:
Roland McGrath
1996-06-04 05:18:15 +00:00
parent b25ae9c6a4
commit efec1d0c47
13 changed files with 253 additions and 162 deletions

View File

@ -1,9 +1,40 @@
Tue Jun 4 02:25:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* elf/linux-compat.c (_init): Pass reloc_addr arg to _dl_lookup_symbol.
* elf/dl-lookup.c (_dl_lookup_symbol): Use l_searchlist.
* elf/dl-deps.c: New file.
* elf/Makefile (rtld-routines): Add dl-deps.
* elf/link.h: Declare _dl_map_object_deps, _dl_open.
* elf/rtld.c (dl_main): Use _dl_map_object_deps.
* elf/dlopen.c: Use _dl_open.
* elf/rtld.c (dl_main): Remove BEFORE_RTLD variable and list
frobnication based on its value. Detach RTLD_MAP from the chain if
its l_opencount is zero after loading deps.
* elf/dlfcn.h (RTLD_BINDING_MASK): New macro.
* elf/link.h (struct link_map): Replace l_deps_loaded flag member with
`struct link_map **l_searchlist' and `unsigned int l_nsearchlist'.
* elf/dl-lookup.c (_dl_lookup_symbol): Make SYMBOL_SCOPE arg an array
of two link_map ptrs. Search the maps in the l_searchlist of each
elt that is not null.
* elf/dl-reloc.c (_dl_relocate_object): Pass proper SCOPE array.
* elf/dl-runtime.c: Likewise.
* elf/dlsym.c: Likewise.
* elf/rtld.c (dl_main): Likewise.
* elf/dl-minimal.c (realloc): Support realloc of the block most
recently returned by the minimal malloc.
Tue Jun 4 00:16:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* sysdeps/gnu/errlist.awk: Produce N_("..."), not _N("...").
* intl: Updated from gettext-0.10.13.
* intl/localealias.c intl/dcgettext.c [_LIBC]: Define HAVE_ALLOCA.
* intl/localealias.c, intl/dcgettext.c [_LIBC]: Define HAVE_ALLOCA.
* signal/siggetmask.c: New file. Wrapper around sigblock with
link_warning about obsolescence.
@ -38,18 +69,6 @@ Mon Jun 3 15:58:22 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
for a HANDLE signal to IGNORE because the signal is blocked, clean
up any pending suspension left over from a call to resume.
Mon Jun 3 01:29:53 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* elf/link.h (struct link_map): Replace l_deps_loaded flag member with
`struct link_map **l_searchlist'.
* elf/dl-lookup.c (_dl_lookup_symbol): Make SYMBOL_SCOPE arg an array
of two link_map ptrs. Search the maps in the l_searchlist of each
of the two elts that is non-null.
* elf/dl-reloc.c (_dl_relocate_object): Pass proper SCOPE array.
* elf/dl-runtime.c: Likewise.
* elf/dlsym.c: Likewise.
* elf/rtld.c (dl_main): Likewise.
Mon Jun 3 00:30:35 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* elf/dl-lookup.c (_dl_lookup_symbol): Take new arg RELOC_ADDR and

View File

@ -29,7 +29,7 @@ libdl-routines := dlopen dlclose dlsym dlerror
libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared.
rtld-routines := rtld $(addprefix dl-,minimal load lookup object reloc \
runtime sysdep error init fini)
deps runtime sysdep error init fini)
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h \
soinit.c sofini.c ldd.sh.in linux-compat.c

93
elf/dl-deps.c Normal file
View File

@ -0,0 +1,93 @@
/* Load the dependencies of a mapped object.
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 <errno.h>
#include <dlfcn.h>
#include <stdlib.h>
void
_dl_map_object_deps (struct link_map *map)
{
unsigned int nlist = 1;
struct link_map **list = malloc (sizeof *list);
unsigned int done;
/* Start the search list with one element: MAP itself. */
list[0] = map;
/* Process each element of the search list, loading each of its immediate
dependencies and appending them to the list as we step through it.
This produces a flat, ordered list that represents a breadth-first
search of the dependency tree. */
for (done = 0; done < nlist; ++done)
{
struct link_map *l = list[done];
if (l->l_info[DT_NEEDED])
{
const char *strtab
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
const Elf32_Dyn *d;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_NEEDED)
{
/* Extend the list and put this object on the end. */
struct link_map **n
= realloc (list, (nlist + 1) * sizeof *list);
if (n)
list = n;
else
{
free (list);
_dl_signal_error (ENOMEM, map->l_name,
"finding dependencies");
}
list[nlist++] = _dl_map_object (l, strtab + d->d_un.d_val);
}
}
}
map->l_searchlist = list;
map->l_nsearchlist = nlist;
}
struct link_map *
_dl_open (struct link_map *parent, const char *file, int mode)
{
struct link_map *new, *l;
Elf32_Addr init;
/* Load the named object. */
new = _dl_map_object (parent, file);
/* Load that object's dependencies. */
_dl_map_object_deps (new);
/* Relocate the objects loaded. */
for (l = new; l; l = l->l_next)
if (! l->l_relocated)
_dl_relocate_object (l, (mode & RTLD_BINDING_MASK) == RTLD_LAZY);
/* Run the initializer functions of new objects. */
while (init = _dl_init_next ())
(*(void (*) (void)) init) ();
return new;
}

View File

@ -29,26 +29,31 @@ Cambridge, MA 02139, USA. */
Elf32_Addr
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
struct link_map *symbol_scope,
struct link_map *symbol_scope[2],
const char *reference_name,
Elf32_Addr reloc_addr,
int noplt)
{
unsigned long int hash = elf_hash (undef_name);
struct link_map *map;
struct
{
Elf32_Addr a;
const Elf32_Sym *s;
} weak_value = { 0, NULL };
size_t i;
struct link_map **scope, *map;
/* Search the relevant loaded objects for a definition. */
for (map = symbol_scope; map; map = map->l_next)
for (scope = symbol_scope; scope < &symbol_scope[2]; ++scope)
if (*scope)
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
{
const Elf32_Sym *symtab;
const char *strtab;
Elf32_Word symidx;
map = (*scope)->l_searchlist[i];
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
@ -61,8 +66,9 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
const Elf32_Sym *sym = &symtab[symidx];
if (sym->st_value == 0 || /* No value. */
reloc_addr == map->l_addr + sym->st_value || /* Self ref. */
(noplt && sym->st_shndx == SHN_UNDEF)) /* Unwanted PLT entry. */
/* Cannot resolve to the location being filled in. */
reloc_addr == map->l_addr + sym->st_value ||
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
continue;
switch (ELF32_ST_TYPE (sym->st_info))
@ -87,7 +93,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
*ref = sym;
return map->l_addr;
case STB_WEAK:
/* Weak definition. Use this value if we don't find another. */
/* Weak definition. Use this value if we don't find
another. */
if (! weak_value.s)
{
weak_value.s = sym;

View File

@ -1,5 +1,5 @@
/* Minimal replacements for basic facilities used in the dynamic linker.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 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
@ -84,10 +84,17 @@ free (void *ptr)
}
weak_symbol (free)
/* This is never called. */
/* This is only called with the most recent block returned by malloc. */
void *
realloc (void *ptr, size_t n)
{ ptr += n; abort (); }
{
void *new;
assert (ptr == alloc_last_block);
alloc_ptr = alloc_last_block;
new = malloc (n);
assert (new == ptr);
return new;
}
weak_symbol (realloc)
/* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */

View File

@ -54,12 +54,11 @@ _dl_relocate_object (struct link_map *l, int lazy)
}
{
struct link_map *real_next, *scope;
struct link_map *scope[2];
const char *strtab
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
Elf32_Addr resolve (const Elf32_Sym **ref,
Elf32_Addr reloc_addr, int noplt)
{
@ -67,16 +66,16 @@ _dl_relocate_object (struct link_map *l, int lazy)
l->l_name, reloc_addr, noplt);
}
real_next = l->l_next;
if (l->l_info[DT_SYMBOLIC])
{
if (l->l_prev)
l->l_prev->l_next = real_next;
l->l_next = _dl_loaded;
scope = l;
scope[0] = l;
scope[1] = _dl_loaded;
}
else
scope = _dl_loaded;
{
scope[0] = _dl_loaded;
scope[1] = l;
}
if (l->l_type == lt_interpreter)
/* We cannot be lazy when relocating the dynamic linker itself. It
@ -87,11 +86,6 @@ _dl_relocate_object (struct link_map *l, int lazy)
lazy = 0;
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
/* Restore list frobnication done above for DT_SYMBOLIC. */
l->l_next = real_next;
if (l->l_prev)
l->l_prev->l_next = l;
}
/* Set up the PLT so its unrelocated entries will

View File

@ -70,8 +70,9 @@ fixup (
Elf32_Addr resolve (const Elf32_Sym **ref,
Elf32_Addr reloc_addr, int noplt)
{
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, _dl_loaded,
l->l_name, reloc_addr, noplt);
struct link_map *scope[2] = { _dl_loaded, NULL };
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
scope, l->l_name, reloc_addr, noplt);
}
/* Perform the specified relocation. */

View File

@ -24,6 +24,7 @@ Cambridge, MA 02139, USA. */
/* The MODE argument to `dlopen' contains one of the following: */
#define RTLD_LAZY 0x001 /* Lazy function call binding. */
#define RTLD_NOW 0x002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
/* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made

View File

@ -24,38 +24,11 @@ Cambridge, MA 02139, USA. */
void *
dlopen (const char *file, int mode)
{
struct link_map *new, *l;
struct link_map *new;
void doit (void)
{
Elf32_Addr init;
new = _dl_map_object (_dl_loaded, file);
/* Map in any dependencies. */
for (l = new; l; l = l->l_next)
if (! l->l_deps_loaded)
{
if (l->l_info[DT_NEEDED])
{
const char *strtab
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
const Elf32_Dyn *d;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_NEEDED)
_dl_map_object (l, strtab + d->d_un.d_val);
}
l->l_deps_loaded = 1;
}
/* Relocate the objects loaded. */
for (l = new; l; l = l->l_next)
if (! l->l_relocated)
_dl_relocate_object (l, mode == RTLD_LAZY);
/* Run the initializer functions of new objects. */
while (init = _dl_init_next ())
(*(void (*) (void)) init) ();
new = _dl_open (_dl_loaded, file, mode);
}
return _dlerror_run (doit) ? NULL : new;

View File

@ -33,7 +33,8 @@ dlsym (void *handle, const char *name)
int lose;
void doit (void)
{
loadbase = _dl_lookup_symbol (name, &ref, map, map->l_name, 0);
struct link_map *scope[2] = { map, NULL };
loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0);
}
/* Confine the symbol scope to just this map. */

View File

@ -90,6 +90,12 @@ struct link_map
Elf32_Word l_phnum; /* Number of program header entries. */
Elf32_Addr l_entry; /* Entry point location. */
/* Array of DT_NEEDED dependencies and their dependencies, in
dependency order for symbol lookup. This is null before the
dependencies have been loaded. */
struct link_map **l_searchlist;
unsigned int l_nsearchlist;
/* Symbol hash table. */
Elf32_Word l_nbuckets;
const Elf32_Word *l_buckets, *l_chain;
@ -102,7 +108,6 @@ struct link_map
lt_library, /* Library needed by main executable. */
lt_loaded, /* Extra run-time loaded shared object. */
} l_type:2;
unsigned int l_deps_loaded:1; /* Nonzero if DT_NEEDED items loaded. */
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_running:1; /* Nonzero while DT_INIT function runs. */
@ -176,22 +181,36 @@ extern struct link_map *_dl_map_object (struct link_map *loader,
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
set up MAP->l_searchlist. */
extern void _dl_map_object_deps (struct link_map *map);
/* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map);
/* Open the shared object NAME, relocate it, and run its initializer if it
hasn't already been run. LOADER's DT_RPATH is used in searching for
NAME. MODE is as for `dlopen' (see <dlfcn.h>). If the object is
already opened, returns its existing map. */
extern struct link_map *_dl_open (struct link_map *loader,
const char *name, int mode);
/* Search loaded objects' symbol tables for a definition of the symbol
referred to by UNDEF. *SYM is the symbol table entry containing the
reference; it is replaced with the defining symbol, and the base load
address of the defining object is returned. SYMBOL_SCOPE is the head of
the chain used for searching. REFERENCE_NAME should name the object
containing the reference; it is used in error messages. RELOC_ADDR is
the address being fixed up and the chosen symbol cannot be one with this
value. If NOPLT is nonzero, then the reference must not be resolved to
a PLT entry. */
address of the defining object is returned. Each of SYMBOL_SCOPE[0] and
SYMBOL_SCOPE[1] that is not null and their dependencies are searched to
resolve the name. REFERENCE_NAME should name the object containing the
reference; it is used in error messages. RELOC_ADDR is the address
being fixed up and the chosen symbol cannot be one with this value. If
NOPLT is nonzero, then the reference must not be resolved to a PLT
entry. */
extern Elf32_Addr _dl_lookup_symbol (const char *undef,
const Elf32_Sym **sym,
struct link_map *symbol_scope,
struct link_map *symbol_scope[2],
const char *reference_name,
Elf32_Addr reloc_addr,
int noplt);

View File

@ -1,5 +1,5 @@
/* Initializer for Linux-compatible dynamic linker `/lib/ld-linux.so.1'.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 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
@ -33,8 +33,9 @@ void
_init (void)
{
const Elf32_Sym *ref = NULL;
Elf32_Addr loadbase = _dl_lookup_symbol ("atexit", &ref, _dl_loaded,
struct link_map *scope[2] = { _dl_loaded, NULL };
Elf32_Addr loadbase = _dl_lookup_symbol ("atexit", &ref, scope,
"<ld-linux.so.1 initialization>",
1);
0, 1);
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
}

View File

@ -124,7 +124,7 @@ dl_main (const Elf32_Phdr *phdr,
Elf32_Addr *user_entry)
{
const Elf32_Phdr *ph;
struct link_map *l, *last, *before_rtld;
struct link_map *l;
const char *interpreter_name;
int lazy;
int list_only = 0;
@ -250,44 +250,19 @@ of this helper program; chances are you did not intend to run this program.\n",
l->l_next = &rtld_map;
rtld_map.l_prev = l;
/* Now process all the DT_NEEDED entries and map in the objects.
Each new link_map will go on the end of the chain, so we will
come across it later in the loop to map in its dependencies. */
before_rtld = NULL;
for (l = _dl_loaded; l; l = l->l_next)
{
if (l->l_info[DT_NEEDED])
{
const char *strtab
= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
const Elf32_Dyn *d;
last = l;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_NEEDED)
{
struct link_map *new;
new = _dl_map_object (l, strtab + d->d_un.d_val);
if (!before_rtld && new == &rtld_map)
before_rtld = last;
last = new;
}
}
l->l_deps_loaded = 1;
}
/* Load all the libraries specified by DT_NEEDED entries. */
_dl_map_object_deps (l);
/* If any DT_NEEDED entry referred to the interpreter object itself,
reorder the list so it appears after its dependent. If not,
remove it from the maps we will use for symbol resolution. */
rtld_map.l_prev->l_next = rtld_map.l_next;
if (rtld_map.l_next)
rtld_map.l_next->l_prev = rtld_map.l_prev;
if (before_rtld)
/* XXX if kept, move it so l_next list is in dep order because
it will determine gdb's search order.
Perhaps do this always, so later dlopen by name finds it?
XXX But then gdb always considers it present. */
if (rtld_map.l_opencount == 0)
{
rtld_map.l_prev = before_rtld;
rtld_map.l_next = before_rtld->l_next;
before_rtld->l_next = &rtld_map;
if (rtld_map.l_next)
rtld_map.l_next->l_prev = &rtld_map;
/* No DT_NEEDED entry referred to the interpreter object itself,
so remove it from the list of visible objects. */
rtld_map.l_prev->l_next = rtld_map.l_next;
rtld_map.l_next->l_prev = rtld_map.l_prev;
}
if (list_only)
@ -316,9 +291,9 @@ of this helper program; chances are you did not intend to run this program.\n",
for (i = 1; i < _dl_argc; ++i)
{
const Elf32_Sym *ref = NULL;
Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
_dl_loaded, "argument",
0, 0);
struct link_map *scope[2] ={ _dl_loaded, NULL };
Elf32_Addr loadbase
= _dl_lookup_symbol (_dl_argv[i], &ref, scope, "argument", 0, 0);
char buf[20], *bp;
buf[sizeof buf - 1] = '\0';
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);