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>
|
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.
|
* sysdeps/mach/hurd/dup2.c: Fixed broken test in last change.
|
||||||
|
@ -272,7 +272,7 @@ RANLIB = ranlib
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Extra flags to pass to GCC.
|
# 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
|
# This is the program that generates makefile
|
||||||
# dependencies from C source files.
|
# dependencies from C source files.
|
||||||
|
@ -22,23 +22,28 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
static jmp_buf catch_env;
|
static jmp_buf catch_env;
|
||||||
static const char *signalled_errstring;
|
static const char *signalled_errstring, *signalled_objname;
|
||||||
|
|
||||||
void
|
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!!!";
|
signalled_errstring = errstring ?: "DYNAMIC LINKER BUG!!!";
|
||||||
longjmp (catch_env, errcode ?: -1);
|
longjmp (catch_env, errcode ?: -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_dl_catch_error (const char **errstring, void (*operate) (void))
|
_dl_catch_error (const char **errstring,
|
||||||
|
const char **objname,
|
||||||
|
void (*operate) (void))
|
||||||
{
|
{
|
||||||
int errcode;
|
int errcode;
|
||||||
|
|
||||||
signalled_errstring = NULL;
|
signalled_errstring = signalled_objname = NULL;
|
||||||
errcode = setjmp (catch_env);
|
errcode = setjmp (catch_env);
|
||||||
(*operate) ();
|
(*operate) ();
|
||||||
*errstring = signalled_errstring;
|
*errstring = signalled_errstring;
|
||||||
|
*objname = signalled_objname;
|
||||||
return *errstring ? errcode : 0;
|
return *errstring ? errcode : 0;
|
||||||
}
|
}
|
||||||
|
@ -107,10 +107,20 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||||||
Elf32_Addr *entry_point)
|
Elf32_Addr *entry_point)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
struct link_map *l = NULL;
|
||||||
char *realname;
|
char *realname;
|
||||||
const size_t pagesize = getpagesize ();
|
const size_t pagesize = getpagesize ();
|
||||||
void *file_mapping = NULL;
|
void *file_mapping = NULL;
|
||||||
size_t mapping_size = 0;
|
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. */
|
/* Make sure LOCATION is mapped in. */
|
||||||
void *map (off_t location, size_t size)
|
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,
|
result = mmap (file_mapping, mapping_size, PROT_READ,
|
||||||
MAP_COPY|MAP_FILE, fd, 0);
|
MAP_COPY|MAP_FILE, fd, 0);
|
||||||
if (result == (void *) -1)
|
if (result == (void *) -1)
|
||||||
return NULL;
|
lose (errno, "cannot map file data");
|
||||||
file_mapping = result;
|
file_mapping = result;
|
||||||
}
|
}
|
||||||
return file_mapping + location;
|
return file_mapping + location;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Elf32_Ehdr *header;
|
const Elf32_Ehdr *header;
|
||||||
struct link_map *l;
|
|
||||||
|
|
||||||
/* Look for this name among those already loaded. */
|
/* Look for this name among those already loaded. */
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
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)
|
if (fd == -1)
|
||||||
return NULL;
|
lose (errno, "cannot open shared object file");
|
||||||
|
|
||||||
/* Look again to see if the real name matched another already loaded. */
|
/* Look again to see if the real name matched another already loaded. */
|
||||||
for (l = _dl_loaded; l; l = l->l_next)
|
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. */
|
/* Map in the first page to read the header. */
|
||||||
header = map (0, sizeof *header);
|
header = map (0, sizeof *header);
|
||||||
if (! header)
|
|
||||||
{
|
|
||||||
lose:
|
|
||||||
(void) close (fd);
|
|
||||||
if (file_mapping)
|
|
||||||
munmap (file_mapping, mapping_size);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef LOSE
|
#undef LOSE
|
||||||
#define LOSE(s) _dl_signal_error (0, s)
|
#define LOSE(s) lose (0, (s))
|
||||||
/* Check the header for basic validity. */
|
/* Check the header for basic validity. */
|
||||||
if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
|
if (*(Elf32_Word *) &header->e_ident != ((ELFMAG0 << (EI_MAG0 * 8)) |
|
||||||
(ELFMAG1 << (EI_MAG1 * 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 ();
|
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||||
if (_dl_zerofd == -1)
|
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;
|
int anywhere;
|
||||||
|
|
||||||
ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
|
ph = map (header->e_phoff, header->e_phnum * sizeof (Elf32_Phdr));
|
||||||
if (! ph)
|
|
||||||
goto lose;
|
|
||||||
memcpy (phdr, ph, sizeof phdr);
|
memcpy (phdr, ph, sizeof phdr);
|
||||||
l->l_phnum = header->e_phnum;
|
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
|
/* XXX this loses if the first segment mmap call puts
|
||||||
it someplace where the later segments cannot fit. */
|
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 |
|
prot, MAP_COPY|MAP_FILE|MAP_INHERIT |
|
||||||
/* Let the system choose any convenient
|
/* Let the system choose any convenient
|
||||||
location if this is the first segment.
|
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;
|
l->l_addr = 0;
|
||||||
}
|
}
|
||||||
if (mapat == (caddr_t) -1)
|
if (mapat == (caddr_t) -1)
|
||||||
_dl_signal_error (errno,
|
lose (errno, "failed to map segment from shared object");
|
||||||
"failed to map region from shared object");
|
|
||||||
|
|
||||||
if (ph->p_memsz > ph->p_filesz)
|
if (ph->p_memsz > ph->p_filesz)
|
||||||
{
|
{
|
||||||
@ -341,8 +340,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||||||
& ~(pagesize - 1)),
|
& ~(pagesize - 1)),
|
||||||
pagesize,
|
pagesize,
|
||||||
prot|PROT_WRITE) < 0)
|
prot|PROT_WRITE) < 0)
|
||||||
_dl_signal_error (errno,
|
lose (errno, "cannot change memory protections");
|
||||||
"cannot change protections");
|
|
||||||
}
|
}
|
||||||
memset (zero, 0, zeroend - zero);
|
memset (zero, 0, zeroend - zero);
|
||||||
if ((prot & PROT_WRITE) == 0)
|
if ((prot & PROT_WRITE) == 0)
|
||||||
|
@ -27,7 +27,8 @@ Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
Elf32_Addr
|
Elf32_Addr
|
||||||
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
_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);
|
unsigned long int hash = elf_hash (undef_name);
|
||||||
struct link_map *map;
|
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)];
|
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);
|
||||||
_dl_signal_error (0, msg);
|
_dl_signal_error (0, reference_name, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ref = weak_value.s;
|
*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);
|
struct link_map *new = malloc (sizeof *new);
|
||||||
if (! 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);
|
memset (new, 0, sizeof *new);
|
||||||
new->l_name = realname;
|
new->l_name = realname;
|
||||||
|
@ -48,7 +48,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
& ~(pagesize - 1)));
|
& ~(pagesize - 1)));
|
||||||
if (mprotect (mapstart, mapend - mapstart,
|
if (mprotect (mapstart, mapend - mapstart,
|
||||||
PROT_READ|PROT_WRITE) < 0)
|
PROT_READ|PROT_WRITE) < 0)
|
||||||
_dl_signal_error (errno,
|
_dl_signal_error (errno, l->l_name,
|
||||||
"cannot make segment writable for relocation");
|
"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)
|
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;
|
real_next = l->l_next;
|
||||||
@ -75,7 +76,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
else
|
else
|
||||||
scope = _dl_loaded;
|
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. */
|
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||||
l->l_next = real_next;
|
l->l_next = real_next;
|
||||||
@ -107,7 +108,7 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
if (ph->p_flags & PF_X)
|
if (ph->p_flags & PF_X)
|
||||||
prot |= PROT_EXEC;
|
prot |= PROT_EXEC;
|
||||||
if (mprotect (mapstart, mapend - mapstart, prot) < 0)
|
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");
|
"can't restore segment prot after reloc");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
#define LOSE(s) _dl_signal_error (0, s)
|
#define LOSE(s) _dl_signal_error (0, map->l_name, s)
|
||||||
|
|
||||||
int
|
int
|
||||||
dlclose (void *handle)
|
dlclose (void *handle)
|
||||||
|
@ -23,42 +23,49 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int _dl_last_errcode;
|
static int last_errcode;
|
||||||
static const char *_dl_last_errstring;
|
static const char *last_errstring;
|
||||||
|
static const char *last_object_name;
|
||||||
|
|
||||||
char *
|
char *
|
||||||
dlerror (void)
|
dlerror (void)
|
||||||
{
|
{
|
||||||
char *ret;
|
static char *buf;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
if (! _dl_last_errstring)
|
if (buf)
|
||||||
|
{
|
||||||
|
free (buf);
|
||||||
|
buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! last_errstring)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (_dl_last_errcode)
|
if (last_errcode == 0 && ! last_object_name)
|
||||||
{
|
ret = (char *) last_errstring;
|
||||||
static char *buf;
|
else if (last_errcode == 0)
|
||||||
if (buf)
|
ret = (asprintf (&buf, "%s: %s", last_object_name, last_errstring) == -1
|
||||||
{
|
? NULL : buf);
|
||||||
free (buf);
|
else if (! last_object_name)
|
||||||
buf = NULL;
|
ret = (asprintf (&buf, "%s: %s",
|
||||||
}
|
last_errstring, strerror (last_errcode)) == -1
|
||||||
if (asprintf (&buf, "%s: %s",
|
? NULL : buf);
|
||||||
_dl_last_errstring, strerror (_dl_last_errcode)) == -1)
|
else
|
||||||
return NULL;
|
ret = (asprintf (&buf, "%s: %s: %s",
|
||||||
else
|
last_object_name, last_errstring,
|
||||||
ret = buf;
|
strerror (last_errcode)) == -1
|
||||||
}
|
? NULL : buf);
|
||||||
else
|
|
||||||
ret = (char *) _dl_last_errstring;
|
|
||||||
|
|
||||||
/* Reset the error indicator. */
|
/* Reset the error indicator. */
|
||||||
_dl_last_errstring = NULL;
|
last_errstring = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_dlerror_run (void (*operate) (void))
|
_dlerror_run (void (*operate) (void))
|
||||||
{
|
{
|
||||||
_dl_last_errcode = _dl_catch_error (&_dl_last_errstring, operate);
|
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
|
||||||
return _dl_last_errstring != NULL;
|
operate);
|
||||||
|
return last_errstring != NULL;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ dlsym (void *handle, const char *name)
|
|||||||
void doit (void)
|
void doit (void)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *ref = NULL;
|
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. */
|
/* 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. */
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <elf.h>
|
#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 <dl-machine.h>
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
||||||
|
|
||||||
static inline void
|
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);
|
info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the relocations specified by DYNAMIC on the running program
|
/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
|
||||||
image. If LAZY is nonzero, don't relocate PLT entries. *RESOLVE is
|
These functions are almost identical, so we use cpp magic to avoid
|
||||||
called to resolve symbol values; it modifies its argument pointer to
|
duplicating their code. It cannot be done in a more general function
|
||||||
point to the defining symbol, and returns the base load address of the
|
because we must be able to completely inline. */
|
||||||
defining object. */
|
|
||||||
|
|
||||||
static inline void
|
#if ! ELF_MACHINE_NO_REL
|
||||||
elf_dynamic_relocate (Elf32_Dyn *dynamic[DT_NUM], Elf32_Addr loadaddr,
|
#include "do-rel.h"
|
||||||
int lazy, Elf32_Addr (*resolve) (const Elf32_Sym **))
|
#define ELF_DYNAMIC_DO_REL(map, lazy, resolve) \
|
||||||
{
|
if ((map)->l_info[DT_REL]) \
|
||||||
const Elf32_Sym *const symtab
|
elf_dynamic_do_rel ((map), DT_REL, DT_RELSZ, (resolve)); \
|
||||||
= (const Elf32_Sym *) dynamic[DT_SYMTAB]->d_un.d_ptr;
|
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 ! ELF_MACHINE_NO_RELA
|
||||||
{
|
#define DO_RELA
|
||||||
if (ELF32_R_SYM (info) == STN_UNDEF)
|
#include "do-rel.h"
|
||||||
return 0; /* This value will not be consulted. */
|
#define ELF_DYNAMIC_DO_RELA(map, lazy, resolve) \
|
||||||
*definer = &symtab[ELF32_R_SYM (info)];
|
if ((map)->l_info[DT_RELA]) \
|
||||||
return (*resolve) (definer);
|
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. */
|
/* This can't just be an inline function because GCC is too dumb
|
||||||
inline void do_rel (Elf32_Word reltag, Elf32_Word sztag)
|
to inline functions containing inlines themselves. */
|
||||||
{
|
#define ELF_DYNAMIC_RELOCATE(map, lazy, resolve) \
|
||||||
const Elf32_Rel *r = (const Elf32_Rel *) dynamic[reltag]->d_un.d_ptr;
|
do { ELF_DYNAMIC_DO_REL ((map), (lazy), (resolve)); \
|
||||||
const Elf32_Rel *end = &r[dynamic[sztag]->d_un.d_val / sizeof *r];
|
ELF_DYNAMIC_DO_RELA ((map), (lazy), (resolve)); } while (0)
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
26
elf/link.h
26
elf/link.h
@ -131,17 +131,23 @@ extern void _dl_sysdep_fatal (const char *string, ...)
|
|||||||
extern int _dl_secure;
|
extern int _dl_secure;
|
||||||
|
|
||||||
/* This function is called by all the internal dynamic linker functions
|
/* This function is called by all the internal dynamic linker functions
|
||||||
when they encounter an error. ERRCODE is either an `errno' code
|
when they encounter an error. ERRCODE is either an `errno' code or
|
||||||
or zero; ERRSTRING is a string describing the specific problem. */
|
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__));
|
__attribute__ ((__noreturn__));
|
||||||
|
|
||||||
/* Call OPERATE, catching errors from `dl_signal_error'. If there is no
|
/* 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
|
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING and
|
||||||
set to the string passed to _dl_signal_error, and the error code passed
|
*OBJECT are set to the strings passed to _dl_signal_error, and the error
|
||||||
is the return value. */
|
code passed is the return value. */
|
||||||
extern int _dl_catch_error (const char **errstring, void (*operate) (void));
|
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
|
/* 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
|
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||||
reference; it is replaced with the defining symbol, and the base load
|
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
|
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,
|
extern Elf32_Addr _dl_lookup_symbol (const char *undef,
|
||||||
const Elf32_Sym **sym,
|
const Elf32_Sym **sym,
|
||||||
struct link_map *symbol_scope);
|
struct link_map *symbol_scope,
|
||||||
|
const char *reference_name);
|
||||||
|
|
||||||
|
|
||||||
/* List of objects currently loaded. */
|
/* 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
|
Elf32_Addr
|
||||||
_dl_start (void *arg)
|
_dl_start (void *arg)
|
||||||
{
|
{
|
||||||
Elf32_Addr rtld_loadaddr;
|
struct link_map rtld_map;
|
||||||
Elf32_Dyn *dynamic_section;
|
|
||||||
Elf32_Dyn *dynamic_info[DT_NUM];
|
|
||||||
|
|
||||||
/* Figure out the run-time load address of the dynamic linker itself. */
|
/* 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.
|
/* Read our own dynamic section and fill in the info array.
|
||||||
Conveniently, the first element of the GOT contains the
|
Conveniently, the first element of the GOT contains the
|
||||||
offset of _DYNAMIC relative to the run-time load address. */
|
offset of _DYNAMIC relative to the run-time load address. */
|
||||||
dynamic_section = (void *) rtld_loadaddr + *elf_machine_got ();
|
rtld_map.l_ld = (void *) rtld_map.l_addr + *elf_machine_got ();
|
||||||
elf_get_dynamic_info (dynamic_section, dynamic_info);
|
elf_get_dynamic_info (rtld_map.l_ld, rtld_map.l_info);
|
||||||
|
|
||||||
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
|
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
|
||||||
ELF_MACHINE_BEFORE_RTLD_RELOC (dynamic_info);
|
ELF_MACHINE_BEFORE_RTLD_RELOC (rtld_map.l_info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Relocate ourselves so we can do normal function calls and
|
/* Relocate ourselves so we can do normal function calls and
|
||||||
data access using the global offset table. */
|
data access using the global offset table. */
|
||||||
{
|
|
||||||
Elf32_Addr resolve (const Elf32_Sym **ref)
|
ELF_DYNAMIC_RELOCATE (&rtld_map, 0, NULL);
|
||||||
{
|
|
||||||
assert ((*ref)->st_shndx != SHN_UNDEF);
|
|
||||||
return rtld_loadaddr;
|
|
||||||
}
|
|
||||||
elf_dynamic_relocate (dynamic_info, rtld_loadaddr, 0, resolve);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now life is sane; we can call functions and access global data.
|
/* Now life is sane; we can call functions and access global data.
|
||||||
Set up to use the operating system facilities, and find out from
|
Set up to use the operating system facilities, and find out from
|
||||||
the operating system's program loader where to find the program
|
the operating system's program loader where to find the program
|
||||||
header table in core. */
|
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
|
/* 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
|
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)
|
void doit (void)
|
||||||
{
|
{
|
||||||
const Elf32_Phdr *ph;
|
const Elf32_Phdr *ph;
|
||||||
struct link_map *l;
|
struct link_map *l;
|
||||||
const char *interpreter_name;
|
const char *interpreter_name;
|
||||||
int lazy;
|
int lazy;
|
||||||
|
|
||||||
if (*user_entry == (Elf32_Addr) &_start)
|
if (*user_entry == (Elf32_Addr) &_start)
|
||||||
{
|
{
|
||||||
/* Ho ho. We are not the program interpreter! We are the program
|
/* Ho ho. We are not the program interpreter! We are the program
|
||||||
itself! This means someone ran ld.so as a command. Well, that
|
itself! This means someone ran ld.so as a command. Well, that
|
||||||
might be convenient to do sometimes. We support it by
|
might be convenient to do sometimes. We support it by
|
||||||
interpreting the args like this:
|
interpreting the args like this:
|
||||||
|
|
||||||
ld.so PROGRAM ARGS...
|
ld.so PROGRAM ARGS...
|
||||||
|
|
||||||
The first argument is the name of a file containing an ELF
|
The first argument is the name of a file containing an ELF
|
||||||
executable we will load and run with the following arguments. To
|
executable we will load and run with the following arguments.
|
||||||
simplify life here, PROGRAM is searched for using the normal rules
|
To simplify life here, PROGRAM is searched for using the
|
||||||
for shared objects, rather than $PATH or anything like that. We
|
normal rules for shared objects, rather than $PATH or anything
|
||||||
just load it and use its entry point; we don't pay attention to
|
like that. We just load it and use its entry point; we don't
|
||||||
its PT_INTERP command (we are the interpreter ourselves). This is
|
pay attention to its PT_INTERP command (we are the interpreter
|
||||||
an easy way to test a new ld.so before installing it. */
|
ourselves). This is an easy way to test a new ld.so before
|
||||||
if (_dl_argc < 2)
|
installing it. */
|
||||||
_dl_sysdep_fatal ("\
|
if (_dl_argc < 2)
|
||||||
|
_dl_sysdep_fatal ("\
|
||||||
Usage: ld.so EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
Usage: ld.so EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||||
You have invoked `ld.so', the helper program for shared library executables.\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\
|
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\
|
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\
|
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"
|
||||||
);
|
);
|
||||||
|
|
||||||
interpreter_name = _dl_argv[0];
|
interpreter_name = _dl_argv[0];
|
||||||
--_dl_argc;
|
--_dl_argc;
|
||||||
++_dl_argv;
|
++_dl_argv;
|
||||||
l = _dl_map_object (NULL, _dl_argv[0], user_entry);
|
l = _dl_map_object (NULL, _dl_argv[0], user_entry);
|
||||||
phdr = l->l_phdr;
|
phdr = l->l_phdr;
|
||||||
phent = l->l_phnum;
|
phent = l->l_phnum;
|
||||||
l->l_type = lt_executable;
|
l->l_type = lt_executable;
|
||||||
l->l_libname = (char *) "";
|
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);
|
|
||||||
}
|
}
|
||||||
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 *errstring;
|
||||||
|
const char *errobj;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = _dl_catch_error (&errstring, &doit);
|
err = _dl_catch_error (&errstring, &errobj, &doit);
|
||||||
if (errstring)
|
if (errstring)
|
||||||
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
_dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
|
||||||
": error in loading shared libraries\n",
|
": error in loading shared libraries\n",
|
||||||
|
errobj ?: "", errobj ? ": " : "",
|
||||||
errstring, err ? ": " : NULL,
|
errstring, err ? ": " : NULL,
|
||||||
err ? strerror (err) : NULL, 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. */
|
/* Nobody cares about this signal. */
|
||||||
break;
|
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 term: /* Time to die. */
|
||||||
case core: /* And leave a rotting corpse. */
|
case core: /* And leave a rotting corpse. */
|
||||||
nirvana:
|
|
||||||
/* Have the proc server stop all other threads in our task. */
|
/* Have the proc server stop all other threads in our task. */
|
||||||
err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
|
err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
|
||||||
assert_perror (err);
|
assert_perror (err);
|
||||||
@ -693,7 +700,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
|||||||
case handle:
|
case handle:
|
||||||
/* Call a handler for this signal. */
|
/* Call a handler for this signal. */
|
||||||
{
|
{
|
||||||
struct sigcontext *scp;
|
struct sigcontext *scp, ocontext;
|
||||||
int wait_for_reply, state_changed;
|
int wait_for_reply, state_changed;
|
||||||
|
|
||||||
/* Stop the thread and abort its pending RPC operations. */
|
/* 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. */
|
thread_get_state is never kosher before thread_abort. */
|
||||||
abort_thread (ss, &thread_state, NULL, 0, 0);
|
abort_thread (ss, &thread_state, NULL, 0, 0);
|
||||||
|
|
||||||
wait_for_reply = (abort_rpcs (ss, signo, &thread_state, &state_changed,
|
if (ss->context)
|
||||||
&reply_port, reply_port_type, untraced)
|
|
||||||
!= MACH_PORT_NULL);
|
|
||||||
|
|
||||||
if (ss->critical_section)
|
|
||||||
{
|
{
|
||||||
/* The thread is in a critical section. Mark the signal as
|
/* We have a previous sigcontext that sigreturn was about
|
||||||
pending. When it finishes the critical section, it will
|
to restore when another signal arrived. */
|
||||||
check for pending signals. */
|
|
||||||
mark_pending ();
|
mach_port_t *loc;
|
||||||
assert (! state_changed);
|
|
||||||
__thread_resume (ss->thread);
|
if (_hurdsig_catch_fault (SIGSEGV))
|
||||||
break;
|
{
|
||||||
|
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
|
/* Call the machine-dependent function to set the thread up
|
||||||
@ -731,18 +783,10 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
|||||||
signo, sigcode,
|
signo, sigcode,
|
||||||
wait_for_reply, &thread_state);
|
wait_for_reply, &thread_state);
|
||||||
if (scp == NULL)
|
if (scp == NULL)
|
||||||
{
|
goto 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;
|
|
||||||
goto nirvana;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the machine-independent parts of the signal context. */
|
/* Set the machine-independent parts of the signal context. */
|
||||||
|
|
||||||
scp->sc_error = sigerror;
|
|
||||||
{
|
{
|
||||||
/* Fetch the thread variable for the MiG reply port,
|
/* Fetch the thread variable for the MiG reply port,
|
||||||
and set it to MACH_PORT_NULL. */
|
and set it to MACH_PORT_NULL. */
|
||||||
@ -754,17 +798,32 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
scp->sc_reply_port = MACH_PORT_NULL;
|
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. */
|
/* Block SIGNO and requested signals while running the handler. */
|
||||||
scp->sc_mask = ss->blocked;
|
scp->sc_mask = ss->blocked;
|
||||||
ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
|
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
|
/* Start the thread running the handler (or possibly waiting for an
|
||||||
RPC reply before running the handler). */
|
RPC reply before running the handler). */
|
||||||
err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
|
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.
|
# Be sure not to make these with implicit rules from foo.defs.
|
||||||
mach.h mach/memory_object.h: ;
|
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
|
generated += errsystems.c
|
||||||
$(objpfx)errsystems.c: errsystems.awk err_*.sub \
|
$(objpfx)errsystems.c: errsystems.awk err_*.sub \
|
||||||
$(wildcard $(addsuffix /err_*.sub,$(+sysdep_dirs)))
|
$(wildcard $(addsuffix /err_*.sub,$(+sysdep_dirs)))
|
||||||
gawk -v subsys='$(filter-out $<,$^)' -f $^ > $@.n
|
gawk -v subsys='$(filter-out $<,$^)' -f $^ > $@.n
|
||||||
mv $@.n $@
|
mv $@.n $@
|
||||||
|
endif
|
||||||
|
@ -68,11 +68,10 @@ elf_machine_load_address (void)
|
|||||||
++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr;
|
++(const Elf32_Rel *) (dynamic_info)[DT_REL]->d_un.d_ptr;
|
||||||
|
|
||||||
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
/* 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
|
MAP is the object containing the reloc. */
|
||||||
by DT_* of the .dynamic section info. */
|
|
||||||
|
|
||||||
static inline void
|
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,
|
const Elf32_Rel *reloc,
|
||||||
Elf32_Addr sym_loadaddr, const Elf32_Sym *sym)
|
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;
|
*reloc_addr += sym_value;
|
||||||
break;
|
break;
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
*reloc_addr += loadaddr;
|
*reloc_addr += map->l_addr;
|
||||||
break;
|
break;
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
*reloc_addr = sym_value - (Elf32_Addr) reloc_addr;
|
*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. */
|
/* The i386 never uses Elf32_Rela relocations. */
|
||||||
static inline void
|
#define ELF_MACHINE_NO_RELA 1
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Set up the loaded object described by L so its unrelocated PLT
|
/* 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 ("\
|
#define RTLD_START asm ("\
|
||||||
.text\n\
|
.text\n\
|
||||||
.globl _start\n\
|
.globl _start\n\
|
||||||
_start: call _dl_start\n\
|
.globl _dl_start_user\n\
|
||||||
# Save the user entry point address in %ebx.\n\
|
_start:\n\
|
||||||
movl %eax, %ebx\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\
|
# 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\
|
||||||
@ -160,10 +160,7 @@ _start: call _dl_start\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\
|
# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
|
||||||
1: call 2f\n\
|
leal _dl_fini@GOT(%ebx), %edx\n\
|
||||||
2: popl %eax\n\
|
# Jump to the user's entry point.\n\
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %eax\n\
|
jmp *%edi\n\
|
||||||
leal _dl_fini@GOT(%eax), %edx\n\
|
|
||||||
# Jump to the user entry point.\n\
|
|
||||||
jmp *%ebx\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,
|
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||||
Cambridge, MA 02139, USA. */
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
register void *sp asm ("%esp");
|
|
||||||
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include "dynamic-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 *)
|
0(%esp) identifier for this shared object (struct link_map *)
|
||||||
|
|
||||||
The user expects the real function the PLT refers to to be entered
|
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
|
void
|
||||||
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
_dl_runtime_resolve (Elf32_Word reloc_offset)
|
||||||
@ -63,14 +61,15 @@ _dl_runtime_resolve (Elf32_Word reloc_offset)
|
|||||||
scope = _dl_loaded;
|
scope = _dl_loaded;
|
||||||
|
|
||||||
definer = &symtab[ELF32_R_SYM (reloc->r_info)];
|
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. */
|
/* Restore list frobnication done above for DT_SYMBOLIC. */
|
||||||
l->l_next = real_next;
|
l->l_next = real_next;
|
||||||
l->l_prev->l_next = l;
|
l->l_prev->l_next = l;
|
||||||
|
|
||||||
/* Apply the relocation with that value. */
|
/* 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
|
/* 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
|
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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
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 <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mach/error.h>
|
#include <mach/error.h>
|
||||||
#include <mach/errorlib.h>
|
#include <errorlib.h>
|
||||||
|
|
||||||
/* Return a string describing the errno code in ERRNUM. */
|
/* Return a string describing the errno code in ERRNUM. */
|
||||||
char *
|
char *
|
||||||
@ -38,7 +38,7 @@ DEFUN(_strerror_internal, (errnum, buf), int errnum AND char buf[1024])
|
|||||||
sub = err_get_sub (errnum);
|
sub = err_get_sub (errnum);
|
||||||
code = err_get_code (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);
|
sprintf (buf, "Unknown error system %d", system);
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -21,6 +21,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <hurd.h>
|
#include <hurd.h>
|
||||||
#include <hurd/fd.h>
|
#include <hurd/fd.h>
|
||||||
|
#include <hurd/resource.h>
|
||||||
|
|
||||||
/* Return the maximum number of file descriptors the current process
|
/* Return the maximum number of file descriptors the current process
|
||||||
could possibly have (until it raises the resource limit). */
|
could possibly have (until it raises the resource limit). */
|
||||||
@ -29,9 +30,9 @@ DEFUN_VOID(__getdtablesize)
|
|||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
HURD_CRITICAL_BEGIN;
|
HURD_CRITICAL_BEGIN;
|
||||||
__mutex_lock (&_hurd_rlimits_lock);
|
__mutex_lock (&_hurd_rlimit_lock);
|
||||||
size = _hurd_rlimits[RLIM_NOFILE].rlim_cur; /* XXX RLIM_INFINITY?? */
|
size = _hurd_rlimits[RLIMIT_NOFILE].rlim_cur;
|
||||||
__mutex_unlock (&_hurd_rlimits_lock);
|
__mutex_unlock (&_hurd_rlimit_lock);
|
||||||
HURD_CRITICAL_END;
|
HURD_CRITICAL_END;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -57,15 +57,13 @@ __sigreturn (struct sigcontext *scp)
|
|||||||
the signal thread will notice it if it runs another handler, and
|
the signal thread will notice it if it runs another handler, and
|
||||||
arrange to have us called over again in the new reality. */
|
arrange to have us called over again in the new reality. */
|
||||||
ss->context = scp;
|
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);
|
__spin_unlock (&ss->lock);
|
||||||
__msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
|
__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);
|
__spin_lock (&ss->lock);
|
||||||
|
ss->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scp->sc_onstack)
|
if (scp->sc_onstack)
|
||||||
|
@ -73,23 +73,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
sizeof (state->basic));
|
sizeof (state->basic));
|
||||||
memcpy (&state->fpu, &ss->context->sc_i386_float_state,
|
memcpy (&state->fpu, &ss->context->sc_i386_float_state,
|
||||||
sizeof (state->fpu));
|
sizeof (state->fpu));
|
||||||
state->set = (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
|
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;
|
|
||||||
}
|
}
|
||||||
/* 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;
|
return NULL;
|
||||||
|
|
||||||
if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
|
if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user