* 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> 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-deps.c (_dl_map_object_deps): Start TAILP at last preload.
* elf/dl-open.c (_dl_open): Force an indirect call for * 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 <errno.h>
#include "dynamic-link.h" #include "dynamic-link.h"
void void
_dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) _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. */ 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) 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 /* 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. */ Cambridge, MA 02139, USA. */
#include <link.h> #include <link.h>
#include "dynamic-link.h"
/* The global scope we will use for symbol lookups. /* 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. */ /* 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
@ -118,14 +119,16 @@ fixup (
/* Set up the scope to find symbols referenced by this object. */ /* Set up the scope to find symbols referenced by this object. */
struct link_map **scope = _dl_object_relocation_scope (l); struct link_map **scope = _dl_object_relocation_scope (l);
/* Perform the specified relocation. */ {
ElfW(Addr) resolve (const ElfW(Sym) **ref, /* This macro is used as a callback from the elf_machine_relplt code. */
ElfW(Addr) reloc_addr, int noplt) #define RESOLVE(ref, reloc_addr, noplt) \
{ (_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, l->l_name, reloc_addr, noplt))
scope, l->l_name, reloc_addr, noplt); #include "dynamic-link.h"
}
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve); /* Perform the specified relocation. */
elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)]);
}
*_dl_global_scope_end = NULL; *_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 /* Perform the relocations in MAP on the running program image as specified
by RELTAG, SZTAG. *RESOLVE is called to resolve symbol values; it by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
modifies its argument pointer to point to the defining symbol, and relocations; they should be set up to call _dl_runtime_resolve, rather
returns the base load address of the defining object. If LAZY is than fully resolved now. */
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 static inline void
elf_dynamic_do_rel (struct link_map *map, elf_dynamic_do_rel (struct link_map *map,
int reltag, int sztag, int reltag, int sztag,
ElfW(Addr) (*resolve) (const ElfW(Sym) **symbol,
ElfW(Addr) reloc_addr, int noplt),
int lazy) int lazy)
{ {
const ElfW(Sym) *const symtab const ElfW(Sym) *const symtab
@ -53,7 +49,7 @@ elf_dynamic_do_rel (struct link_map *map,
elf_machine_lazy_rel (map, r); elf_machine_lazy_rel (map, r);
else else
for (; r < end; ++r) 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 #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); info[DT_PLTREL]->d_un.d_val == DT_RELA);
} }
#ifdef RESOLVE
/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. /* 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 These functions are almost identical, so we use cpp magic to avoid
duplicating their code. It cannot be done in a more general function 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 #if ! ELF_MACHINE_NO_REL
#include "do-rel.h" #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]) \ 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] && \ if ((map)->l_info[DT_PLTREL] && \
(map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \ (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 #else
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) /* Nothing to do. */ #define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */
#endif #endif
#if ! ELF_MACHINE_NO_RELA #if ! ELF_MACHINE_NO_RELA
#define DO_RELA #define DO_RELA
#include "do-rel.h" #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]) \ 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] && \ if ((map)->l_info[DT_PLTREL] && \
(map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \ (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 #else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */ #define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */
#endif #endif
/* This can't just be an inline function because GCC is too dumb /* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */ to inline functions containing inlines themselves. */
#define ELF_DYNAMIC_RELOCATE(map, lazy, resolve) \ #define ELF_DYNAMIC_RELOCATE(map, lazy) \
do { ELF_DYNAMIC_DO_REL ((map), (lazy), (resolve)); \ do { ELF_DYNAMIC_DO_REL ((map), (lazy)); \
ELF_DYNAMIC_DO_RELA ((map), (lazy), (resolve)); } while (0) ELF_DYNAMIC_DO_RELA ((map), (lazy)); } while (0)
#endif

View File

@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
#include <link.h> #include <link.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> /* Check if MAP_ANON is defined. */ #include <sys/mman.h> /* Check if MAP_ANON is defined. */
#include "../stdio-common/_itoa.h" #include "../stdio-common/_itoa.h"
@ -28,6 +29,7 @@ Cambridge, MA 02139, USA. */
/* This #define produces dynamic linking inline functions for /* This #define produces dynamic linking inline functions for
bootstrap relocation instead of general-purpose relocation. */ bootstrap relocation instead of general-purpose relocation. */
#define RTLD_BOOTSTRAP #define RTLD_BOOTSTRAP
#define RESOLVE(sym, reloc_addr, noplt) 0
#include "dynamic-link.h" #include "dynamic-link.h"
@ -79,7 +81,7 @@ _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. */
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. /* 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, not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */ Cambridge, MA 02139, USA. */
#ifndef dl_machine_h
#define dl_machine_h
#define ELF_MACHINE_NAME "i386" #define ELF_MACHINE_NAME "i386"
#include <assert.h> #include <assert.h>
#include <string.h>
#include <link.h>
/* Return nonzero iff E_MACHINE is compatible with the running host. */ /* Return nonzero iff E_MACHINE is compatible with the running host. */
static inline int static inline int
@ -68,102 +68,6 @@ elf_machine_load_address (void)
++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr; \ ++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr; \
(dynamic_info)[DT_RELSZ]->d_un.d_val -= sizeof (Elf32_Rel); (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 /* 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. */ 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\ # Jump to the user's entry point.\n\
jmp *%edi\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 */