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> Tue Jun 4 00:16:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* sysdeps/gnu/errlist.awk: Produce N_("..."), not _N("..."). * sysdeps/gnu/errlist.awk: Produce N_("..."), not _N("...").
* intl: Updated from gettext-0.10.13. * 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 * signal/siggetmask.c: New file. Wrapper around sigblock with
link_warning about obsolescence. 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 for a HANDLE signal to IGNORE because the signal is blocked, clean
up any pending suspension left over from a call to resume. 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> 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 * 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. libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared.
rtld-routines := rtld $(addprefix dl-,minimal load lookup object reloc \ 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 \ distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h \
soinit.c sofini.c ldd.sh.in linux-compat.c 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,77 +29,84 @@ Cambridge, MA 02139, USA. */
Elf32_Addr Elf32_Addr
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, _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, const char *reference_name,
Elf32_Addr reloc_addr, Elf32_Addr reloc_addr,
int noplt) int noplt)
{ {
unsigned long int hash = elf_hash (undef_name); unsigned long int hash = elf_hash (undef_name);
struct link_map *map;
struct struct
{ {
Elf32_Addr a; Elf32_Addr a;
const Elf32_Sym *s; const Elf32_Sym *s;
} weak_value = { 0, NULL }; } weak_value = { 0, NULL };
size_t i;
struct link_map **scope, *map;
/* Search the relevant loaded objects for a definition. */ /* 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)
const Elf32_Sym *symtab; for (i = 0; i < (*scope)->l_nsearchlist; ++i)
const char *strtab;
Elf32_Word symidx;
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);
/* Search the appropriate hash bucket in this object's symbol table
for a definition for the same symbol name. */
for (symidx = map->l_buckets[hash % map->l_nbuckets];
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{ {
const Elf32_Sym *sym = &symtab[symidx]; const Elf32_Sym *symtab;
const char *strtab;
Elf32_Word symidx;
if (sym->st_value == 0 || /* No value. */ map = (*scope)->l_searchlist[i];
reloc_addr == map->l_addr + sym->st_value || /* Self ref. */
(noplt && sym->st_shndx == SHN_UNDEF)) /* Unwanted PLT entry. */
continue;
switch (ELF32_ST_TYPE (sym->st_info)) 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);
/* Search the appropriate hash bucket in this object's symbol table
for a definition for the same symbol name. */
for (symidx = map->l_buckets[hash % map->l_nbuckets];
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{ {
case STT_NOTYPE: const Elf32_Sym *sym = &symtab[symidx];
case STT_FUNC:
case STT_OBJECT:
break;
default:
/* Not a code/data definition. */
continue;
}
if (sym != *ref && strcmp (strtab + sym->st_name, undef_name)) if (sym->st_value == 0 || /* No value. */
/* Not the symbol we are looking for. */ /* Cannot resolve to the location being filled in. */
continue; reloc_addr == map->l_addr + sym->st_value ||
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
continue;
switch (ELF32_ST_BIND (sym->st_info)) switch (ELF32_ST_TYPE (sym->st_info))
{
case STB_GLOBAL:
/* Global definition. Just what we need. */
*ref = sym;
return map->l_addr;
case STB_WEAK:
/* Weak definition. Use this value if we don't find another. */
if (! weak_value.s)
{ {
weak_value.s = sym; case STT_NOTYPE:
weak_value.a = map->l_addr; case STT_FUNC:
case STT_OBJECT:
break;
default:
/* Not a code/data definition. */
continue;
}
if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
/* Not the symbol we are looking for. */
continue;
switch (ELF32_ST_BIND (sym->st_info))
{
case STB_GLOBAL:
/* Global definition. Just what we need. */
*ref = sym;
return map->l_addr;
case STB_WEAK:
/* Weak definition. Use this value if we don't find
another. */
if (! weak_value.s)
{
weak_value.s = sym;
weak_value.a = map->l_addr;
}
break;
default:
/* Local symbols are ignored. */
break;
} }
break;
default:
/* Local symbols are ignored. */
break;
} }
} }
}
if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK) if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK)
{ {

View File

@ -1,5 +1,5 @@
/* Minimal replacements for basic facilities used in the dynamic linker. /* 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. 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
@ -84,10 +84,17 @@ free (void *ptr)
} }
weak_symbol (free) weak_symbol (free)
/* This is never called. */ /* This is only called with the most recent block returned by malloc. */
void * void *
realloc (void *ptr, size_t n) 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) weak_symbol (realloc)
/* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */ /* 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 const char *strtab
= ((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);
Elf32_Addr resolve (const Elf32_Sym **ref, Elf32_Addr resolve (const Elf32_Sym **ref,
Elf32_Addr reloc_addr, int noplt) 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); l->l_name, reloc_addr, noplt);
} }
real_next = l->l_next;
if (l->l_info[DT_SYMBOLIC]) if (l->l_info[DT_SYMBOLIC])
{ {
if (l->l_prev) scope[0] = l;
l->l_prev->l_next = real_next; scope[1] = _dl_loaded;
l->l_next = _dl_loaded;
scope = l;
} }
else else
scope = _dl_loaded; {
scope[0] = _dl_loaded;
scope[1] = l;
}
if (l->l_type == lt_interpreter) if (l->l_type == lt_interpreter)
/* We cannot be lazy when relocating the dynamic linker itself. It /* 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; lazy = 0;
ELF_DYNAMIC_RELOCATE (l, lazy, resolve); 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 /* 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 resolve (const Elf32_Sym **ref,
Elf32_Addr reloc_addr, int noplt) Elf32_Addr reloc_addr, int noplt)
{ {
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, _dl_loaded, struct link_map *scope[2] = { _dl_loaded, NULL };
l->l_name, reloc_addr, noplt); return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
scope, l->l_name, reloc_addr, noplt);
} }
/* Perform the specified relocation. */ /* Perform the specified relocation. */

View File

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

View File

@ -24,38 +24,11 @@ Cambridge, MA 02139, USA. */
void * void *
dlopen (const char *file, int mode) dlopen (const char *file, int mode)
{ {
struct link_map *new, *l; struct link_map *new;
void doit (void) void doit (void)
{ {
Elf32_Addr init; new = _dl_open (_dl_loaded, file, mode);
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) ();
} }
return _dlerror_run (doit) ? NULL : new; return _dlerror_run (doit) ? NULL : new;

View File

@ -33,7 +33,8 @@ dlsym (void *handle, const char *name)
int lose; int lose;
void doit (void) 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. */ /* 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_Word l_phnum; /* Number of program header entries. */
Elf32_Addr l_entry; /* Entry point location. */ 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. */ /* Symbol hash table. */
Elf32_Word l_nbuckets; Elf32_Word l_nbuckets;
const Elf32_Word *l_buckets, *l_chain; const Elf32_Word *l_buckets, *l_chain;
@ -102,7 +108,6 @@ struct link_map
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_deps_loaded:1; /* Nonzero if DT_NEEDED items loaded. */
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. */
@ -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, extern struct link_map *_dl_map_object_from_fd (const char *name,
int fd, char *realname); 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. */ /* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map); 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 /* 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. SYMBOL_SCOPE is the head of address of the defining object is returned. Each of SYMBOL_SCOPE[0] and
the chain used for searching. REFERENCE_NAME should name the object SYMBOL_SCOPE[1] that is not null and their dependencies are searched to
containing the reference; it is used in error messages. RELOC_ADDR is resolve the name. REFERENCE_NAME should name the object containing the
the address being fixed up and the chosen symbol cannot be one with this reference; it is used in error messages. RELOC_ADDR is the address
value. If NOPLT is nonzero, then the reference must not be resolved to being fixed up and the chosen symbol cannot be one with this value. If
a PLT entry. */ NOPLT is nonzero, then the reference must not be resolved to a PLT
entry. */
extern Elf32_Addr _dl_lookup_symbol (const char *undef, extern Elf32_Addr _dl_lookup_symbol (const char *undef,
const Elf32_Sym **sym, const Elf32_Sym **sym,
struct link_map *symbol_scope, struct link_map *symbol_scope[2],
const char *reference_name, const char *reference_name,
Elf32_Addr reloc_addr, Elf32_Addr reloc_addr,
int noplt); int noplt);

View File

@ -1,5 +1,5 @@
/* Initializer for Linux-compatible dynamic linker `/lib/ld-linux.so.1'. /* 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. 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
@ -33,8 +33,9 @@ void
_init (void) _init (void)
{ {
const Elf32_Sym *ref = NULL; 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>", "<ld-linux.so.1 initialization>",
1); 0, 1);
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini); (*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
} }

View File

@ -124,7 +124,7 @@ dl_main (const Elf32_Phdr *phdr,
Elf32_Addr *user_entry) Elf32_Addr *user_entry)
{ {
const Elf32_Phdr *ph; const Elf32_Phdr *ph;
struct link_map *l, *last, *before_rtld; struct link_map *l;
const char *interpreter_name; const char *interpreter_name;
int lazy; int lazy;
int list_only = 0; 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; l->l_next = &rtld_map;
rtld_map.l_prev = l; rtld_map.l_prev = l;
/* Now process all the DT_NEEDED entries and map in the objects. /* Load all the libraries specified by DT_NEEDED entries. */
Each new link_map will go on the end of the chain, so we will _dl_map_object_deps (l);
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;
}
/* If any DT_NEEDED entry referred to the interpreter object itself, /* XXX if kept, move it so l_next list is in dep order because
reorder the list so it appears after its dependent. If not, it will determine gdb's search order.
remove it from the maps we will use for symbol resolution. */ Perhaps do this always, so later dlopen by name finds it?
rtld_map.l_prev->l_next = rtld_map.l_next; XXX But then gdb always considers it present. */
if (rtld_map.l_next) if (rtld_map.l_opencount == 0)
rtld_map.l_next->l_prev = rtld_map.l_prev;
if (before_rtld)
{ {
rtld_map.l_prev = before_rtld; /* No DT_NEEDED entry referred to the interpreter object itself,
rtld_map.l_next = before_rtld->l_next; so remove it from the list of visible objects. */
before_rtld->l_next = &rtld_map; 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;
rtld_map.l_next->l_prev = &rtld_map;
} }
if (list_only) 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) for (i = 1; i < _dl_argc; ++i)
{ {
const Elf32_Sym *ref = NULL; const Elf32_Sym *ref = NULL;
Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref, struct link_map *scope[2] ={ _dl_loaded, NULL };
_dl_loaded, "argument", Elf32_Addr loadbase
0, 0); = _dl_lookup_symbol (_dl_argv[i], &ref, scope, "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);