mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* mach/Makefile (server-interfaces): Removed notify and device_reply. For shlibs with eager binding, libmachuser.so must not refer to any functions not defined in libc.
This commit is contained in:
parent
4174072112
commit
a1a9d21596
@ -1,3 +1,9 @@
|
|||||||
|
Tue May 30 15:52:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* mach/Makefile (server-interfaces): Removed notify and
|
||||||
|
device_reply. For shlibs with eager binding, libmachuser.so must
|
||||||
|
not refer to any functions not defined in libc.
|
||||||
|
|
||||||
Sat May 27 16:23:22 1995 Jim Meyering (meyering@comco.com)
|
Sat May 27 16:23:22 1995 Jim Meyering (meyering@comco.com)
|
||||||
|
|
||||||
* sysdeps/generic/memchr.c: Cast RHS to const unsigned char *
|
* sysdeps/generic/memchr.c: Cast RHS to const unsigned char *
|
||||||
|
@ -43,8 +43,14 @@ _dl_catch_error (const char **errstring,
|
|||||||
|
|
||||||
signalled_errstring = signalled_objname = NULL;
|
signalled_errstring = signalled_objname = NULL;
|
||||||
errcode = setjmp (catch_env);
|
errcode = setjmp (catch_env);
|
||||||
(*operate) ();
|
if (errcode == 0)
|
||||||
|
{
|
||||||
|
(*operate) ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We get here only if we longjmp'd out of OPERATE. */
|
||||||
*errstring = signalled_errstring;
|
*errstring = signalled_errstring;
|
||||||
*objname = signalled_objname;
|
*objname = signalled_objname;
|
||||||
return *errstring ? errcode : 0;
|
return errcode == -1 ? 0 : errcode;
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,5 @@ _dl_fini (void)
|
|||||||
|
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
for (l = _dl_loaded; l; l = l->l_next)
|
||||||
if (l->l_init_called && l->l_info[DT_FINI])
|
if (l->l_init_called && l->l_info[DT_FINI])
|
||||||
(*(void (*) (void)) l->l_info[DT_FINI]->d_un.d_ptr) ();
|
(*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||||
}
|
}
|
||||||
|
@ -46,15 +46,17 @@ _dl_init_next (void)
|
|||||||
{
|
{
|
||||||
/* Find each dependency in order, and see if it
|
/* Find each dependency in order, and see if it
|
||||||
needs to run an initializer. */
|
needs to run an initializer. */
|
||||||
|
const char *strtab
|
||||||
|
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
const Elf32_Dyn *d;
|
const Elf32_Dyn *d;
|
||||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||||
if (d->d_tag == DT_NEEDED)
|
if (d->d_tag == DT_NEEDED)
|
||||||
{
|
{
|
||||||
struct link_map *needed = _dl_map_object
|
struct link_map *needed
|
||||||
(l, (const char *) (l->l_addr + d->d_un.d_ptr), NULL);
|
= _dl_map_object (l, strtab + d->d_un.d_val, NULL);
|
||||||
Elf32_Addr init;
|
Elf32_Addr init;
|
||||||
--needed->l_opencount;
|
--needed->l_opencount;
|
||||||
init = next_init (l); /* Recurse on this dependency. */
|
init = next_init (needed); /* Recurse on this dependency. */
|
||||||
if (init != 0)
|
if (init != 0)
|
||||||
return init;
|
return init;
|
||||||
}
|
}
|
||||||
@ -74,7 +76,7 @@ _dl_init_next (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Look for the first initializer not yet called. */
|
/* Look for the first initializer not yet called. */
|
||||||
l = _dl_loaded;
|
l = _dl_loaded->l_next; /* Skip the executable itself. */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
init = next_init (l);
|
init = next_init (l);
|
||||||
|
@ -158,11 +158,12 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||||||
|
|
||||||
size_t namelen = strlen (name) + 1;
|
size_t namelen = strlen (name) + 1;
|
||||||
|
|
||||||
void trypath (const char *dirpath)
|
inline void trypath (const char *dirpath)
|
||||||
{
|
{
|
||||||
fd = open_path (name, namelen, dirpath, &realname);
|
fd = open_path (name, namelen, dirpath, &realname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fd = -1;
|
||||||
if (loader && loader->l_info[DT_RPATH])
|
if (loader && loader->l_info[DT_RPATH])
|
||||||
trypath ((const char *) (loader->l_addr +
|
trypath ((const char *) (loader->l_addr +
|
||||||
loader->l_info[DT_RPATH]->d_un.d_ptr));
|
loader->l_info[DT_RPATH]->d_un.d_ptr));
|
||||||
@ -317,14 +318,14 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||||||
if (ph->p_memsz > ph->p_filesz)
|
if (ph->p_memsz > ph->p_filesz)
|
||||||
{
|
{
|
||||||
/* Extra zero pages should appear at the end of this segment,
|
/* Extra zero pages should appear at the end of this segment,
|
||||||
after the data mapped from the file. Adjust MAPEND to map
|
after the data mapped from the file. */
|
||||||
only the data from the file. We will later allocate zero
|
caddr_t zero, zeroend, zeropage;
|
||||||
pages following the data mapping. */
|
|
||||||
caddr_t zero = mapat - mapstart + ph->p_filesz;
|
mapat += ph->p_vaddr - mapstart;
|
||||||
caddr_t zeroend = mapat - mapstart + ph->p_memsz;
|
zero = mapat + ph->p_filesz;
|
||||||
caddr_t zeropage
|
zeroend = mapat + ph->p_memsz;
|
||||||
= (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
|
zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
|
||||||
& ~(pagesize - 1));
|
& ~(pagesize - 1));
|
||||||
|
|
||||||
if (zeroend < zeropage)
|
if (zeroend < zeropage)
|
||||||
/* All the extra data is in the last page of the segment.
|
/* All the extra data is in the last page of the segment.
|
||||||
@ -342,7 +343,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||||||
prot|PROT_WRITE) < 0)
|
prot|PROT_WRITE) < 0)
|
||||||
lose (errno, "cannot change memory protections");
|
lose (errno, "cannot change memory protections");
|
||||||
}
|
}
|
||||||
memset (zero, 0, zeroend - zero);
|
memset (zero, 0, zeropage - zero);
|
||||||
if ((prot & PROT_WRITE) == 0)
|
if ((prot & PROT_WRITE) == 0)
|
||||||
mprotect ((caddr_t) ((Elf32_Addr) zero
|
mprotect ((caddr_t) ((Elf32_Addr) zero
|
||||||
& ~(pagesize - 1)),
|
& ~(pagesize - 1)),
|
||||||
|
@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
/* Search loaded objects' symbol tables for a definition of
|
/* Search loaded objects' symbol tables for a definition of
|
||||||
the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since
|
the symbol UNDEF_NAME. Don't use a PLT defn in UNDEF_MAP, since
|
||||||
@ -70,13 +71,13 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sym == *ref)
|
if (sym->st_shndx == SHN_UNDEF)
|
||||||
/* This is the same symbol we are looking for the value for.
|
/* This is the same symbol we are looking for the value for.
|
||||||
If it is a PLT entry, it will have a value of its own;
|
If it is a PLT entry, it will have a value of its own;
|
||||||
but that is not what we are looking for. */
|
but that is not what we are looking for. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp (strtab + sym->st_name, undef_name))
|
if (sym != *ref && strcmp (strtab + sym->st_name, undef_name))
|
||||||
/* Not the symbol we are looking for. */
|
/* Not the symbol we are looking for. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -106,8 +107,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
|||||||
const char msg[] = "undefined symbol: ";
|
const char msg[] = "undefined symbol: ";
|
||||||
char buf[sizeof msg + strlen (undef_name)];
|
char buf[sizeof msg + strlen (undef_name)];
|
||||||
memcpy (buf, msg, sizeof msg - 1);
|
memcpy (buf, msg, sizeof msg - 1);
|
||||||
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg);
|
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
|
||||||
_dl_signal_error (0, reference_name, msg);
|
_dl_signal_error (0, reference_name, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ref = weak_value.s;
|
*ref = weak_value.s;
|
||||||
|
@ -83,7 +83,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
l->l_prev->l_next = l;
|
l->l_prev->l_next = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->l_info[DT_JMPREL] && ! lazy)
|
if (l->l_info[DT_JMPREL] && lazy)
|
||||||
/* Set up the PLT so its unrelocated entries will
|
/* Set up the PLT so its unrelocated entries will
|
||||||
jump to _dl_runtime_resolve, which will relocate them. */
|
jump to _dl_runtime_resolve, which will relocate them. */
|
||||||
elf_machine_runtime_setup (l);
|
elf_machine_runtime_setup (l);
|
||||||
|
53
elf/do-rel.h
53
elf/do-rel.h
@ -30,37 +30,46 @@ 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. *RESOLVE is called to resolve symbol values; it
|
||||||
modifies its argument pointer to point to the defining symbol, and
|
modifies its argument pointer to point to the defining symbol, and
|
||||||
returns the base load address of the defining object. */
|
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. */
|
||||||
|
|
||||||
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,
|
||||||
Elf32_Addr (*resolve) (const Elf32_Sym **))
|
Elf32_Addr (*resolve) (const Elf32_Sym **),
|
||||||
|
int lazy)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *const symtab
|
const Elf32_Sym *const symtab
|
||||||
= (const Elf32_Sym *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
|
= (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||||
const Elf32_Rel *r = (const Elf32_Rel *) map->l_info[reltag]->d_un.d_ptr;
|
const Elf32_Rel *r
|
||||||
|
= (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr);
|
||||||
const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
|
const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
|
||||||
|
|
||||||
for (; r < end; ++r)
|
if (lazy)
|
||||||
{
|
/* Doing lazy PLT relocations; they need very little info. */
|
||||||
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
|
for (; r < end; ++r)
|
||||||
Elf32_Addr loadbase;
|
elf_machine_lazy_rel (map, r);
|
||||||
|
else
|
||||||
|
for (; r < end; ++r)
|
||||||
|
{
|
||||||
|
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
|
||||||
|
Elf32_Addr loadbase;
|
||||||
|
|
||||||
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
|
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
|
||||||
loadbase = 0; /* This value will not be consulted. */
|
loadbase = 0; /* This value will not be consulted. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (resolve)
|
if (resolve)
|
||||||
loadbase = (*resolve) (&definer);
|
loadbase = (*resolve) (&definer);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert (definer->st_shndx != SHN_UNDEF);
|
assert (definer->st_shndx != SHN_UNDEF);
|
||||||
loadbase = map->l_addr;
|
loadbase = map->l_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elf_machine_rel (map, r, loadbase, definer);
|
elf_machine_rel (map, r, loadbase, definer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef elf_dynamic_do_rel
|
#undef elf_dynamic_do_rel
|
||||||
|
@ -56,9 +56,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
|
|||||||
#include "do-rel.h"
|
#include "do-rel.h"
|
||||||
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
|
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
|
||||||
if ((map)->l_info[DT_REL]) \
|
if ((map)->l_info[DT_REL]) \
|
||||||
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \
|
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve), 0); \
|
||||||
if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
|
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
|
||||||
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve));
|
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
|
||||||
#else
|
#else
|
||||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||||
#endif
|
#endif
|
||||||
@ -68,9 +68,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
|
|||||||
#include "do-rel.h"
|
#include "do-rel.h"
|
||||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
|
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
|
||||||
if ((map)->l_info[DT_RELA]) \
|
if ((map)->l_info[DT_RELA]) \
|
||||||
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve)); \
|
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve), 0); \
|
||||||
if (!(lazy) && (map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
|
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
|
||||||
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve);
|
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
|
||||||
#else
|
#else
|
||||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,6 +93,8 @@ _dl_start (void *arg)
|
|||||||
|
|
||||||
void _start (void);
|
void _start (void);
|
||||||
|
|
||||||
|
static int rtld_command; /* Nonzero if we were run directly. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dl_main (const Elf32_Phdr *phdr,
|
dl_main (const Elf32_Phdr *phdr,
|
||||||
Elf32_Word phent,
|
Elf32_Word phent,
|
||||||
@ -138,6 +140,7 @@ file you run. This is mostly of use for maintainers to test new versions\n\
|
|||||||
of this helper program; chances are you did not intend to run this program.\n"
|
of this helper program; chances are you did not intend to run this program.\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rtld_command = 1;
|
||||||
interpreter_name = _dl_argv[0];
|
interpreter_name = _dl_argv[0];
|
||||||
--_dl_argc;
|
--_dl_argc;
|
||||||
++_dl_argv;
|
++_dl_argv;
|
||||||
@ -164,7 +167,7 @@ of this helper program; chances are you did not intend to run this program.\n"
|
|||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
/* This tells us where to find the dynamic section,
|
/* This tells us where to find the dynamic section,
|
||||||
which tells us everything we need to do. */
|
which tells us everything we need to do. */
|
||||||
l->l_ld = (void *) ph->p_vaddr;
|
l->l_ld = (void *) l->l_addr + ph->p_vaddr;
|
||||||
break;
|
break;
|
||||||
case PT_INTERP:
|
case PT_INTERP:
|
||||||
/* This "interpreter segment" was used by the program loader to
|
/* This "interpreter segment" was used by the program loader to
|
||||||
@ -173,7 +176,7 @@ of this helper program; chances are you did not intend to run this program.\n"
|
|||||||
dlopen call or DT_NEEDED entry, for something that wants to link
|
dlopen call or DT_NEEDED entry, for something that wants to link
|
||||||
against the dynamic linker as a shared library, will know that
|
against the dynamic linker as a shared library, will know that
|
||||||
the shared object is already loaded. */
|
the shared object is already loaded. */
|
||||||
interpreter_name = (void *) ph->p_vaddr;
|
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert (interpreter_name); /* How else did we get here? */
|
assert (interpreter_name); /* How else did we get here? */
|
||||||
@ -220,7 +223,7 @@ of this helper program; chances are you did not intend to run this program.\n"
|
|||||||
l->l_next->l_prev = l->l_prev;
|
l->l_next->l_prev = l->l_prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy = _dl_secure || *(getenv ("LD_BIND_NOW") ?: "");
|
lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||||
|
|
||||||
/* Now we have all the objects loaded. Relocate them all.
|
/* Now we have all the objects loaded. Relocate them all.
|
||||||
We do this in reverse order so that copy relocs of earlier
|
We do this in reverse order so that copy relocs of earlier
|
||||||
|
@ -75,7 +75,7 @@ elf_machine_rel (struct link_map *map,
|
|||||||
const Elf32_Rel *reloc,
|
const Elf32_Rel *reloc,
|
||||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
|
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
|
||||||
{
|
{
|
||||||
Elf32_Addr *const reloc_addr = (Elf32_Addr *) reloc->r_offset;
|
Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
|
||||||
const Elf32_Addr sym_value = sym_loadaddr + sym->st_value;
|
const Elf32_Addr sym_value = sym_loadaddr + sym->st_value;
|
||||||
|
|
||||||
switch (ELF32_R_TYPE (reloc->r_info))
|
switch (ELF32_R_TYPE (reloc->r_info))
|
||||||
@ -102,6 +102,20 @@ elf_machine_rel (struct link_map *map,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The i386 never uses Elf32_Rela relocations. */
|
/* The i386 never uses Elf32_Rela relocations. */
|
||||||
#define ELF_MACHINE_NO_RELA 1
|
#define ELF_MACHINE_NO_RELA 1
|
||||||
@ -113,12 +127,14 @@ elf_machine_rel (struct link_map *map,
|
|||||||
static inline void
|
static inline void
|
||||||
elf_machine_runtime_setup (struct link_map *l)
|
elf_machine_runtime_setup (struct link_map *l)
|
||||||
{
|
{
|
||||||
|
Elf32_Addr *got;
|
||||||
extern void _dl_runtime_resolve (Elf32_Word);
|
extern void _dl_runtime_resolve (Elf32_Word);
|
||||||
|
|
||||||
/* The GOT entries for functions in the PLT have not yet been filled
|
/* The GOT entries for functions in the PLT have not yet been filled
|
||||||
in. Their initial contents will arrange when called to push an
|
in. Their initial contents will arrange when called to push an
|
||||||
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
Elf32_Addr *got = (Elf32_Addr *) l->l_info[DT_PLTGOT]->d_un.d_ptr;
|
got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
|
||||||
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
||||||
/* This function will get called to fix up the GOT entry indicated by
|
/* This function will get called to fix up the GOT entry indicated by
|
||||||
the offset on the stack, and then jump to the resolved address. */
|
the offset on the stack, and then jump to the resolved address. */
|
||||||
@ -140,9 +156,20 @@ _dl_start_user:\n\
|
|||||||
# Save the user entry point address in %edi.\n\
|
# Save the user entry point address in %edi.\n\
|
||||||
movl %eax, %edi\n\
|
movl %eax, %edi\n\
|
||||||
# Point %ebx at the GOT.
|
# Point %ebx at the GOT.
|
||||||
1: call 2f\n\
|
call 0f\n\
|
||||||
2: popl %ebx\n\
|
0: popl %ebx\n\
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx\n\
|
addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx\n\
|
||||||
|
# See if we were run as a command with the executable file\n\
|
||||||
|
# name as an extra leading argument.\n\
|
||||||
|
movl rtld_command@GOT(%ebx), %eax\n\
|
||||||
|
movl (%eax),%eax\n\
|
||||||
|
testl %eax,%eax\n\
|
||||||
|
jz 0f\n\
|
||||||
|
# Pop the original argument count, decrement it, and replace\n\
|
||||||
|
# the original first argument pointer with the new count.\n\
|
||||||
|
popl %eax\n\
|
||||||
|
decl %eax\n\
|
||||||
|
movl %eax,(%esp)\n\
|
||||||
# Call _dl_init_next to return the address of an initializer\n\
|
# Call _dl_init_next to return the address of an initializer\n\
|
||||||
# function to run.\n\
|
# function to run.\n\
|
||||||
0: call _dl_init_next@PLT\n\
|
0: call _dl_init_next@PLT\n\
|
||||||
@ -150,7 +177,7 @@ _dl_start_user:\n\
|
|||||||
testl %eax,%eax\n\
|
testl %eax,%eax\n\
|
||||||
jz 1f\n\
|
jz 1f\n\
|
||||||
# Call the shared object initializer function.\n\
|
# Call the shared object initializer function.\n\
|
||||||
# NOTE: We depend only on the registers (%ebx)\n\
|
# NOTE: We depend only on the registers (%ebx and %edi)\n\
|
||||||
# and the return address pushed by this call;\n\
|
# and the return address pushed by this call;\n\
|
||||||
# the initializer is called with the stack just\n\
|
# the initializer is called with the stack just\n\
|
||||||
# as it appears on entry, and it is free to move\n\
|
# as it appears on entry, and it is free to move\n\
|
||||||
@ -159,8 +186,8 @@ _dl_start_user:\n\
|
|||||||
call *%eax\n\
|
call *%eax\n\
|
||||||
# Loop to call _dl_init_next for the next initializer.\n\
|
# Loop to call _dl_init_next for the next initializer.\n\
|
||||||
jmp 0b\n\
|
jmp 0b\n\
|
||||||
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
|
1: # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
|
||||||
leal _dl_fini@GOT(%ebx), %edx\n\
|
movl _dl_fini@GOT(%ebx), %edx\n\
|
||||||
# Jump to the user's entry point.\n\
|
# Jump to the user's entry point.\n\
|
||||||
jmp *%edi\n\
|
jmp *%edi\n\
|
||||||
");
|
");
|
||||||
|
@ -34,15 +34,16 @@ void
|
|||||||
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
||||||
{
|
{
|
||||||
__label__ return_insn;
|
__label__ return_insn;
|
||||||
struct link_map *l = (void *) &(&reloc_offset)[-1];
|
struct link_map *l = (void *) (&reloc_offset)[-1];
|
||||||
|
|
||||||
const Elf32_Sym *const symtab
|
const Elf32_Sym *const symtab
|
||||||
= (const Elf32_Sym *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
|
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||||
const char *strtab
|
const char *strtab =
|
||||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
(const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
|
|
||||||
const Elf32_Rel *const reloc = (void *) (l->l_info[DT_JMPREL]->d_un.d_ptr
|
const Elf32_Rel *const reloc
|
||||||
+ reloc_offset);
|
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
||||||
|
reloc_offset);
|
||||||
|
|
||||||
const Elf32_Sym *definer;
|
const Elf32_Sym *definer;
|
||||||
Elf32_Addr loadbase;
|
Elf32_Addr loadbase;
|
||||||
@ -83,7 +84,7 @@ _dl_runtime_resolve (Elf32_Word reloc_offset)
|
|||||||
referred to by this PLT entry; once "ret" pops this address, the
|
referred to by this PLT entry; once "ret" pops this address, the
|
||||||
function in the shared object will run with the stack arranged just as
|
function in the shared object will run with the stack arranged just as
|
||||||
when the user entered the PLT. */
|
when the user entered the PLT. */
|
||||||
(&reloc_offset)[0] = *(Elf32_Word *) reloc->r_offset;
|
(&reloc_offset)[0] = *(Elf32_Word *) (l->l_addr + reloc->r_offset);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
#include "dl-machine.h"
|
#include "dl-machine.h"
|
||||||
|
|
||||||
|
extern void __mach_init (void);
|
||||||
|
|
||||||
extern int _dl_argc;
|
extern int _dl_argc;
|
||||||
extern char **_dl_argv;
|
extern char **_dl_argv;
|
||||||
extern char **_environ;
|
extern char **_environ;
|
||||||
@ -52,8 +54,8 @@ _dl_sysdep_start (void **start_argptr,
|
|||||||
char **p;
|
char **p;
|
||||||
|
|
||||||
/* Cache the information in various global variables. */
|
/* Cache the information in various global variables. */
|
||||||
_dl_argc = *argdata++;
|
_dl_argc = *argdata;
|
||||||
_dl_argv = (void *) argdata;
|
_dl_argv = (void *) &argdata[1];
|
||||||
_environ = &_dl_argv[_dl_argc + 1];
|
_environ = &_dl_argv[_dl_argc + 1];
|
||||||
for (p = _environ; *p; ++p);
|
for (p = _environ; *p; ++p);
|
||||||
_dl_hurd_data = (void *) ++p;
|
_dl_hurd_data = (void *) ++p;
|
||||||
@ -66,6 +68,12 @@ _dl_sysdep_start (void **start_argptr,
|
|||||||
_dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
|
_dl_hurd_data->phdrsz / sizeof (Elf32_Phdr),
|
||||||
&_dl_hurd_data->user_entry);
|
&_dl_hurd_data->user_entry);
|
||||||
|
|
||||||
|
/* Deallocate the reply port and task port rights acquired by
|
||||||
|
__mach_init. We are done with them now, and the user will
|
||||||
|
reacquire them for himself when he wants them. */
|
||||||
|
__mig_dealloc_reply_port (MACH_PORT_NULL);
|
||||||
|
__mach_port_deallocate (__mach_task_self (), __mach_task_self_);
|
||||||
|
|
||||||
{
|
{
|
||||||
extern void _dl_start_user (void);
|
extern void _dl_start_user (void);
|
||||||
/* Unwind the stack to ARGDATA and simulate a return from _dl_start
|
/* Unwind the stack to ARGDATA and simulate a return from _dl_start
|
||||||
@ -74,6 +82,9 @@ _dl_sysdep_start (void **start_argptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set up so we can do RPCs. */
|
||||||
|
__mach_init ();
|
||||||
|
|
||||||
/* See hurd/hurdstartup.c; this deals with getting information
|
/* See hurd/hurdstartup.c; this deals with getting information
|
||||||
from the exec server and slicing up the arguments.
|
from the exec server and slicing up the arguments.
|
||||||
Then it will call `go', above. */
|
Then it will call `go', above. */
|
||||||
|
@ -95,8 +95,8 @@ init1 (int argc, char *arg0, ...)
|
|||||||
__libc_init (argc, argv, __environ);
|
__libc_init (argc, argv, __environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init (int *data, int retaddr)
|
init (int *data, void *usercode, void **retaddrloc)
|
||||||
{
|
{
|
||||||
int argc = *data;
|
int argc = *data;
|
||||||
char **argv = (void *) (data + 1);
|
char **argv = (void *) (data + 1);
|
||||||
@ -115,6 +115,11 @@ init (int *data, int retaddr)
|
|||||||
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
|
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
|
||||||
__hurd_threadvar_max = _HURD_THREADVAR_MAX;
|
__hurd_threadvar_max = _HURD_THREADVAR_MAX;
|
||||||
|
|
||||||
|
|
||||||
|
/* After possibly switching stacks, call `init1' (above) with the user
|
||||||
|
code as the return address, and the argument data immediately above
|
||||||
|
that on the stack. */
|
||||||
|
|
||||||
if (_cthread_init_routine)
|
if (_cthread_init_routine)
|
||||||
{
|
{
|
||||||
/* Initialize cthreads, which will allocate us a new stack to run on. */
|
/* Initialize cthreads, which will allocate us a new stack to run on. */
|
||||||
@ -136,13 +141,45 @@ init (int *data, int retaddr)
|
|||||||
/* Copy the Hurd startup data block to the new stack. */
|
/* Copy the Hurd startup data block to the new stack. */
|
||||||
*od = *d;
|
*od = *d;
|
||||||
|
|
||||||
data = newsp;
|
/* Push the user code address on the top of the new stack. It will
|
||||||
|
be the return address for `init1'; we will jump there with NEWSP
|
||||||
|
as the stack pointer. */
|
||||||
|
*--(void **) newsp = usercode;
|
||||||
|
/* Mutate our own return address to run the code below. */
|
||||||
|
*retaddrloc = &&switch_stacks;
|
||||||
|
/* Force NEWSP into %ecx and &init1 into %eax, which are not restored
|
||||||
|
by function return. */
|
||||||
|
asm volatile ("# a %0 c %1" : : "a" (&init1), "c" (newsp));
|
||||||
|
return;
|
||||||
|
switch_stacks:
|
||||||
|
/* Our return address was redirected to here, so at this point our
|
||||||
|
stack is unwound and callers' registers restored. Only %ecx and
|
||||||
|
%eax are call-clobbered and thus still have the values we set just
|
||||||
|
above. Fetch from there the new stack pointer we will run on, and
|
||||||
|
jmp to the run-time address of `init1'; when it returns, it will
|
||||||
|
run the user code with the argument data at the top of the stack. */
|
||||||
|
asm volatile ("movl %ecx, %esp; jmp *%eax");
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We are not switching stacks, but we must play some games with
|
||||||
|
the one we've got, similar to the stack-switching code above. */
|
||||||
|
*retaddrloc = &&call_init1;
|
||||||
|
/* Force the user code address into %ecx and the run-time address of
|
||||||
|
`init1' into %eax, for use below. */
|
||||||
|
asm volatile ("# a %0 c %1" : : "a" (&init1), "c" (usercode));
|
||||||
|
return;
|
||||||
|
call_init1:
|
||||||
|
/* As in the stack-switching case, at this point our stack is unwound
|
||||||
|
and callers' registers restored, and only %ecx and %eax
|
||||||
|
communicate values from the lines above. In this case we have
|
||||||
|
stashed in %ecx the user code return address. Push it on the top
|
||||||
|
of the stack so it acts as init1's return address, and then jump
|
||||||
|
there. */
|
||||||
|
asm volatile ("pushl %ecx; jmp *%eax");
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call `init1' (above) with the user code as the return address,
|
|
||||||
and the argument data immediately above that on the stack. */
|
|
||||||
*--data = retaddr;
|
|
||||||
asm volatile ("movl %0, %%esp; jmp %*%1" : : "g" (data), "r" (&init1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -151,30 +188,32 @@ init (int *data, int retaddr)
|
|||||||
It is called just before the user _start code from i386/elf/start.S,
|
It is called just before the user _start code from i386/elf/start.S,
|
||||||
with the stack set up as that code gets it. */
|
with the stack set up as that code gets it. */
|
||||||
|
|
||||||
static void soinit (int argc, ...) __attribute__ ((unused, section (".init")));
|
/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT
|
||||||
|
pointer in the dynamic section based solely on that. It is convention
|
||||||
|
for this function to be in the `.init' section, but the symbol name is
|
||||||
|
the only thing that really matters!! */
|
||||||
|
/*void _init (int argc, ...) __attribute__ ((unused, section (".init")));*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
soinit (int argc, ...)
|
_init (int argc, ...)
|
||||||
{
|
{
|
||||||
/* Initialize data structures so we can do RPCs. */
|
/* Initialize data structures so we can do RPCs. */
|
||||||
__mach_init ();
|
__mach_init ();
|
||||||
|
|
||||||
RUN_HOOK (_hurd_preinit_hook, ());
|
RUN_HOOK (_hurd_preinit_hook, ());
|
||||||
|
|
||||||
init (&argc, (&argc)[-1]);
|
init (&argc, ((void **) &argc)[-1], &((void **) &argc)[-1]);
|
||||||
|
|
||||||
(void) &soinit; /* Avoid gcc optimizing this fn out. */
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
__libc_init_first (int argc, ...)
|
__libc_init_first (int argc __attribute__ ((unused)), ...)
|
||||||
{
|
{
|
||||||
#ifndef PIC
|
#ifndef PIC
|
||||||
void doinit (int *data)
|
void doinit (int *data)
|
||||||
{
|
{
|
||||||
init (data, (&argc)[-1]);
|
init (data, ((void **) &argc)[-1], &((void **) &data)[-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize data structures so we can do RPCs. */
|
/* Initialize data structures so we can do RPCs. */
|
||||||
|
Loading…
Reference in New Issue
Block a user