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:
Roland McGrath 1995-05-31 13:23:14 +00:00
parent 4174072112
commit a1a9d21596
14 changed files with 193 additions and 87 deletions

View File

@ -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)
* sysdeps/generic/memchr.c: Cast RHS to const unsigned char *

View File

@ -43,8 +43,14 @@ _dl_catch_error (const char **errstring,
signalled_errstring = signalled_objname = NULL;
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;
*objname = signalled_objname;
return *errstring ? errcode : 0;
return errcode == -1 ? 0 : errcode;
}

View File

@ -26,5 +26,5 @@ _dl_fini (void)
for (l = _dl_loaded; l; l = l->l_next)
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)) ();
}

View File

@ -46,15 +46,17 @@ _dl_init_next (void)
{
/* Find each dependency in order, and see if it
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;
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_NEEDED)
{
struct link_map *needed = _dl_map_object
(l, (const char *) (l->l_addr + d->d_un.d_ptr), NULL);
struct link_map *needed
= _dl_map_object (l, strtab + d->d_un.d_val, NULL);
Elf32_Addr init;
--needed->l_opencount;
init = next_init (l); /* Recurse on this dependency. */
init = next_init (needed); /* Recurse on this dependency. */
if (init != 0)
return init;
}
@ -74,7 +76,7 @@ _dl_init_next (void)
}
/* Look for the first initializer not yet called. */
l = _dl_loaded;
l = _dl_loaded->l_next; /* Skip the executable itself. */
do
{
init = next_init (l);

View File

@ -158,11 +158,12 @@ _dl_map_object (struct link_map *loader, const char *name,
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 = -1;
if (loader && loader->l_info[DT_RPATH])
trypath ((const char *) (loader->l_addr +
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)
{
/* Extra zero pages should appear at the end of this segment,
after the data mapped from the file. Adjust MAPEND to map
only the data from the file. We will later allocate zero
pages following the data mapping. */
caddr_t zero = mapat - mapstart + ph->p_filesz;
caddr_t zeroend = mapat - mapstart + ph->p_memsz;
caddr_t zeropage
= (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
& ~(pagesize - 1));
after the data mapped from the file. */
caddr_t zero, zeroend, zeropage;
mapat += ph->p_vaddr - mapstart;
zero = mapat + ph->p_filesz;
zeroend = mapat + ph->p_memsz;
zeropage = (caddr_t) ((Elf32_Addr) (zero + pagesize - 1)
& ~(pagesize - 1));
if (zeroend < zeropage)
/* 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)
lose (errno, "cannot change memory protections");
}
memset (zero, 0, zeroend - zero);
memset (zero, 0, zeropage - zero);
if ((prot & PROT_WRITE) == 0)
mprotect ((caddr_t) ((Elf32_Addr) zero
& ~(pagesize - 1)),

View File

@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
#include <stddef.h>
#include <libelf.h>
#include <link.h>
#include <assert.h>
/* Search loaded objects' symbol tables for a definition of
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;
}
if (sym == *ref)
if (sym->st_shndx == SHN_UNDEF)
/* 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;
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. */
continue;
@ -106,8 +107,8 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
const char msg[] = "undefined symbol: ";
char buf[sizeof msg + strlen (undef_name)];
memcpy (buf, msg, sizeof msg - 1);
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg);
_dl_signal_error (0, reference_name, msg);
memcpy (&buf[sizeof msg - 1], undef_name, sizeof buf - sizeof msg + 1);
_dl_signal_error (0, reference_name, buf);
}
*ref = weak_value.s;

View File

@ -83,7 +83,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
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
jump to _dl_runtime_resolve, which will relocate them. */
elf_machine_runtime_setup (l);

View File

@ -30,37 +30,46 @@ 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. */
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
elf_dynamic_do_rel (struct link_map *map,
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 *) 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_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->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];
for (; r < end; ++r)
{
const Elf32_Sym *definer = &symtab[ELF32_R_SYM (r->r_info)];
Elf32_Addr loadbase;
if (lazy)
/* Doing lazy PLT relocations; they need very little info. */
for (; r < end; ++r)
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)
loadbase = 0; /* This value will not be consulted. */
else
{
if (resolve)
loadbase = (*resolve) (&definer);
else
{
assert (definer->st_shndx != SHN_UNDEF);
loadbase = map->l_addr;
}
}
elf_machine_rel (map, r, loadbase, definer);
}
if (ELF32_R_SYM (r->r_info) == STN_UNDEF)
loadbase = 0; /* This value will not be consulted. */
else
{
if (resolve)
loadbase = (*resolve) (&definer);
else
{
assert (definer->st_shndx != SHN_UNDEF);
loadbase = map->l_addr;
}
}
elf_machine_rel (map, r, loadbase, definer);
}
}
#undef elf_dynamic_do_rel

View File

