Sat May 6 11:06:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* Makeconfig (+gccwarn): Add -Winline. * hurd/hurdsig.c (_hurd_internal_post_signal): If SS->context is set, avoid abort_rpcs, and use reply and intr ports saved in SS->context. * sysdeps/mach/hurd/i386/trampoline.c: Don't set SS->intr_port from SS->context. Don't clear SS->context. * sysdeps/mach/hurd/i386/sigreturn.c: Don't set SS->intr_port when setting SS->context. If msg_sig_post returns, re-lock and clear SS->context. Fri May 5 10:37:09 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * mach/Makefile (errsystems.c): Comment out generation rule. * sysdeps/mach/_strerror.c: Consider a system unknown if its bad_sub member is null. * mach/mig-alloc.c: Add weak alias to non-__ name.
This commit is contained in:
parent
0fb807c1db
commit
421f82e5cc
22
ChangeLog
22
ChangeLog
@ -1,3 +1,25 @@
|
||||
Sat May 6 11:06:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* Makeconfig (+gccwarn): Add -Winline.
|
||||
|
||||
* hurd/hurdsig.c (_hurd_internal_post_signal): If SS->context is
|
||||
set, avoid abort_rpcs, and use reply and intr ports saved in
|
||||
SS->context.
|
||||
* sysdeps/mach/hurd/i386/trampoline.c: Don't set SS->intr_port
|
||||
from SS->context. Don't clear SS->context.
|
||||
* sysdeps/mach/hurd/i386/sigreturn.c: Don't set SS->intr_port when
|
||||
setting SS->context. If msg_sig_post returns, re-lock and clear
|
||||
SS->context.
|
||||
|
||||
Fri May 5 10:37:09 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* mach/Makefile (errsystems.c): Comment out generation rule.
|
||||
|
||||
* sysdeps/mach/_strerror.c: Consider a system unknown if its
|
||||
bad_sub member is null.
|
||||
|
||||
* mach/mig-alloc.c: Add weak alias to non-__ name.
|
||||
|
||||
Wed May 3 11:56:35 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* sysdeps/mach/hurd/dup2.c: Fixed broken test in last change.
|
||||
|
@ -272,7 +272,7 @@ RANLIB = ranlib
|
||||
endif
|
||||
|
||||
# Extra flags to pass to GCC.
|
||||
+gccwarn := -Wall -Wwrite-strings -Wno-parentheses
|
||||
+gccwarn := -Wall -Wwrite-strings -Wno-parentheses -Winline
|
||||
|
||||
# This is the program that generates makefile
|
||||
# dependencies from C source files.
|
||||
|
@ -22,23 +22,28 @@ Cambridge, MA 02139, USA. */
|
||||
#include <setjmp.h>
|
||||
|
||||
static jmp_buf catch_env;
|
||||
static const char *signalled_errstring;
|
||||
static const char *signalled_errstring, *signalled_objname;
|
||||
|
||||
void
|
||||
_dl_signal_error (int errcode, const char *errstring)
|
||||
_dl_signal_error (int errcode,
|
||||
const char *objname,
|
||||
const char *errstring)
|
||||
{
|
||||
signalled_errstring = errstring ?: "DYNAMIC LINKER BUG!!!";
|
||||
longjmp (catch_env, errcode ?: -1);
|
||||
}
|
||||
|
||||
int
|
||||
_dl_catch_error (const char **errstring, void (*operate) (void))
|
||||
_dl_catch_error (const char **errstring,
|
||||
const char **objname,
|
||||
void (*operate) (void))
|
||||
{
|
||||
int errcode;
|
||||
|
||||
signalled_errstring = NULL;
|
||||
signalled_errstring = signalled_objname = NULL;
|
||||
errcode = setjmp (catch_env);
|
||||
(*operate) ();
|
||||
*errstring = signalled_errstring;
|
||||
*objname = signalled_objname;
|
||||
return *errstring ? errcode : 0;
|
||||
}
|
||||
|
@ -107,10 +107,20 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
Elf32_Addr *entry_point)
|
||||
{
|
||||
int fd;
|
||||
struct link_map *l = NULL;
|
||||
char *realname;
|
||||
const size_t pagesize = getpagesize ();
|
||||
void *file_mapping = NULL;
|
||||
size_t mapping_size = 0;
|
||||
|
||||
void lose (int code, const char *msg)
|
||||
{
|
||||
(void) close (fd);
|
||||
if (file_mapping)
|
||||
munmap (file_mapping, mapping_size);
|
||||
_dl_signal_error (code, l ? l->l_name : name, msg);
|
||||
}
|
||||
|
||||
/* Make sure LOCATION is mapped in. */
|
||||
void *map (off_t location, size_t size)
|
||||
{
|
||||
@ -124,14 +134,13 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
result = mmap (file_mapping, mapping_size, PROT_READ,
|
||||
MAP_COPY|MAP_FILE, fd, 0);
|
||||
if (result == (void *) -1)
|
||||
return NULL;
|
||||
lose (errno, "cannot map file data");
|
||||
file_mapping = result;
|
||||
}
|
||||
return file_mapping + location;
|
||||
}
|
||||
|
||||
const Elf32_Ehdr *header;
|
||||
struct link_map *l;
|
||||
|
||||
/* Look for this name among those already loaded. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
@ -170,7 +179,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
}
|
||||
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
lose (errno, "cannot open shared object file");
|
||||
|
||||
/* Look again to see if the real name matched another already loaded. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
@ -186,17 +195,9 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
|
||||
/* Map in the first page to read the header. */
|
||||
header = map (0, sizeof *header);
|
||||
if (! header)
|
||||
{
|
||||
lose:
|
||||
(void) close (fd);
|
||||
if (file_mapping)
|
||||
munmap (file_mapping, mapping_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef LOSE
|
||||
#define LOSE(s) _dl_signal_error (0, s)
|
||||
#define LOSE(s) lose (0, (s))
|
||||
/* Check the header for basic validity. */
|
||||
if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
|
||||
(ELFMAG1 << (EI_MAG1 * 8)) |
|
||||
@ -224,7 +225,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
{
|
||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||
if (_dl_zerofd == -1)
|
||||
_dl_signal_error (errno, "cannot open zero fill device");
|
||||
_dl_signal_error (errno, NULL, "cannot open zero fill device");
|
||||
}
|
||||
|
||||
{
|
||||
@ -235,8 +236,6 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
int anywhere;
|
||||
|
||||
ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
|
||||
if (! ph)
|
||||
goto lose;
|
||||
memcpy (phdr, ph, sizeof phdr);
|
||||
l->l_phnum = header->e_phnum;
|
||||
|
||||
@ -288,7 +287,8 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
{
|
||||
/* XXX this loses if the first segment mmap call puts
|
||||
it someplace where the later segments cannot fit. */
|
||||
mapat = mmap ((caddr_t) l->l_addr + mapstart, mapend - mapstart,
|
||||
mapat = mmap ((caddr_t) (l->l_addr + mapstart),
|
||||
mapend - mapstart,
|
||||
prot, MAP_COPY|MAP_FILE|MAP_INHERIT |
|
||||
/* Let the system choose any convenient
|
||||
location if this is the first segment.
|
||||
@ -312,8 +312,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
l->l_addr = 0;
|
||||
}
|
||||
if (mapat == (caddr_t) -1)
|
||||
_dl_signal_error (errno,
|
||||
"failed to map region from shared object");
|
||||
lose (errno, "failed to map segment from shared object");
|
||||
|
||||
if (ph->p_memsz > ph->p_filesz)
|
||||
{
|
||||
@ -341,8 +340,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
& ~(pagesize - 1)),
|
||||
pagesize,
|
||||
prot|PROT_WRITE) < 0)
|
||||
_dl_signal_error (errno,
|
||||
"cannot change protections");
|
||||
lose (errno, "cannot change memory protections");
|
||||
}
|
||||
memset (zero, 0, zeroend - zero);
|
||||
if ((prot & PROT_WRITE) == 0)
|
||||
|
@ -27,7 +27,8 @@ Cambridge, MA 02139, USA. */
|
||||
|
||||
Elf32_Addr
|
||||
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
||||
struct link_map *symbol_scope)
|
||||
struct link_map *symbol_scope,
|
||||
const char *reference_name)
|
||||
{
|
||||
unsigned long int hash = elf_hash (undef_name);
|
||||
struct link_map *map;
|
||||
@ -106,7 +107,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
||||
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, msg);
|
||||
_dl_signal_error (0, reference_name, msg);
|
||||
}
|
||||
|
||||
*ref = weak_value.s;
|
||||
|
@ -37,7 +37,8 @@ _dl_new_object (char *realname, const char *libname, int type)
|
||||
{
|
||||
struct link_map *new = malloc (sizeof *new);
|
||||
if (! new)
|
||||
_dl_signal_error (ENOMEM, "can't open new object");
|
||||
_dl_signal_error (ENOMEM, libname,
|
||||
"cannot allocate shared object descriptor");
|
||||
|
||||
memset (new, 0, sizeof *new);
|
||||
new->l_name = realname;
|
||||
|
@ -48,7 +48,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
& ~(pagesize - 1)));
|
||||
if (mprotect (mapstart, mapend - mapstart,
|
||||
PROT_READ|PROT_WRITE) < 0)
|
||||
_dl_signal_error (errno,
|
||||
_dl_signal_error (errno, l->l_name,
|
||||
"cannot make segment writable for relocation");
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,8 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
|
||||
Elf32_Addr resolve (const Elf32_Sym **ref)
|
||||
{
|
||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope);
|
||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
||||
l->l_name);
|
||||
}
|
||||
|
||||
real_next = l->l_next;
|
||||
@ -75,7 +76,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
else
|
||||
scope = _dl_loaded;
|
||||
|
||||
elf_dynamic_relocate (l->l_info, l->l_addr, lazy, resolve);
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, resolve);
|
||||
|
||||
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||
l->l_next = real_next;
|
||||
@ -107,7 +108,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
||||
if (ph->p_flags & PF_X)
|
||||
prot |= PROT_EXEC;
|
||||
if (mprotect (mapstart, mapend - mapstart, prot) < 0)
|
||||
_dl_signal_error (errno,
|
||||
_dl_signal_error (errno, l->l_name,
|
||||
"can't restore segment prot after reloc");
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
#define LOSE(s) _dl_signal_error (0, s)
|
||||
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
||||
|
||||
int
|
||||
dlclose (void *handle)
|
||||
|
@ -23,42 +23,49 @@ Cambridge, MA 02139, USA. */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int _dl_last_errcode;
|
||||
static const char *_dl_last_errstring;
|
||||
static int last_errcode;
|
||||
static const char *last_errstring;
|
||||
static const char *last_object_name;
|
||||
|
||||
char *
|
||||
dlerror (void)
|
||||
{
|
||||
char *ret;
|
||||
static char *buf;
|
||||
char *ret;
|
||||
|
||||
if (! _dl_last_errstring)
|
||||
if (buf)
|
||||
{
|
||||
free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (! last_errstring)
|
||||
return NULL;
|
||||
|
||||
if (_dl_last_errcode)
|
||||
{
|
||||
static char *buf;
|
||||
if (buf)
|
||||
{
|
||||
free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
if (asprintf (&buf, "%s: %s",
|
||||
_dl_last_errstring, strerror (_dl_last_errcode)) == -1)
|
||||
return NULL;
|
||||
else
|
||||
ret = buf;
|
||||
}
|
||||
else
|
||||
ret = (char *) _dl_last_errstring;
|
||||
if (last_errcode == 0 && ! last_object_name)
|
||||
ret = (char *) last_errstring;
|
||||
else if (last_errcode == 0)
|
||||
ret = (asprintf (&buf, "%s: %s", last_object_name, last_errstring) == -1
|
||||
? NULL : buf);
|
||||
else if (! last_object_name)
|
||||
ret = (asprintf (&buf, "%s: %s",
|
||||
last_errstring, strerror (last_errcode)) == -1
|
||||
? NULL : buf);
|
||||
else
|
||||
ret = (asprintf (&buf, "%s: %s: %s",
|
||||
last_object_name, last_errstring,
|
||||
strerror (last_errcode)) == -1
|
||||
? NULL : buf);
|
||||
|
||||
/* Reset the error indicator. */
|
||||
_dl_last_errstring = NULL;
|
||||
return ret;
|
||||
/* Reset the error indicator. */
|
||||
last_errstring = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
_dlerror_run (void (*operate) (void))
|
||||
{
|
||||
_dl_last_errcode = _dl_catch_error (&_dl_last_errstring, operate);
|
||||
return _dl_last_errstring != NULL;
|
||||
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
|
||||
operate);
|
||||
return last_errstring != NULL;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ dlsym (void *handle, const char *name)
|
||||
void doit (void)
|
||||
{
|
||||
const Elf32_Sym *ref = NULL;
|
||||
value = _dl_lookup_symbol (name, &ref, map);
|
||||
value = _dl_lookup_symbol (name, map->l_name, &ref, map);
|
||||
}
|
||||
|
||||
/* Confine the symbol scope to just this map. */
|
||||
|
68
elf/do-rel.h
Normal file
68
elf/do-rel.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* Do relocations for ELF dynamic linking.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
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. */
|
||||
|
||||
/* This file may be included twice, to define both
|
||||
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
|
||||
|
||||
#ifdef DO_RELA
|
||||
#define elf_dynamic_do_rel elf_dynamic_do_rela
|
||||
#define Elf32_Rel Elf32_Rela
|
||||
#define elf_machine_rel elf_machine_rela
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
static inline void
|
||||
elf_dynamic_do_rel (struct link_map *map,
|
||||
int reltag, int sztag,
|
||||
Elf32_Addr (*resolve) (const Elf32_Sym **))
|
||||
{
|
||||
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_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 (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
|
||||
#undef Elf32_Rel
|
||||
#undef elf_machine_rel
|
@ -18,23 +18,10 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
/* This machine-dependent file defines these inline functions. */
|
||||
|
||||
static void elf_machine_rel (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
const Elf32_Rel *reloc,
|
||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym);
|
||||
static void elf_machine_rela (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
const Elf32_Rela *reloc,
|
||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym);
|
||||
static Elf32_Addr *elf_machine_got (void);
|
||||
static Elf32_Addr elf_machine_load_address (void);
|
||||
|
||||
#include <dl-machine.h>
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
||||
|
||||
static inline void
|
||||
@ -60,60 +47,36 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM])
|
||||
info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||
}
|
||||
|
||||
/* Perform the relocations specified by DYNAMIC on the running program
|
||||
image. If LAZY is nonzero, don't relocate PLT entries. *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. */
|
||||
/* 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
|
||||
because we must be able to completely inline. */
|
||||
|
||||
static inline void
|
||||
elf_dynamic_relocate (Elf32_Dyn *dynamic[DT_NUM], Elf32_Addr loadaddr,
|
||||
int lazy, Elf32_Addr (*resolve) (const Elf32_Sym **))
|
||||
{
|
||||
const Elf32_Sym *const symtab
|
||||
= (const Elf32_Sym *) dynamic[DT_SYMTAB]->d_un.d_ptr;
|
||||
#if ! ELF_MACHINE_NO_REL
|
||||
#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));
|
||||
#else
|
||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||
#endif
|
||||
|
||||
inline Elf32_Addr symvalue (Elf32_Word info, const Elf32_Sym **definer)
|
||||
{
|
||||
if (ELF32_R_SYM (info) == STN_UNDEF)
|
||||
return 0; /* This value will not be consulted. */
|
||||
*definer = &symtab[ELF32_R_SYM (info)];
|
||||
return (*resolve) (definer);
|
||||
}
|
||||
#if ! ELF_MACHINE_NO_RELA
|
||||
#define DO_RELA
|
||||
#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);
|
||||
#else
|
||||
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) /* Nothing to do. */
|
||||
#endif
|
||||
|
||||
/* Perform Elf32_Rel relocations in the section found by RELTAG, SZTAG. */
|
||||
inline void do_rel (Elf32_Word reltag, Elf32_Word sztag)
|
||||
{
|
||||
const Elf32_Rel *r = (const Elf32_Rel *) dynamic[reltag]->d_un.d_ptr;
|
||||
const Elf32_Rel *end = &r[dynamic[sztag]->d_un.d_val / sizeof *r];
|
||||
while (r < end)
|
||||
{
|
||||
const Elf32_Sym *definer;
|
||||
Elf32_Addr loadbase = symvalue (r->r_info, &definer);
|
||||
elf_machine_rel (loadaddr, dynamic, r, loadbase, definer);
|
||||
++r;
|
||||
}
|
||||
}
|
||||
/* Perform Elf32_Rela relocations in the section found by RELTAG, SZTAG. */
|
||||
inline void do_rela (Elf32_Word reltag, Elf32_Word sztag)
|
||||
{
|
||||
const Elf32_Rela *r = (const Elf32_Rela *) dynamic[reltag]->d_un.d_ptr;
|
||||
const Elf32_Rela *end = &r[dynamic[sztag]->d_un.d_val / sizeof *r];
|
||||
while (r < end)
|
||||
{
|
||||
const Elf32_Sym *definer;
|
||||
Elf32_Addr loadbase = symvalue (r->r_info, &definer);
|
||||
elf_machine_rela (loadaddr, dynamic, r, loadbase, definer);
|
||||
++r;
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic[DT_RELA])
|
||||
do_rela (DT_RELA, DT_RELASZ);
|
||||
if (dynamic[DT_REL])
|
||||
do_rel (DT_REL, DT_RELSZ);
|
||||
if (dynamic[DT_JMPREL] && ! lazy)
|
||||
/* Relocate the PLT right now. */
|
||||
(dynamic[DT_PLTREL]->d_un.d_val == DT_REL ? do_rel : do_rela)
|
||||
(DT_JMPREL, DT_PLTRELSZ);
|
||||
}
|
||||
/* 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)
|
||||
|
26
elf/link.h
26
elf/link.h
@ -131,17 +131,23 @@ extern void _dl_sysdep_fatal (const char *string, ...)
|
||||
extern int _dl_secure;
|
||||
|
||||
/* This function is called by all the internal dynamic linker functions
|
||||
when they encounter an error. ERRCODE is either an `errno' code
|
||||
or zero; ERRSTRING is a string describing the specific problem. */
|
||||
when they encounter an error. ERRCODE is either an `errno' code or
|
||||
zero; OBJECT is the name of the problematical shared object, or null if
|
||||
it is a general problem; ERRSTRING is a string describing the specific
|
||||
problem. */
|
||||
|
||||
extern void _dl_signal_error (int errcode, const char *errstring)
|
||||
extern void _dl_signal_error (int errcode,
|
||||
const char *object,
|
||||
const char *errstring)
|
||||
__attribute__ ((__noreturn__));
|
||||
|
||||
/* Call OPERATE, catching errors from `dl_signal_error'. If there is no
|
||||
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING is
|
||||
set to the string passed to _dl_signal_error, and the error code passed
|
||||
is the return value. */
|
||||
extern int _dl_catch_error (const char **errstring, void (*operate) (void));
|
||||
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING and
|
||||
*OBJECT are set to the strings passed to _dl_signal_error, and the error
|
||||
code passed is the return value. */
|
||||
extern int _dl_catch_error (const char **errstring,
|
||||
const char **object,
|
||||
void (*operate) (void));
|
||||
|
||||
|
||||
/* Helper function for <dlfcn.h> functions. Runs the OPERATE function via
|
||||
@ -166,10 +172,12 @@ extern void _dl_setup_hash (struct link_map *map);
|
||||
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||
reference; it is replaced with the defining symbol, and the base load
|
||||
address of the defining object is returned. SYMBOL_SCOPE is the head of
|
||||
the chain used for searching. */
|
||||
the chain used for searching. REFERENCE_NAME should name the object
|
||||
containing the reference; it is used in error messages. */
|
||||
extern Elf32_Addr _dl_lookup_symbol (const char *undef,
|
||||
const Elf32_Sym **sym,
|
||||
struct link_map *symbol_scope);
|
||||
struct link_map *symbol_scope,
|
||||
const char *reference_name);
|
||||
|
||||
|
||||
/* List of objects currently loaded. */
|
||||
|
274
elf/rtld.c
274
elf/rtld.c
@ -52,40 +52,33 @@ static void dl_main (const Elf32_Phdr *phdr,
|
||||
Elf32_Addr
|
||||
_dl_start (void *arg)
|
||||
{
|
||||
Elf32_Addr rtld_loadaddr;
|
||||
Elf32_Dyn *dynamic_section;
|
||||
Elf32_Dyn *dynamic_info[DT_NUM];
|
||||
struct link_map rtld_map;
|
||||
|
||||
/* Figure out the run-time load address of the dynamic linker itself. */
|
||||
rtld_loadaddr = elf_machine_load_address ();
|
||||
rtld_map.l_addr = elf_machine_load_address ();
|
||||
|
||||
/* Read our own dynamic section and fill in the info array.
|
||||
Conveniently, the first element of the GOT contains the
|
||||
offset of _DYNAMIC relative to the run-time load address. */
|
||||
dynamic_section = (void *) rtld_loadaddr + *elf_machine_got ();
|
||||
elf_get_dynamic_info (dynamic_section, dynamic_info);
|
||||
rtld_map.l_ld = (void *) rtld_map.l_addr + *elf_machine_got ();
|
||||
elf_get_dynamic_info (rtld_map.l_ld, rtld_map.l_info);
|
||||
|
||||
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (dynamic_info);
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (rtld_map.l_info);
|
||||
#endif
|
||||
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
{
|
||||
Elf32_Addr resolve (const Elf32_Sym **ref)
|
||||
{
|
||||
assert ((*ref)->st_shndx != SHN_UNDEF);
|
||||
return rtld_loadaddr;
|
||||
}
|
||||
elf_dynamic_relocate (dynamic_info, rtld_loadaddr, 0, resolve);
|
||||
}
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (&rtld_map, 0, NULL);
|
||||
|
||||
|
||||
/* Now life is sane; we can call functions and access global data.
|
||||
Set up to use the operating system facilities, and find out from
|
||||
the operating system's program loader where to find the program
|
||||
header table in core. */
|
||||
|
||||
dl_r_debug.r_ldbase = rtld_loadaddr; /* Record our load address. */
|
||||
dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address. */
|
||||
|
||||
/* Call the OS-dependent function to set up life so we can do things like
|
||||
file access. It will call `dl_main' (below) to do all the real work
|
||||
@ -107,29 +100,30 @@ dl_main (const Elf32_Phdr *phdr,
|
||||
{
|
||||
void doit (void)
|
||||
{
|
||||
const Elf32_Phdr *ph;
|
||||
struct link_map *l;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
const Elf32_Phdr *ph;
|
||||
struct link_map *l;
|
||||
const char *interpreter_name;
|
||||
int lazy;
|
||||
|
||||
if (*user_entry == (Elf32_Addr) &_start)
|
||||
{
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments. To
|
||||
simplify life here, PROGRAM is searched for using the normal rules
|
||||
for shared objects, rather than $PATH or anything like that. We
|
||||
just load it and use its entry point; we don't pay attention to
|
||||
its PT_INTERP command (we are the interpreter ourselves). This is
|
||||
an easy way to test a new ld.so before installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
if (*user_entry == (Elf32_Addr) &_start)
|
||||
{
|
||||
/* Ho ho. We are not the program interpreter! We are the program
|
||||
itself! This means someone ran ld.so as a command. Well, that
|
||||
might be convenient to do sometimes. We support it by
|
||||
interpreting the args like this:
|
||||
|
||||
ld.so PROGRAM ARGS...
|
||||
|
||||
The first argument is the name of a file containing an ELF
|
||||
executable we will load and run with the following arguments.
|
||||
To simplify life here, PROGRAM is searched for using the
|
||||
normal rules for shared objects, rather than $PATH or anything
|
||||
like that. We just load it and use its entry point; we don't
|
||||
pay attention to its PT_INTERP command (we are the interpreter
|
||||
ourselves). This is an easy way to test a new ld.so before
|
||||
installing it. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
Usage: ld.so EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||
You have invoked `ld.so', the helper program for shared library executables.\n\
|
||||
This program usually lives in the file `/lib/ld.so', and special directives\n\
|
||||
@ -142,116 +136,118 @@ that file itself, but always uses this helper program from the file you\n\
|
||||
specified, instead of the helper program file specified in the executable\n\
|
||||
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"
|
||||
);
|
||||
);
|
||||
|
||||
interpreter_name = _dl_argv[0];
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
l = _dl_map_object (NULL, _dl_argv[0], user_entry);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_type = lt_executable;
|
||||
l->l_libname = (char *) "";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
}
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
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;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure, which we
|
||||
will set up later to communicate with the debugger. */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
||||
|
||||
l = _dl_new_object ((char *) interpreter_name, interpreter_name,
|
||||
lt_interpreter);
|
||||
|
||||
/* Now process all the DT_NEEDED entries and map in the objects.
|
||||
Each new link_map will go on the end of the chain, so we will
|
||||
come across it later in the loop to map in its dependencies. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
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)
|
||||
_dl_map_object (l, strtab + d->d_un.d_val, NULL);
|
||||
interpreter_name = _dl_argv[0];
|
||||
--_dl_argc;
|
||||
++_dl_argv;
|
||||
l = _dl_map_object (NULL, _dl_argv[0], user_entry);
|
||||
phdr = l->l_phdr;
|
||||
phent = l->l_phnum;
|
||||
l->l_type = lt_executable;
|
||||
l->l_libname = (char *) "";
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
else
|
||||
{
|
||||
/* Create a link_map for the executable itself.
|
||||
This will be what dlopen on "" returns. */
|
||||
l = _dl_new_object ((char *) "", "", lt_executable);
|
||||
l->l_phdr = phdr;
|
||||
l->l_phnum = phent;
|
||||
interpreter_name = 0;
|
||||
}
|
||||
|
||||
/* Scan the program header table for the dynamic section. */
|
||||
for (ph = phdr; ph < &phdr[phent]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
find the program interpreter, which is this program itself, the
|
||||
dynamic linker. We note what name finds us, so that a future
|
||||
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;
|
||||
break;
|
||||
}
|
||||
assert (interpreter_name); /* How else did we get here? */
|
||||
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
_dl_setup_hash (l);
|
||||
|
||||
if (l->l_info[DT_DEBUG])
|
||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||
with the run-time address of the r_debug structure, which we
|
||||
will set up later to communicate with the debugger. */
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
||||
|
||||
l = _dl_new_object ((char *) interpreter_name, interpreter_name,
|
||||
lt_interpreter);
|
||||
|
||||
/* Now process all the DT_NEEDED entries and map in the objects.
|
||||
Each new link_map will go on the end of the chain, so we will
|
||||
come across it later in the loop to map in its dependencies. */
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
{
|
||||
if (l->l_info[DT_NEEDED])
|
||||
{
|
||||
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)
|
||||
_dl_map_object (l, strtab + d->d_un.d_val, NULL);
|
||||
}
|
||||
l->l_deps_loaded = 1;
|
||||
}
|
||||
|
||||
l = _dl_loaded->l_next;
|
||||
assert (l->l_type == lt_interpreter);
|
||||
if (l->l_opencount == 0)
|
||||
{
|
||||
/* No DT_NEEDED entry referred to the interpreter object itself.
|
||||
Remove it from the maps we will use for symbol resolution. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
}
|
||||
|
||||
lazy = _dl_secure || *(getenv ("LD_BIND_NOW") ?: "");
|
||||
|
||||
/* Now we have all the objects loaded. Relocate them all.
|
||||
We do this in reverse order so that copy relocs of earlier
|
||||
objects overwrite the data written by later objects. */
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
_dl_relocate_object (l, lazy);
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
dl_r_debug.r_map = _dl_loaded;
|
||||
dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
|
||||
}
|
||||
|
||||
l = _dl_loaded->l_next;
|
||||
assert (l->l_type == lt_interpreter);
|
||||
if (l->l_opencount == 0)
|
||||
{
|
||||
/* No DT_NEEDED entry referred to the interpreter object itself.
|
||||
Remove it from the maps we will use for symbol resolution. */
|
||||
l->l_prev->l_next = l->l_next;
|
||||
if (l->l_next)
|
||||
l->l_next->l_prev = l->l_prev;
|
||||
}
|
||||
|
||||
lazy = _dl_secure || *(getenv ("LD_BIND_NOW") ?: "");
|
||||
|
||||
/* Now we have all the objects loaded. Relocate them all.
|
||||
We do this in reverse order so that copy relocs of earlier
|
||||
objects overwrite the data written by later objects. */
|
||||
l = _dl_loaded;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
do
|
||||
{
|
||||
_dl_relocate_object (l, lazy);
|
||||
l = l->l_prev;
|
||||
} while (l);
|
||||
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
dl_r_debug.r_map = _dl_loaded;
|
||||
dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
|
||||
}
|
||||
const char *errstring;
|
||||
const char *errobj;
|
||||
int err;
|
||||
|
||||
err = _dl_catch_error (&errstring, &doit);
|
||||
err = _dl_catch_error (&errstring, &errobj, &doit);
|
||||
if (errstring)
|
||||
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
||||
": error in loading shared libraries\n",
|
||||
errobj ?: "", errobj ? ": " : "",
|
||||
errstring, err ? ": " : NULL,
|
||||
err ? strerror (err) : NULL, NULL);
|
||||
|
||||
|
115
hurd/hurdsig.c
115
hurd/hurdsig.c
@ -667,9 +667,16 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
/* Nobody cares about this signal. */
|
||||
break;
|
||||
|
||||
sigbomb:
|
||||
/* We got a fault setting up the stack frame for the handler.
|
||||
Nothing to do but die; BSD gets SIGILL in this case. */
|
||||
sigcode = signo; /* XXX ? */
|
||||
signo = SIGILL;
|
||||
act = core;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case term: /* Time to die. */
|
||||
case core: /* And leave a rotting corpse. */
|
||||
nirvana:
|
||||
/* Have the proc server stop all other threads in our task. */
|
||||
err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
|
||||
assert_perror (err);
|
||||
@ -693,7 +700,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
case handle:
|
||||
/* Call a handler for this signal. */
|
||||
{
|
||||
struct sigcontext *scp;
|
||||
struct sigcontext *scp, ocontext;
|
||||
int wait_for_reply, state_changed;
|
||||
|
||||
/* Stop the thread and abort its pending RPC operations. */
|
||||
@ -710,19 +717,64 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
thread_get_state is never kosher before thread_abort. */
|
||||
abort_thread (ss, &thread_state, NULL, 0, 0);
|
||||
|
||||
wait_for_reply = (abort_rpcs (ss, signo, &thread_state, &state_changed,
|
||||
&reply_port, reply_port_type, untraced)
|
||||
!= MACH_PORT_NULL);
|
||||
|
||||
if (ss->critical_section)
|
||||
if (ss->context)
|
||||
{
|
||||
/* The thread is in a critical section. Mark the signal as
|
||||
pending. When it finishes the critical section, it will
|
||||
check for pending signals. */
|
||||
mark_pending ();
|
||||
assert (! state_changed);
|
||||
__thread_resume (ss->thread);
|
||||
break;
|
||||
/* We have a previous sigcontext that sigreturn was about
|
||||
to restore when another signal arrived. */
|
||||
|
||||
mach_port_t *loc;
|
||||
|
||||
if (_hurdsig_catch_fault (SIGSEGV))
|
||||
{
|
||||
assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
|
||||
_hurdsig_fault_sigcode < (long int) (ss->context + 1));
|
||||
/* We faulted reading the thread's stack. Forget that
|
||||
context and pretend it wasn't there. It almost
|
||||
certainly crash if this handler returns, but that's it's
|
||||
problem. */
|
||||
ss->context = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy the context from the thread's stack before
|
||||
we start diddling the stack to set up the handler. */
|
||||
ocontext = *ss->context;
|
||||
ss->context = &ocontext;
|
||||
}
|
||||
_hurdsig_end_catch_fault ();
|
||||
|
||||
if (! machine_get_basic_state (ss->thread, &thread_state))
|
||||
goto sigbomb;
|
||||
loc = interrupted_reply_port_location (&thread_state);
|
||||
if (loc && *loc != MACH_PORT_NULL)
|
||||
/* This is the reply port for the context which called
|
||||
sigreturn. Since we are abandoning that context entirely
|
||||
and restoring SS->context instead, destroy this port. */
|
||||
__mach_port_destroy (__mach_task_self (), *loc);
|
||||
|
||||
/* The thread was in sigreturn, not in any interruptible RPC. */
|
||||
wait_for_reply = 0;
|
||||
|
||||
assert (! ss->critical_section);
|
||||
}
|
||||
else
|
||||
{
|
||||
wait_for_reply = (abort_rpcs (ss, signo,
|
||||
&thread_state, &state_changed,
|
||||
&reply_port, reply_port_type,
|
||||
untraced)
|
||||
!= MACH_PORT_NULL);
|
||||
|
||||
if (ss->critical_section)
|
||||
{
|
||||
/* The thread is in a critical section. Mark the signal as
|
||||
pending. When it finishes the critical section, it will
|
||||
check for pending signals. */
|
||||
mark_pending ();
|
||||
assert (! state_changed);
|
||||
__thread_resume (ss->thread);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the machine-dependent function to set the thread up
|
||||
@ -731,18 +783,10 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
signo, sigcode,
|
||||
wait_for_reply, &thread_state);
|
||||
if (scp == NULL)
|
||||
{
|
||||
/* We got a fault setting up the stack frame for the handler.
|
||||
Nothing to do but die; BSD gets SIGILL in this case. */
|
||||
sigcode = signo; /* XXX ? */
|
||||
signo = SIGILL;
|
||||
act = core;
|
||||
goto nirvana;
|
||||
}
|
||||
goto sigbomb;
|
||||
|
||||
/* Set the machine-independent parts of the signal context. */
|
||||
|
||||
scp->sc_error = sigerror;
|
||||
{
|
||||
/* Fetch the thread variable for the MiG reply port,
|
||||
and set it to MACH_PORT_NULL. */
|
||||
@ -754,17 +798,32 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
||||
}
|
||||
else
|
||||
scp->sc_reply_port = MACH_PORT_NULL;
|
||||
|
||||
/* Save the intr_port in use by the interrupted code,
|
||||
and clear the cell before running the trampoline. */
|
||||
scp->sc_intr_port = ss->intr_port;
|
||||
ss->intr_port = MACH_PORT_NULL;
|
||||
|
||||
if (ss->context)
|
||||
{
|
||||
/* After the handler runs we will restore to the state in
|
||||
SS->context, not the state of the thread now. So restore
|
||||
that context's reply port and intr port. */
|
||||
|
||||
scp->sc_reply_port = ss->context->sc_reply_port;
|
||||
scp->sc_intr_port = ss->context->sc_intr_port;
|
||||
|
||||
ss->context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Backdoor extra argument to signal handler. */
|
||||
scp->sc_error = sigerror;
|
||||
|
||||
/* Block SIGNO and requested signals while running the handler. */
|
||||
scp->sc_mask = ss->blocked;
|
||||
ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
|
||||
|
||||
/* Save the intr_port in use by the interrupted code,
|
||||
and clear the cell before running the trampoline. */
|
||||
scp->sc_intr_port = ss->intr_port;
|
||||
ss->intr_port = MACH_PORT_NULL;
|
||||
|
||||
/* Start the thread running the handler (or possibly waiting for an
|
||||
RPC reply before running the handler). */
|
||||
err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
|
||||
|
@ -183,8 +183,12 @@ endif
|
||||
# Be sure not to make these with implicit rules from foo.defs.
|
||||
mach.h mach/memory_object.h: ;
|
||||
|
||||
ifneq (,)
|
||||
# A gcc bug prevents the generated file from working properly,
|
||||
# so we have one in the distribution for the time being.
|
||||
generated += errsystems.c
|
||||
$(objpfx)errsystems.c: errsystems.awk err_*.sub \
|
||||
$(wildcard $(addsuffix /err_*.sub,$(+sysdep_dirs)))
|
||||
gawk -v subsys='$(filter-out $<,$^)' -f $^ > $@.n
|
||||
mv $@.n $@
|
||||
endif
|
||||
|
@ -68,11 +68,10 @@ elf_machine_load_address (void)
|
||||
++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr;
|
||||
|
||||
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
||||
LOADADDR is the load address of the object; INFO is an array indexed
|
||||
by DT_* of the .dynamic section info. */
|
||||
MAP is the object containing the reloc. */
|
||||
|
||||
static inline void
|
||||
elf_machine_rel (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
elf_machine_rel (struct link_map *map,
|
||||
const Elf32_Rel *reloc,
|
||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
|
||||
{
|
||||
@ -92,7 +91,7 @@ elf_machine_rel (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
*reloc_addr += sym_value;
|
||||
break;
|
||||
case R_386_RELATIVE:
|
||||
*reloc_addr += loadaddr;
|
||||
*reloc_addr += map->l_addr;
|
||||
break;
|
||||
case R_386_PC32:
|
||||
*reloc_addr = sym_value - (Elf32_Addr) reloc_addr;
|
||||
@ -105,13 +104,7 @@ elf_machine_rel (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
|
||||
|
||||
/* The i386 never uses Elf32_Rela relocations. */
|
||||
static inline void
|
||||
elf_machine_rela (Elf32_Addr loadaddr, Elf32_Dyn *info[DT_NUM],
|
||||
const Elf32_Rela *reloc,
|
||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
|
||||
{
|
||||
_dl_signal_error (0, "Elf32_Rela relocation requested -- unused on i386");
|
||||
}
|
||||
#define ELF_MACHINE_NO_RELA 1
|
||||
|
||||
|
||||
/* Set up the loaded object described by L so its unrelocated PLT
|
||||
@ -140,9 +133,16 @@ elf_machine_runtime_setup (struct link_map *l)
|
||||
#define RTLD_START asm ("\
|
||||
.text\n\
|
||||
.globl _start\n\
|
||||
_start: call _dl_start\n\
|
||||
# Save the user entry point address in %ebx.\n\
|
||||
movl %eax, %ebx\n\
|
||||
.globl _dl_start_user\n\
|
||||
_start:\n\
|
||||
call _dl_start\n\
|
||||
_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 _dl_init_next to return the address of an initializer\n\
|
||||
# function to run.\n\
|
||||
0: call _dl_init_next@PLT\n\
|
||||
@ -160,10 +160,7 @@ _start: call _dl_start\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\
|
||||
1: call 2f\n\
|
||||
2: popl %eax\n\
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %eax\n\
|
||||
leal _dl_fini@GOT(%eax), %edx\n\
|
||||
# Jump to the user entry point.\n\
|
||||
jmp *%ebx\n\
|
||||
leal _dl_fini@GOT(%ebx), %edx\n\
|
||||
# Jump to the user's entry point.\n\
|
||||
jmp *%edi\n\
|
||||
");
|
||||
|
@ -17,8 +17,6 @@ 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. */
|
||||
|
||||
register void *sp asm ("%esp");
|
||||
|
||||
#include <link.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
@ -30,7 +28,7 @@ register void *sp asm ("%esp");
|
||||
0(%esp) identifier for this shared object (struct link_map *)
|
||||
|
||||
The user expects the real function the PLT refers to to be entered
|
||||
8(%esp) as the top of stack. */
|
||||
with 8(%esp) as the top of stack. */
|
||||
|
||||
void
|
||||
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
||||
@ -63,14 +61,15 @@ _dl_runtime_resolve (Elf32_Word reloc_offset)
|
||||
scope = _dl_loaded;
|
||||
|
||||
definer = &symtab[ELF32_R_SYM (reloc->r_info)];
|
||||
loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer, scope);
|
||||
loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
|
||||
scope, l->l_name);
|
||||
|
||||
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||
l->l_next = real_next;
|
||||
l->l_prev->l_next = l;
|
||||
|
||||
/* Apply the relocation with that value. */
|
||||
elf_machine_rel (l->l_addr, l->l_info, reloc, loadbase, definer);
|
||||
elf_machine_rel (l, reloc, loadbase, definer);
|
||||
|
||||
/* The top of the stack is the word we set L from; but this location
|
||||
holds the address we will return to. Store there the address of a
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993, 1995 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -20,7 +20,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mach/error.h>
|
||||
#include <mach/errorlib.h>
|
||||
#include <errorlib.h>
|
||||
|
||||
/* Return a string describing the errno code in ERRNUM. */
|
||||
char *
|
||||
@ -38,7 +38,7 @@ DEFUN(_strerror_internal, (errnum, buf), int errnum AND char buf[1024])
|
||||
sub = err_get_sub (errnum);
|
||||
code = err_get_code (errnum);
|
||||
|
||||
if (system > err_max_system)
|
||||
if (system > err_max_system || ! __mach_error_systems[system].bad_sub)
|
||||
{
|
||||
sprintf (buf, "Unknown error system %d", system);
|
||||
return buf;
|
||||
|
@ -21,6 +21,7 @@ Cambridge, MA 02139, USA. */
|
||||
#include <unistd.h>
|
||||
#include <hurd.h>
|
||||
#include <hurd/fd.h>
|
||||
#include <hurd/resource.h>
|
||||
|
||||
/* Return the maximum number of file descriptors the current process
|
||||
could possibly have (until it raises the resource limit). */
|
||||
@ -29,9 +30,9 @@ DEFUN_VOID(__getdtablesize)
|
||||
{
|
||||
int size;
|
||||
HURD_CRITICAL_BEGIN;
|
||||
__mutex_lock (&_hurd_rlimits_lock);
|
||||
size = _hurd_rlimits[RLIM_NOFILE].rlim_cur; /* XXX RLIM_INFINITY?? */
|
||||
__mutex_unlock (&_hurd_rlimits_lock);
|
||||
__mutex_lock (&_hurd_rlimit_lock);
|
||||
size = _hurd_rlimits[RLIMIT_NOFILE].rlim_cur;
|
||||
__mutex_unlock (&_hurd_rlimit_lock);
|
||||
HURD_CRITICAL_END;
|
||||
return size;
|
||||
}
|
||||
|
@ -57,15 +57,13 @@ __sigreturn (struct sigcontext *scp)
|
||||
the signal thread will notice it if it runs another handler, and
|
||||
arrange to have us called over again in the new reality. */
|
||||
ss->context = scp;
|
||||
/* Clear the intr_port slot, since we are not in fact doing
|
||||
an interruptible RPC right now. If SS->intr_port is not null,
|
||||
the SCP context is doing an interruptible RPC, but the signal
|
||||
thread will examine us while we are blocked in the sig_post RPC. */
|
||||
ss->intr_port = MACH_PORT_NULL;
|
||||
__spin_unlock (&ss->lock);
|
||||
__msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
|
||||
/* If a pending signal was handled, sig_post never returned. */
|
||||
/* If a pending signal was handled, sig_post never returned.
|
||||
If it did return, the pending signal didn't run a handler;
|
||||
proceed as usual. */
|
||||
__spin_lock (&ss->lock);
|
||||
ss->context = NULL;
|
||||
}
|
||||
|
||||
if (scp->sc_onstack)
|
||||
|
@ -73,23 +73,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
||||
sizeof (state->basic));
|
||||
memcpy (&state->fpu, &ss->context->sc_i386_float_state,
|
||||
sizeof (state->fpu));
|
||||
state->set = (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
|
||||
assert (! rpc_wait);
|
||||
/* The intr_port slot was cleared before sigreturn sent us the
|
||||
sig_post that made us notice this pending signal, so
|
||||
_hurd_internal_post_signal wouldn't do interrupt_operation.
|
||||
After we return, our caller will set SCP->sc_intr_port (in the
|
||||
new context) from SS->intr_port and clear SS->intr_port. Now
|
||||
that we are restoring this old context recorded by sigreturn,
|
||||
we want to restore its intr_port too; so store it in
|
||||
SS->intr_port now, so it will end up in SCP->sc_intr_port
|
||||
later. */
|
||||
ss->intr_port = ss->context->sc_intr_port;
|
||||
state->set |= (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
|
||||
}
|
||||
/* If the sigreturn context was bogus, just ignore it. */
|
||||
ss->context = NULL;
|
||||
}
|
||||
else if (! machine_get_basic_state (ss->thread, state))
|
||||
|
||||
if (! machine_get_basic_state (ss->thread, state))
|
||||
return NULL;
|
||||
|
||||
if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
|
||||
|
Loading…
Reference in New Issue
Block a user