* elf/dl-reloc.c: Include "dynamic-link.h" at file scope.

* elf/rtld.c: Include <string.h>.

	* elf/dynamic-link.h (ELF_DYNAMIC_DO_REL, ELF_DYNAMIC_DO_RELA,
	ELF_DYNAMIC_RELOCATE): No longer take RESOLVE argument.
	Conditionalize defns on [RESOLVE].
	* elf/do-rel.h (elf_dynamic_do_rel): Likewise.
	* sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise.
	Instead use RESOLVE macro with same args.
	(elf_machine_rel): Conditionalize defn on [RESOLVE].
	* elf/dl-reloc.c (RESOLVE): New macro, define before including
	"dynamic-link.h".  It replaces `resolve' local function.
	* elf/dl-runtime.c: Likewise.
	* elf/rtld.c: Likewise.
This commit is contained in:
Roland McGrath 1996-07-14 11:39:25 +00:00
parent c928de7902
commit f51d1dfd35
7 changed files with 154 additions and 137 deletions

View File

@ -1,5 +1,21 @@
Sun Jul 14 01:51:39 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* elf/dl-reloc.c: Include "dynamic-link.h" at file scope.
* elf/rtld.c: Include <string.h>.
* elf/dynamic-link.h (ELF_DYNAMIC_DO_REL, ELF_DYNAMIC_DO_RELA,
ELF_DYNAMIC_RELOCATE): No longer take RESOLVE argument.
Conditionalize defns on [RESOLVE].
* elf/do-rel.h (elf_dynamic_do_rel): Likewise.
* sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise.
Instead use RESOLVE macro with same args.
(elf_machine_rel): Conditionalize defn on [RESOLVE].
* elf/dl-reloc.c (RESOLVE): New macro, define before including
"dynamic-link.h". It replaces `resolve' local function.
* elf/dl-runtime.c: Likewise.
* elf/rtld.c: Likewise.
* elf/dl-deps.c (_dl_map_object_deps): Start TAILP at last preload.
* elf/dl-open.c (_dl_open): Force an indirect call for

View File

@ -24,7 +24,6 @@ Cambridge, MA 02139, USA. */
#include <errno.h>
#include "dynamic-link.h"
void
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
{
@ -56,15 +55,14 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
const char *strtab /* String table object symbols. */
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
ElfW(Addr) resolve (const ElfW(Sym) **ref,
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,
l->l_name, reloc_addr, noplt);
}
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
#define RESOLVE(ref, reloc_addr, noplt) \
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
l->l_name, reloc_addr, noplt))
#include "dynamic-link.h"
ELF_DYNAMIC_RELOCATE (l, lazy);
}
/* Set up the PLT so its unrelocated entries will jump to

View File

@ -18,7 +18,6 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <link.h>
#include "dynamic-link.h"
/* The global scope we will use for symbol lookups.
@ -68,6 +67,8 @@ _dl_object_relocation_scope (struct link_map *l)
}
}
#include "dynamic-link.h"
/* Figure out the right type, Rel or Rela. */
#define elf_machine_rel 1
#define elf_machine_rela 2
@ -118,14 +119,16 @@ fixup (
/* 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) reloc_addr, int noplt)
{
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
scope, l->l_name, reloc_addr, noplt);
}
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve);
{
/* This macro is used as a callback from the elf_machine_relplt code. */
#define RESOLVE(ref, reloc_addr, noplt) \
(_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
l->l_name, reloc_addr, noplt))
#include "dynamic-link.h"
/* Perform the specified relocation. */
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)]);
}
*_dl_global_scope_end = NULL;

View File

@ -28,17 +28,13 @@ Cambridge, MA 02139, USA. */
/* Perform the relocations in MAP on the running program image as specified
by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it
modifies its argument pointer to point to the defining symbol, and
returns the base load address of the defining object. If LAZY is
nonzero, this is the first pass on PLT relocations; they should be set
up to call _dl_runtime_resolve, rather than fully resolved now. */
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
relocations; they should be set up to call _dl_runtime_resolve, rather
than fully resolved now. */
static inline void
elf_dynamic_do_rel (struct link_map *map,
int reltag, int sztag,
ElfW(Addr) (*resolve) (const ElfW(Sym) **symbol,
ElfW(Addr) reloc_addr, int noplt),
int lazy)
{
const ElfW(Sym) *const symtab
@ -53,7 +49,7 @@ elf_dynamic_do_rel (struct link_map *map,
elf_machine_lazy_rel (map, r);
else
for (; r < end; ++r)
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], resolve);
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)]);
}
#undef elf_dynamic_do_rel