@ -56,9 +56,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
#include "do-rel.h"
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
if ((map)->l_info[DT_REL]) \
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \
if (!(lazy) && (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_REL, DT_RELSZ, (resolve), 0); \
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_REL) \
elf_dynamic_do_rel ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
#else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
#endif
@ -68,9 +68,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
#include "do-rel.h"
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
if ((map)->l_info[DT_RELA]) \
elf_dynamic_do_rela ((map), DT_RELA, DT_RELASZ, (resolve)); \
if (!(lazy) && (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_RELA, DT_RELASZ, (resolve), 0); \
if ((map)->l_info[DT_PLTREL]->d_un.d_val == DT_RELA) \
elf_dynamic_do_rela ((map), DT_JMPREL, DT_PLTRELSZ, (resolve), (lazy));
#else
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
#endif

View File

@ -93,6 +93,8 @@ _dl_start (void *arg)
void _start (void);
static int rtld_command; /* Nonzero if we were run directly. */
static void
dl_main (const Elf32_Phdr *phdr,
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"
);
rtld_command = 1;
interpreter_name = _dl_argv[0];
--_dl_argc;
++_dl_argv;
@ -164,7 +167,7 @@ of this helper program; chances are you did not intend to run this program.\n"
case PT_DYNAMIC:
/* This tells us where to find the dynamic section,
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;
case PT_INTERP:
/* 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
against the dynamic linker as a shared library, will know that
the shared object is already loaded. */
interpreter_name = (void *) ph->p_vaddr;
interpreter_name = (void *) l->l_addr + ph->p_vaddr;
break;
}
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;
}
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.
We do this in reverse order so that copy relocs of earlier

View File

@ -75,7 +75,7 @@ elf_machine_rel (struct link_map *map,
const Elf32_Rel *reloc,
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;
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. */
#define ELF_MACHINE_NO_RELA 1
@ -113,12 +127,14 @@ elf_machine_rel (struct link_map *map,
static inline void
elf_machine_runtime_setup (struct link_map *l)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
/* The GOT entries for functions in the PLT have not yet been filled
in. Their initial contents will arrange when called to push an
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
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. */
/* 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. */
@ -140,9 +156,20 @@ _dl_start_user:\n\
# Save the user entry point address in %edi.\n\
movl %eax, %edi\n\
# Point %ebx at the GOT.
1: call 2f\n\
2: popl %ebx\n\
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx\n\
call 0f\n\
0: popl %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\
# function to run.\n\
0: call _dl_init_next@PLT\n\
@ -150,7 +177,7 @@ _dl_start_user:\n\
testl %eax,%eax\n\
jz 1f\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\
# the initializer is called with the stack just\n\
# as it appears on entry, and it is free to move\n\
@ -159,8 +186,8 @@ _dl_start_user:\n\
call *%eax\n\
# Loop to call _dl_init_next for the next initializer.\n\
jmp 0b\n\
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
leal _dl_fini@GOT(%ebx), %edx\n\
1: # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
movl _dl_fini@GOT(%ebx), %edx\n\
# Jump to the user's entry point.\n\
jmp *%edi\n\
");

View File

@ -34,15 +34,16 @@ void
_dl_runtime_resolve (Elf32_Word reloc_offset)
{
__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 *) l->l_info[DT_SYMTAB]->d_un.d_ptr;
const char *strtab
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
const char *strtab =
(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
+ reloc_offset);
const Elf32_Rel *const reloc
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
const Elf32_Sym *definer;
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
function in the shared object will run with the stack arranged just as
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;

View File

@ -36,6 +36,8 @@ Cambridge, MA 02139, USA. */
#include "dl-machine.h"
extern void __mach_init (void);
extern int _dl_argc;
extern char **_dl_argv;
extern char **_environ;
@ -52,8 +54,8 @@ _dl_sysdep_start (void **start_argptr,
char **p;
/* Cache the information in various global variables. */
_dl_argc = *argdata++;
_dl_argv = (void *) argdata;
_dl_argc = *argdata;
_dl_argv = (void *) &argdata[1];
_environ = &_dl_argv[_dl_argc + 1];
for (p = _environ; *p; ++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->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);
/* 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
from the exec server and slicing up the arguments.
Then it will call `go', above. */

View File

@ -95,8 +95,8 @@ init1 (int argc, char *arg0, ...)
__libc_init (argc, argv, __environ);
}
static void
init (int *data, int retaddr)
static void
init (int *data, void *usercode, void **retaddrloc)
{
int argc = *data;
char **argv = (void *) (data + 1);
@ -115,6 +115,11 @@ init (int *data, int retaddr)
if (__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)
{
/* 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. */
*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,
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
soinit (int argc, ...)
void
_init (int argc, ...)
{
/* Initialize data structures so we can do RPCs. */
__mach_init ();
RUN_HOOK (_hurd_preinit_hook, ());
init (&argc, (&argc)[-1]);
(void) &soinit; /* Avoid gcc optimizing this fn out. */
init (&argc, ((void **) &argc)[-1], &((void **) &argc)[-1]);
}
#endif
void
__libc_init_first (int argc, ...)
__libc_init_first (int argc __attribute__ ((unused)), ...)
{
#ifndef PIC
void doinit (int *data)
{
init (data, (&argc)[-1]);
init (data, ((void **) &argc)[-1], &((void **) &data)[-1]);
}
/* Initialize data structures so we can do RPCs. */