diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | elf/dl-reloc.c | 16 | ||||
-rw-r--r-- | elf/dl-runtime.c | 21 | ||||
-rw-r--r-- | elf/do-rel.h | 12 | ||||
-rw-r--r-- | elf/dynamic-link.h | 26 | ||||
-rw-r--r-- | elf/rtld.c | 4 | ||||
-rw-r--r-- | sysdeps/i386/dl-machine.h | 196 |
7 files changed, 154 insertions, 137 deletions
diff --git a/ChangeLog b/ChangeLog index 256151e35e..0a3946203c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index e6778e7de3..5adf0f6dac 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -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 diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index cdacd756ef..2785592c44 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -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; diff --git a/elf/do-rel.h b/elf/do-rel.h index ebf2e84a64..25da59252f 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index b69cb3fd43..45b6b2dcde 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -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 diff --git a/elf/rtld.c b/elf/rtld.c index 2e23d9cb38..1058d87150 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -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. diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 7a61aaad4c..dc88b043ea 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -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 */ |