View File

@ -56,6 +56,8 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM])
info[DT_PLTREL]->d_un.d_val == DT_RELA);
}
#ifdef RESOLVE
/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
These functions are almost identical, so we use cpp magic to avoid
duplicating their code. It cannot be done in a more general function
@ -63,31 +65,33 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM])
#if ! ELF_MACHINE_NO_REL
#include "do-rel.h"
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
#define ELF_DYNAMIC_DO_REL(map, lazy) \
if ((map)->l_info[DT_REL]) \
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve), 0); \
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, 0); \
if ((map)->l_info[DT_PLTREL] && \
(map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (lazy));
#else
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) /* Nothing to do. */
#define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */
#endif
#if ! ELF_MACHINE_NO_RELA
#define DO_RELA
#include "do-rel.h"
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
#define ELF_DYNAMIC_DO_RELA(map, lazy) \
if ((map)->l_info[DT_RELA]) \
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve), 0); \
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, 0); \
if ((map)->l_info[DT_PLTREL] && \
(map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (lazy));
#else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
#define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */
#endif
/* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */
#define ELF_DYNAMIC_RELOCATE(map, lazy, resolve) \
do { ELF_DYNAMIC_DO_REL ((map), (lazy), (resolve)); \
ELF_DYNAMIC_DO_RELA ((map), (lazy), (resolve)); } while (0)
#define ELF_DYNAMIC_RELOCATE(map, lazy) \
do { ELF_DYNAMIC_DO_REL ((map), (lazy)); \
ELF_DYNAMIC_DO_RELA ((map), (lazy)); } while (0)
#endif

View File

@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
#include <link.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h> /* Check if MAP_ANON is defined. */
#include "../stdio-common/_itoa.h"
@ -28,6 +29,7 @@ Cambridge, MA 02139, USA. */
/* This #define produces dynamic linking inline functions for
bootstrap relocation instead of general-purpose relocation. */
#define RTLD_BOOTSTRAP
#define RESOLVE(sym, reloc_addr, noplt) 0
#include "dynamic-link.h"
@ -79,7 +81,7 @@ _dl_start (void *arg)
/* Relocate ourselves so we can do normal function calls and
data access using the global offset table. */
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, NULL);
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
/* Now life is sane; we can call functions and access global data.

View File

@ -17,12 +17,12 @@ 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. */
#ifndef dl_machine_h
#define dl_machine_h
#define ELF_MACHINE_NAME "i386"
#include <assert.h>
#include <string.h>
#include <link.h>
/* Return nonzero iff E_MACHINE is compatible with the running host. */
static inline int
@ -68,102 +68,6 @@ elf_machine_load_address (void)
++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr; \
(dynamic_info)[DT_RELSZ]->d_un.d_val -= sizeof (Elf32_Rel);
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
static inline void
elf_machine_rel (struct link_map *map,
const Elf32_Rel *reloc, const Elf32_Sym *sym,
Elf32_Addr (*resolve) (const Elf32_Sym **ref,
Elf32_Addr reloc_addr,
int noplt))
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
Elf32_Addr loadbase;
#ifdef RTLD_BOOTSTRAP
#define RESOLVE(noplt) map->l_addr
#else
#define RESOLVE(noplt) (*resolve) (&sym, (Elf32_Addr) reloc_addr, noplt)
#endif
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_COPY:
loadbase = RESOLVE (0);
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
break;
case R_386_GLOB_DAT:
loadbase = RESOLVE (0);
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
break;
case R_386_JMP_SLOT:
loadbase = RESOLVE (1);
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
break;
case R_386_32:
{
Elf32_Addr undo = 0;
#ifndef RTLD_BOOTSTRAP
/* This is defined in rtld.c, but nowhere in the static libc.a;
make the reference weak so static programs can still link. This
declaration cannot be done when compiling rtld.c (i.e. #ifdef
RTLD_BOOTSTRAP) because rtld.c contains the common defn for
_dl_rtld_map, which is incompatible with a weak decl in the same
file. */
weak_extern (_dl_rtld_map);
if (map == &_dl_rtld_map)
/* Undo the relocation done here during bootstrapping. Now we will
relocate it anew, possibly using a binding found in the user
program or a loaded library rather than the dynamic linker's
built-in definitions used while loading those libraries. */
undo = map->l_addr + sym->st_value;
#endif
loadbase = RESOLVE (0);
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
break;
}
case R_386_RELATIVE:
if (!resolve || map != &_dl_rtld_map) /* Already done in rtld itself. */
*reloc_addr += map->l_addr;
break;
case R_386_PC32:
loadbase = RESOLVE (0);
*reloc_addr += ((sym ? (loadbase + sym->st_value) : 0) -
(Elf32_Addr) reloc_addr);
break;
case R_386_NONE: /* Alright, Wilbur. */
break;
default:
assert (! "unexpected dynamic reloc type");
break;
}
#undef RESOLVE
}
static inline void
elf_machine_lazy_rel (struct link_map *map, const Elf32_Rel *reloc)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_JMP_SLOT:
*reloc_addr += map->l_addr;
break;
default:
assert (! "unexpected PLT reloc type");
break;
}
}
/* Nonzero iff TYPE describes relocation of a PLT entry, so
PLT entries should not be allowed to define the value. */
#define elf_machine_pltrel_p(type) ((type) == R_386_JMP_SLOT)
/* The i386 never uses Elf32_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
@ -264,3 +168,97 @@ _dl_start_user:\n\
# Jump to the user's entry point.\n\
jmp *%edi\n\
");
/* Nonzero iff TYPE describes relocation of a PLT entry, so
PLT entries should not be allowed to define the value. */
#define elf_machine_pltrel_p(type) ((type) == R_386_JMP_SLOT)
/* The i386 never uses Elf32_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1
#endif /* !dl_machine_h */
#ifdef RESOLVE
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
MAP is the object containing the reloc. */
static inline void
elf_machine_rel (struct link_map *map,
const Elf32_Rel *reloc, const Elf32_Sym *sym)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
Elf32_Addr loadbase;
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_COPY:
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
memcpy (reloc_addr, (void *) (loadbase + sym->st_value), sym->st_size);
break;
case R_386_GLOB_DAT:
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
break;
case R_386_JMP_SLOT:
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 1);
*reloc_addr = sym ? (loadbase + sym->st_value) : 0;
break;
case R_386_32:
{
Elf32_Addr undo = 0;
#ifndef RTLD_BOOTSTRAP
/* This is defined in rtld.c, but nowhere in the static libc.a;
make the reference weak so static programs can still link. This
declaration cannot be done when compiling rtld.c (i.e. #ifdef
RTLD_BOOTSTRAP) because rtld.c contains the common defn for
_dl_rtld_map, which is incompatible with a weak decl in the same
file. */
weak_extern (_dl_rtld_map);
if (map == &_dl_rtld_map)
/* Undo the relocation done here during bootstrapping. Now we will
relocate it anew, possibly using a binding found in the user
program or a loaded library rather than the dynamic linker's
built-in definitions used while loading those libraries. */
undo = map->l_addr + sym->st_value;
#endif
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
*reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo;
break;
}
case R_386_RELATIVE:
#ifndef RTLD_BOOTSTRAP
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
#endif
*reloc_addr += map->l_addr;
break;
case R_386_PC32:
loadbase = RESOLVE (&sym, (Elf32_Addr) reloc_addr, 0);
*reloc_addr += ((sym ? (loadbase + sym->st_value) : 0) -
(Elf32_Addr) reloc_addr);
break;
case R_386_NONE: /* Alright, Wilbur. */
break;
default:
assert (! "unexpected dynamic reloc type");
break;
}
}
static inline void
elf_machine_lazy_rel (struct link_map *map, const Elf32_Rel *reloc)
{
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
switch (ELF32_R_TYPE (reloc->r_info))
{
case R_386_JMP_SLOT:
*reloc_addr += map->l_addr;
break;
default:
assert (! "unexpected PLT reloc type");
break;
}
}
#endif /* RESOLVE */