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:
Roland McGrath 1995-05-08 09:11:25 +00:00
parent 0fb807c1db
commit 421f82e5cc
22 changed files with 471 additions and 355 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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");
}
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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
View 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

View file

@ -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)

View file

@ -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. */

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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\
");

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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)

View file

@ -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) &&