mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-25 14:30:06 +00:00
* 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:
parent
c928de7902
commit
f51d1dfd35
16
ChangeLog
16
ChangeLog
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
12
elf/do-rel.h
12
elf/do-rel.h
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user