This commit is contained in:
christos 1999-03-01 16:40:07 +00:00
parent bc97a25328
commit 26475619ed
19 changed files with 1578 additions and 1422 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: link_elf.h,v 1.3 1998/10/30 05:43:40 jonathan Exp $ */
/* $NetBSD: link_elf.h,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* This only exists for GDB.
@ -11,24 +11,26 @@
#include <machine/elf_machdep.h>
struct link_map {
caddr_t l_addr; /* Base Address of library */
caddr_t l_addr; /* Base Address of library */
#ifdef __mips__
caddr_t l_offs; /* Load Offset of library */
caddr_t l_offs; /* Load Offset of library */
#endif
const char *l_name; /* Absolute Path to Library */
void *l_ld; /* Pointer to .dynamic in memory */
struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
const char *l_name; /* Absolute Path to Library */
void *l_ld; /* Pointer to .dynamic in memory */
struct link_map *l_next; /* linked list of of mapped libs */
struct link_map *l_prev;
};
struct r_debug {
int r_version; /* not used */
struct link_map *r_map; /* list of loaded images */
void (*r_brk)(void); /* pointer to break point */
int r_version; /* not used */
struct link_map *r_map; /* list of loaded images */
void (*r_brk) __P((void)); /* pointer to break point */
enum {
RT_CONSISTENT, /* things are stable */
RT_ADD, /* adding a shared library */
RT_DELETE /* removing a shared library */
} r_state;
RT_CONSISTENT, /* things are stable */
RT_ADD, /* adding a shared library */
RT_DELETE /* removing a shared library */
} r_state;
};
#endif /* _LINK_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ppc_reloc.c,v 1.1 1998/11/24 11:34:31 tsubai Exp $ */
/* $NetBSD: ppc_reloc.c,v 1.2 1999/03/01 16:40:08 christos Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@ -37,11 +37,11 @@
#include "debug.h"
#include "rtld.h"
extern caddr_t _rtld_bind_powerpc(const Obj_Entry *, Elf_Word);
extern void _rtld_powerpc_pltcall(Elf_Word);
extern void _rtld_powerpc_pltresolve(Elf_Word, Elf_Word);
caddr_t _rtld_bind_powerpc __P((const Obj_Entry *, Elf_Word));
void _rtld_powerpc_pltcall __P((Elf_Word));
void _rtld_powerpc_pltresolve __P((Elf_Word, Elf_Word));
static Elf_Addr _rtld_bind_pltgot(const Obj_Entry *, const Elf_RelA *);
static Elf_Addr _rtld_bind_pltgot __P((const Obj_Entry *, const Elf_RelA *));
#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)

View File

@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.6 1999/02/27 17:12:13 pk Exp $ */
/* $NetBSD: mdreloc.c,v 1.7 1999/03/01 16:40:08 christos Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -160,10 +160,10 @@ static int reloc_target_bitmask[] = {
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
int
_rtld_relocate_nonplt_object(
const Obj_Entry *obj,
const Elf_RelA *rela,
bool dodebug)
_rtld_relocate_nonplt_object(obj, rela, dodebug)
const Obj_Entry *obj;
const Elf_RelA *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf_Word type, value, mask;
@ -262,12 +262,12 @@ _rtld_relocate_nonplt_object(
}
int
_rtld_relocate_plt_object(
const Obj_Entry *obj,
const Elf_RelA *rela,
caddr_t *addrp,
bool bind_now,
bool dodebug)
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
const Obj_Entry *obj;
const Elf_RelA *rela;
caddr_t *addrp;
bool bind_now;
bool dodebug;
{
const Elf_Sym *def;
const Obj_Entry *defobj;

View File

@ -1,4 +1,4 @@
/* $NetBSD: debug.c,v 1.1 1996/12/16 20:37:57 cgd Exp $ */
/* $NetBSD: debug.c,v 1.2 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -35,7 +35,12 @@
* Support for printing debugging messages.
*/
#include <sys/cdefs.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "debug.h"
#include "rtldenv.h"
@ -44,16 +49,28 @@
int debug = 0;
void
#ifdef __STDC__
debug_printf(const char *format, ...)
#else
debug_printf(va_alist)
va_dcl
#endif
{
if(debug) {
va_list ap;
va_start(ap, format);
if(debug) {
va_list ap;
#ifdef __STDC__
va_start(ap, format);
#else
const char *format;
xvprintf(format, ap);
va_start(ap);
format = va_arg(ap, const char *);
#endif
va_end(ap);
xprintf("\n");
}
xvprintf(format, ap);
va_end(ap);
xprintf("\n");
}
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: debug.h,v 1.3 1999/02/24 18:31:00 christos Exp $ */
/* $NetBSD: debug.h,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -35,30 +35,24 @@
* Support for printing debugging messages.
*/
#ifndef DEBUG_H /* { */
#define DEBUG_H 1
#ifndef DEBUG_H
#define DEBUG_H
#ifndef __GNUC__ /* { */
#error "Sorry, this module relies on some GNU extensions"
#endif /* } */
extern void xprintf(const char *fmt, ...)
__attribute__((__format__(__printf__, 1, 2)));
extern void xvprintf(const char *fmt, va_list ap)
__attribute__((__format__(__printf__, 1, 0)));
extern void debug_printf(const char *, ...)
#ifdef DEBUG
extern void debug_printf __P((const char *, ...))
__attribute__((__format__(__printf__, 1, 2)));
extern int debug;
#ifdef DEBUG /* { */
#define dbg(format, args...) debug_printf(format, ## args)
#else /* } { */
#define dbg(format, args...) ((void) 0)
#endif /* } */
# define dbg(a) debug_printf a
#else
# define dbg(a) ((void) 0)
#endif
#ifdef RTLD_DEBUG_RELOC
#define rdbg(f, format, args...) if (f) debug_printf(format, ## args)
# define rdbg(f, a) if (f) debug_printf a
#else
#define rdbg(f, format, args...) ((void) 0)
# define rdbg(f, a) ((void) 0)
#endif
#endif /* } */
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: headers.c,v 1.3 1999/02/24 18:31:00 christos Exp $ */
/* $NetBSD: headers.c,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -57,181 +57,193 @@
* information in its Obj_Entry structure.
*/
void
_rtld_digest_dynamic(
Obj_Entry *obj)
_rtld_digest_dynamic(obj)
Obj_Entry *obj;
{
Elf_Dyn *dynp;
Needed_Entry **needed_tail = &obj->needed;
const Elf_Dyn *dyn_rpath = NULL;
enum Elf_e_dynamic_type plttype = Elf_edt_rel;
Elf_Word relsize = 0, relasize = 0, pltrelsize = 0, pltrelasize = 0;
Elf_Dyn *dynp;
Needed_Entry **needed_tail = &obj->needed;
const Elf_Dyn *dyn_rpath = NULL;
enum Elf_e_dynamic_type plttype = Elf_edt_rel;
Elf_Word relsz = 0, relasz = 0;
Elf_Word pltrelsz = 0, pltrelasz = 0;
for (dynp = obj->dynamic; dynp->d_tag != Elf_edt_null; ++dynp) {
switch(dynp->d_tag) {
for (dynp = obj->dynamic; dynp->d_tag != Elf_edt_null; ++dynp) {
switch (dynp->d_tag) {
case Elf_edt_rel:
obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_rel:
obj->rel = (const Elf_Rel *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_relsz:
relsize = dynp->d_un.d_val;
break;
case Elf_edt_relsz:
relsz = dynp->d_un.d_val;
break;
case Elf_edt_relent:
assert(dynp->d_un.d_val == sizeof(Elf_Rel));
break;
case Elf_edt_relent:
assert(dynp->d_un.d_val == sizeof(Elf_Rel));
break;
case Elf_edt_jmprel:
if (plttype == Elf_edt_rel) {
obj->pltrel = (const Elf_Rel *)
(obj->relocbase + dynp->d_un.d_ptr);
} else {
obj->pltrela = (const Elf_RelA *)
(obj->relocbase + dynp->d_un.d_ptr);
}
break;
case Elf_edt_jmprel:
if (plttype == Elf_edt_rel) {
obj->pltrel = (const Elf_Rel *)
(obj->relocbase + dynp->d_un.d_ptr);
} else {
obj->pltrela = (const Elf_RelA *)
(obj->relocbase + dynp->d_un.d_ptr);
}
break;
case Elf_edt_pltrelsz:
if (plttype == Elf_edt_rel) {
pltrelsize = dynp->d_un.d_val;
} else {
pltrelasize = dynp->d_un.d_val;
}
break;
case Elf_edt_pltrelsz:
if (plttype == Elf_edt_rel) {
pltrelsz = dynp->d_un.d_val;
} else {
pltrelasz = dynp->d_un.d_val;
}
break;
case Elf_edt_rela:
obj->rela = (const Elf_RelA *) (obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_rela:
obj->rela = (const Elf_RelA *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_relasz:
relasize = dynp->d_un.d_val;
break;
case Elf_edt_relasz:
relasz = dynp->d_un.d_val;
break;
case Elf_edt_relaent:
assert(dynp->d_un.d_val == sizeof(Elf_RelA));
break;
case Elf_edt_relaent:
assert(dynp->d_un.d_val == sizeof(Elf_RelA));
break;
case Elf_edt_pltrel:
plttype = dynp->d_un.d_val;
assert(plttype == Elf_edt_rel || plttype == Elf_edt_rela);
if (plttype == Elf_edt_rela) {
obj->pltrela = (const Elf_RelA *) obj->pltrel;
obj->pltrel = NULL;
pltrelasize = pltrelsize;
pltrelsize = 0;
}
break;
case Elf_edt_pltrel:
plttype = dynp->d_un.d_val;
assert(plttype == Elf_edt_rel ||
plttype == Elf_edt_rela);
if (plttype == Elf_edt_rela) {
obj->pltrela = (const Elf_RelA *) obj->pltrel;
obj->pltrel = NULL;
pltrelasz = pltrelsz;
pltrelsz = 0;
}
break;
case Elf_edt_symtab:
obj->symtab = (const Elf_Sym *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_symtab:
obj->symtab = (const Elf_Sym *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_syment:
assert(dynp->d_un.d_val == sizeof(Elf_Sym));
break;
case Elf_edt_syment:
assert(dynp->d_un.d_val == sizeof(Elf_Sym));
break;
case Elf_edt_strtab:
obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_strtab:
obj->strtab = (const char *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_strsz:
obj->strsize = dynp->d_un.d_val;
break;
case Elf_edt_strsz:
obj->strsize = dynp->d_un.d_val;
break;
case Elf_edt_hash:
{
const Elf_Word *hashtab = (const Elf_Word *)
(obj->relocbase + dynp->d_un.d_ptr);
obj->nbuckets = hashtab[0];
obj->nchains = hashtab[1];
obj->buckets = hashtab + 2;
obj->chains = obj->buckets + obj->nbuckets;
}
break;
case Elf_edt_hash:
{
const Elf_Word *hashtab = (const Elf_Word *)
(obj->relocbase + dynp->d_un.d_ptr);
case Elf_edt_needed:
assert(!obj->rtld);
{
Needed_Entry *nep = NEW(Needed_Entry);
nep->name = dynp->d_un.d_val;
nep->obj = NULL;
nep->next = NULL;
obj->nbuckets = hashtab[0];
obj->nchains = hashtab[1];
obj->buckets = hashtab + 2;
obj->chains = obj->buckets + obj->nbuckets;
}
break;
*needed_tail = nep;
needed_tail = &nep->next;
}
break;
case Elf_edt_needed:
assert(!obj->rtld);
{
Needed_Entry *nep = NEW(Needed_Entry);
case Elf_edt_pltgot:
obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr);
break;
nep->name = dynp->d_un.d_val;
nep->obj = NULL;
nep->next = NULL;
case Elf_edt_textrel:
obj->textrel = true;
break;
*needed_tail = nep;
needed_tail = &nep->next;
}
break;
case Elf_edt_symbolic:
obj->symbolic = true;
break;
case Elf_edt_pltgot:
obj->pltgot = (Elf_Addr *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_rpath:
/*
* We have to wait until later to process this, because we
* might not have gotten the address of the string table yet.
*/
dyn_rpath = dynp;
break;
case Elf_edt_textrel:
obj->textrel = true;
break;
case Elf_edt_soname:
/* Not used by the dynamic linker. */
break;
case Elf_edt_symbolic:
obj->symbolic = true;
break;
case Elf_edt_init:
obj->init = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_rpath:
/*
* We have to wait until later to process this, because
* we might not have gotten the address of the string
* table yet.
*/
dyn_rpath = dynp;
break;
case Elf_edt_fini:
obj->fini = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_soname:
/* Not used by the dynamic linker. */
break;
case Elf_edt_debug:
case Elf_edt_init:
obj->init = (void (*) __P((void)))
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_fini:
obj->fini = (void (*) __P((void)))
(obj->relocbase + dynp->d_un.d_ptr);
break;
case Elf_edt_debug:
#ifdef RTLD_LOADER
dynp->d_un.d_ptr = (Elf_Addr) &_rtld_debug;
dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
#endif
break;
break;
#if defined(__mips__)
case DT_MIPS_LOCAL_GOTNO:
obj->local_gotno = dynp->d_un.d_val;
break;
case DT_MIPS_LOCAL_GOTNO:
obj->local_gotno = dynp->d_un.d_val;
break;
case DT_MIPS_SYMTABNO:
obj->symtabno = dynp->d_un.d_val;
break;
case DT_MIPS_SYMTABNO:
obj->symtabno = dynp->d_un.d_val;
break;
case DT_MIPS_GOTSYM:
obj->gotsym = dynp->d_un.d_val;
break;
case DT_MIPS_GOTSYM:
obj->gotsym = dynp->d_un.d_val;
break;
case DT_MIPS_RLD_MAP:
case DT_MIPS_RLD_MAP:
#ifdef RTLD_LOADER
*((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) &_rtld_debug;
*((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
&_rtld_debug;
#endif
break;
break;
#endif
}
}
}
obj->rellim = (const Elf_Rel *) ((caddr_t) obj->rel + relsize);
obj->relalim = (const Elf_RelA *) ((caddr_t) obj->rela + relasize);
obj->pltrellim = (const Elf_Rel *) ((caddr_t) obj->pltrel + pltrelsize);
obj->pltrelalim = (const Elf_RelA *) ((caddr_t) obj->pltrela + pltrelasize);
obj->rellim = (const Elf_Rel *)((caddr_t)obj->rel + relsz);
obj->relalim = (const Elf_RelA *)((caddr_t)obj->rela + relasz);
obj->pltrellim = (const Elf_Rel *)((caddr_t)obj->pltrel + pltrelsz);
obj->pltrelalim = (const Elf_RelA *)((caddr_t)obj->pltrela + pltrelasz);
if (dyn_rpath != NULL) {
_rtld_add_paths(&obj->rpaths, obj->strtab + dyn_rpath->d_un.d_val,
true);
}
if (dyn_rpath != NULL) {
_rtld_add_paths(&obj->rpaths, obj->strtab +
dyn_rpath->d_un.d_val, true);
}
}
/*
@ -241,47 +253,47 @@ _rtld_digest_dynamic(
* returns an Obj_Entry structure.
*/
Obj_Entry *
_rtld_digest_phdr(
const Elf_Phdr *phdr,
int phnum,
caddr_t entry)
_rtld_digest_phdr(phdr, phnum, entry)
const Elf_Phdr *phdr;
int phnum;
caddr_t entry;
{
Obj_Entry *obj = CNEW(Obj_Entry);
const Elf_Phdr *phlimit = phdr + phnum;
const Elf_Phdr *ph;
int nsegs = 0;
Obj_Entry *obj = CNEW(Obj_Entry);
const Elf_Phdr *phlimit = phdr + phnum;
const Elf_Phdr *ph;
int nsegs = 0;
for (ph = phdr; ph < phlimit; ++ph) {
switch(ph->p_type) {
for (ph = phdr; ph < phlimit; ++ph) {
switch (ph->p_type) {
case Elf_pt_phdr:
assert((const Elf_Phdr *) ph->p_vaddr == phdr);
obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
obj->phsize = ph->p_memsz;
break;
case Elf_pt_phdr:
assert((const Elf_Phdr *) ph->p_vaddr == phdr);
obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
obj->phsize = ph->p_memsz;
break;
case Elf_pt_load:
assert(nsegs < 2);
if (nsegs == 0) { /* First load segment */
obj->vaddrbase = round_down(ph->p_vaddr);
obj->mapbase = (caddr_t) obj->vaddrbase;
obj->relocbase = obj->mapbase - obj->vaddrbase;
obj->textsize = round_up(ph->p_vaddr + ph->p_memsz) -
obj->vaddrbase;
} else { /* Last load segment */
obj->mapsize = round_up(ph->p_vaddr + ph->p_memsz) -
obj->vaddrbase;
}
++nsegs;
break;
case Elf_pt_load:
assert(nsegs < 2);
if (nsegs == 0) { /* First load segment */
obj->vaddrbase = round_down(ph->p_vaddr);
obj->mapbase = (caddr_t) obj->vaddrbase;
obj->relocbase = obj->mapbase - obj->vaddrbase;
obj->textsize = round_up(ph->p_vaddr +
ph->p_memsz) - obj->vaddrbase;
} else { /* Last load segment */
obj->mapsize = round_up(ph->p_vaddr +
ph->p_memsz) - obj->vaddrbase;
}
++nsegs;
break;
case Elf_pt_dynamic:
obj->dynamic = (Elf_Dyn *) ph->p_vaddr;
break;
case Elf_pt_dynamic:
obj->dynamic = (Elf_Dyn *) ph->p_vaddr;
break;
}
}
}
assert(nsegs == 2);
assert(nsegs == 2);
obj->entry = entry;
return obj;
obj->entry = entry;
return obj;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: link.h,v 1.3 1998/10/30 05:43:40 jonathan Exp $ */
/* $NetBSD: link.h,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* This only exists for GDB.
@ -11,24 +11,26 @@
#include <machine/elf_machdep.h>
struct link_map {
caddr_t l_addr; /* Base Address of library */
caddr_t l_addr; /* Base Address of library */
#ifdef __mips__
caddr_t l_offs; /* Load Offset of library */
caddr_t l_offs; /* Load Offset of library */
#endif
const char *l_name; /* Absolute Path to Library */
void *l_ld; /* Pointer to .dynamic in memory */
struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
const char *l_name; /* Absolute Path to Library */
void *l_ld; /* Pointer to .dynamic in memory */
struct link_map *l_next; /* linked list of of mapped libs */
struct link_map *l_prev;
};
struct r_debug {
int r_version; /* not used */
struct link_map *r_map; /* list of loaded images */
void (*r_brk)(void); /* pointer to break point */
int r_version; /* not used */
struct link_map *r_map; /* list of loaded images */
void (*r_brk) __P((void)); /* pointer to break point */
enum {
RT_CONSISTENT, /* things are stable */
RT_ADD, /* adding a shared library */
RT_DELETE /* removing a shared library */
} r_state;
RT_CONSISTENT, /* things are stable */
RT_ADD, /* adding a shared library */
RT_DELETE /* removing a shared library */
} r_state;
};
#endif /* _LINK_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: load.c,v 1.2 1999/02/24 18:31:00 christos Exp $ */
/* $NetBSD: load.c,v 1.3 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -61,49 +61,49 @@
* on failure.
*/
Obj_Entry *
_rtld_load_object(
char *filepath,
bool dodebug)
_rtld_load_object(filepath, dodebug)
char *filepath;
bool dodebug;
{
Obj_Entry *obj;
Obj_Entry *obj;
for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
if (strcmp(obj->path, filepath) == 0)
break;
for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
if (strcmp(obj->path, filepath) == 0)
break;
if (obj == NULL) { /* First use of this object, so we must map it in */
int fd;
if (obj == NULL) { /* First use of this object, so we must map it in */
int fd;
if ((fd = open(filepath, O_RDONLY)) == -1) {
_rtld_error("Cannot open \"%s\"", filepath);
return NULL;
}
obj = _rtld_map_object(filepath, fd);
close(fd);
if (obj == NULL) {
free(filepath);
return NULL;
}
if ((fd = open(filepath, O_RDONLY)) == -1) {
_rtld_error("Cannot open \"%s\"", filepath);
return NULL;
}
obj = _rtld_map_object(filepath, fd);
(void)close(fd);
if (obj == NULL) {
free(filepath);
return NULL;
}
obj->path = filepath;
_rtld_digest_dynamic(obj);
obj->path = filepath;
_rtld_digest_dynamic(obj);
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
#ifdef RTLD_LOADER
_rtld_linkmap_add(obj); /* for GDB */
_rtld_linkmap_add(obj); /* for GDB */
#endif
if (dodebug) {
dbg(" %p .. %p: %s", obj->mapbase,
obj->mapbase + obj->mapsize - 1, obj->path);
if (obj->textrel)
dbg(" WARNING: %s has impure text", obj->path);
}
} else
free(filepath);
if (dodebug) {
dbg((" %p .. %p: %s", obj->mapbase,
obj->mapbase + obj->mapsize - 1, obj->path));
if (obj->textrel)
dbg((" WARNING: %s has impure text",
obj->path));
}
} else
free(filepath);
++obj->refcount;
return obj;
++obj->refcount;
return obj;
}
/*
@ -112,32 +112,33 @@ _rtld_load_object(
* returns -1 on failure.
*/
int
_rtld_load_needed_objects(
Obj_Entry *first)
_rtld_load_needed_objects(first)
Obj_Entry *first;
{
Obj_Entry *obj;
int status = 0;
Obj_Entry *obj;
int status = 0;
for (obj = first; obj != NULL; obj = obj->next) {
Needed_Entry *needed;
for (obj = first; obj != NULL; obj = obj->next) {
Needed_Entry *needed;
for (needed = obj->needed; needed != NULL; needed = needed->next) {
const char *name = obj->strtab + needed->name;
char *libpath = _rtld_find_library(name, obj);
for (needed = obj->needed; needed != NULL;
needed = needed->next) {
const char *name = obj->strtab + needed->name;
char *libpath = _rtld_find_library(name, obj);
if (libpath == NULL) {
status = -1;
} else {
needed->obj = _rtld_load_object(libpath, true);
if (needed->obj == NULL)
status = -1; /* FIXME - cleanup */
}
if (libpath == NULL) {
status = -1;
} else {
needed->obj = _rtld_load_object(libpath, true);
if (needed->obj == NULL)
status = -1; /* FIXME - cleanup */
}
#ifdef RTLD_LOADER
if (status == -1)
return status;
if (status == -1)
return status;
#endif
}
}
}
return status;
return status;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: malloc.c,v 1.2 1997/10/08 08:55:35 mrg Exp $ */
/* $NetBSD: malloc.c,v 1.3 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright (c) 1983 Regents of the University of California.
@ -48,6 +48,7 @@
* This is designed for use in a virtual memory environment.
*/
#include <sys/cdefs.h>
#include "rtldenv.h"
#include <stdlib.h>
#include <string.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: map_object.c,v 1.3 1998/02/20 09:27:20 mycroft Exp $ */
/* $NetBSD: map_object.c,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -46,7 +46,7 @@
#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
static int protflags(int); /* Elf flags -> mmap protection */
static int protflags __P((int)); /* Elf flags -> mmap protection */
/*
* Map a shared object into memory. The argument is a file descriptor,
@ -56,202 +56,202 @@ static int protflags(int); /* Elf flags -> mmap protection */
* for the shared object. Returns NULL on failure.
*/
Obj_Entry *
_rtld_map_object(
const char *path,
int fd)
_rtld_map_object(path, fd)
const char *path;
int fd;
{
Obj_Entry *obj;
union {
Elf_Ehdr hdr;
char buf[PAGESIZE];
} u;
int nbytes;
Elf_Phdr *phdr;
Elf_Phdr *phlimit;
Elf_Phdr *segs[2];
int nsegs;
Elf_Phdr *phdyn;
Elf_Phdr *phphdr;
caddr_t mapbase;
size_t mapsize;
Elf_Off base_offset;
Elf_Addr base_vaddr;
Elf_Addr base_vlimit;
caddr_t base_addr;
Elf_Off data_offset;
Elf_Addr data_vaddr;
Elf_Addr data_vlimit;
caddr_t data_addr;
Obj_Entry *obj;
union {
Elf_Ehdr hdr;
char buf[PAGESIZE];
} u;
int nbytes;
Elf_Phdr *phdr;
Elf_Phdr *phlimit;
Elf_Phdr *segs[2];
int nsegs;
Elf_Phdr *phdyn;
Elf_Phdr *phphdr;
caddr_t mapbase;
size_t mapsize;
Elf_Off base_offset;
Elf_Addr base_vaddr;
Elf_Addr base_vlimit;
caddr_t base_addr;
Elf_Off data_offset;
Elf_Addr data_vaddr;
Elf_Addr data_vlimit;
caddr_t data_addr;
#ifdef RTLD_LOADER
Elf_Addr clear_vaddr;
caddr_t clear_addr;
size_t nclear;
Elf_Addr bss_vaddr;
Elf_Addr bss_vlimit;
caddr_t bss_addr;
Elf_Addr clear_vaddr;
caddr_t clear_addr;
size_t nclear;
Elf_Addr bss_vaddr;
Elf_Addr bss_vlimit;
caddr_t bss_addr;
#endif
if ((nbytes = read(fd, u.buf, PAGESIZE)) == -1) {
_rtld_error("%s: read error: %s", path, xstrerror(errno));
return NULL;
}
if ((nbytes = read(fd, u.buf, PAGESIZE)) == -1) {
_rtld_error("%s: read error: %s", path, xstrerror(errno));
return NULL;
}
/* Make sure the file is valid */
if (nbytes < sizeof(Elf_Ehdr) ||
memcmp(Elf_e_ident, u.hdr.e_ident, Elf_e_siz) != 0) {
_rtld_error("%s: unrecognized file format", path);
return NULL;
}
/* Elf_e_ident includes class */
if (u.hdr.e_ident[Elf_ei_version] != Elf_ev_current ||
u.hdr.e_version != Elf_ev_current ||
u.hdr.e_ident[Elf_ei_data] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
_rtld_error("%s: Unsupported file version", path);
return NULL;
}
if (u.hdr.e_type != Elf_et_exec && u.hdr.e_type != Elf_et_dyn) {
_rtld_error("%s: Unsupported file type", path);
return NULL;
}
switch (u.hdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES)
default:
_rtld_error("%s: Unsupported machine", path);
return NULL;
}
/* Make sure the file is valid */
if (nbytes < sizeof(Elf_Ehdr)
|| memcmp(Elf_e_ident, u.hdr.e_ident, Elf_e_siz) != 0) {
_rtld_error("%s: unrecognized file format", path);
return NULL;
}
/* Elf_e_ident includes class */
if (u.hdr.e_ident[Elf_ei_version] != Elf_ev_current
|| u.hdr.e_version != Elf_ev_current
|| u.hdr.e_ident[Elf_ei_data] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
_rtld_error("%s: Unsupported file version", path);
return NULL;
}
if (u.hdr.e_type != Elf_et_exec && u.hdr.e_type != Elf_et_dyn) {
_rtld_error("%s: Unsupported file type", path);
return NULL;
}
switch (u.hdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES)
/*
* We rely on the program header being in the first page. This is
* not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably.
*/
assert(u.hdr.e_phentsize == sizeof(Elf_Phdr));
assert(u.hdr.e_phoff + u.hdr.e_phnum * sizeof(Elf_Phdr) <= PAGESIZE);
assert(u.hdr.e_phoff + u.hdr.e_phnum * sizeof(Elf_Phdr) <= nbytes);
default:
_rtld_error("%s: Unsupported machine", path);
return NULL;
}
/*
* Scan the program header entries, and save key information.
*
* We rely on there being exactly two load segments, text and data,
* in that order.
*/
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
phlimit = phdr + u.hdr.e_phnum;
nsegs = 0;
phdyn = NULL;
phphdr = NULL;
while (phdr < phlimit) {
switch (phdr->p_type) {
/*
* We rely on the program header being in the first page. This is
* not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably.
*/
assert(u.hdr.e_phentsize == sizeof(Elf_Phdr));
assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGESIZE);
assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes);
/*
* Scan the program header entries, and save key information.
*
* We rely on there being exactly two load segments, text and data,
* in that order.
*/
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
phlimit = phdr + u.hdr.e_phnum;
nsegs = 0;
phdyn = NULL;
phphdr = NULL;
while(phdr < phlimit) {
switch(phdr->p_type) {
case Elf_pt_load:
case Elf_pt_load:
#ifdef __mips__
/* NetBSD/pmax 1.1 elf toolchain peculiarity */
if (nsegs >= 2) {
_rtld_error("%s: too many sections\n", path);
return NULL;
}
/* NetBSD/pmax 1.1 elf toolchain peculiarity */
if (nsegs >= 2) {
_rtld_error("%s: too many sections\n", path);
return NULL;
}
#endif
assert(nsegs < 2);
segs[nsegs] = phdr;
++nsegs;
break;
assert(nsegs < 2);
segs[nsegs] = phdr;
++nsegs;
break;
case Elf_pt_phdr:
phphdr = phdr;
break;
case Elf_pt_phdr:
phphdr = phdr;
break;
case Elf_pt_dynamic:
phdyn = phdr;
break;
case Elf_pt_dynamic:
phdyn = phdr;
break;
}
++phdr;
}
++phdr;
}
if (phdyn == NULL) {
_rtld_error("%s: not dynamically-linked", path);
return NULL;
}
assert(nsegs == 2);
if (phdyn == NULL) {
_rtld_error("%s: not dynamically-linked", path);
return NULL;
}
assert(nsegs == 2);
#ifdef __i386__
assert(segs[0]->p_align <= PAGESIZE);
assert(segs[1]->p_align <= PAGESIZE);
assert(segs[0]->p_align <= PAGESIZE);
assert(segs[1]->p_align <= PAGESIZE);
#endif
/*
* Map the entire address space of the object, to stake out our
* contiguous region, and to establish the base address for relocation.
*/
base_offset = round_down(segs[0]->p_offset);
base_vaddr = round_down(segs[0]->p_vaddr);
base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
mapsize = base_vlimit - base_vaddr;
/*
* Map the entire address space of the object, to stake out our
* contiguous region, and to establish the base address for relocation.
*/
base_offset = round_down(segs[0]->p_offset);
base_vaddr = round_down(segs[0]->p_vaddr);
base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
mapsize = base_vlimit - base_vaddr;
#ifdef RTLD_LOADER
base_addr = u.hdr.e_type == Elf_et_exec ? (caddr_t) base_vaddr : NULL;
base_addr = u.hdr.e_type == Elf_et_exec ? (caddr_t) base_vaddr : NULL;
#else
base_addr = NULL;
base_addr = NULL;
#endif
mapbase = mmap(base_addr, mapsize, protflags(segs[0]->p_flags),
MAP_FILE|MAP_PRIVATE, fd, base_offset);
if (mapbase == (caddr_t) -1) {
_rtld_error("mmap of entire address space failed: %s", xstrerror(errno));
return NULL;
}
if (base_addr != NULL && mapbase != base_addr) {
_rtld_error("mmap returned wrong address: wanted %p, got %p", base_addr,
mapbase);
munmap(mapbase, mapsize);
return NULL;
}
/* Overlay the data segment onto the proper region. */
data_offset = round_down(segs[1]->p_offset);
data_vaddr = round_down(segs[1]->p_vaddr);
data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);
data_addr = mapbase + (data_vaddr - base_vaddr);
if (mmap(data_addr, data_vlimit - data_vaddr, protflags(segs[1]->p_flags),
MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, data_offset) == (caddr_t) -1) {
_rtld_error("mmap of data failed: %s", xstrerror(errno));
return NULL;
}
#ifdef RTLD_LOADER
/* Clear any BSS in the last page of the data segment. */
clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz;
clear_addr = mapbase + (clear_vaddr - base_vaddr);
if ((nclear = data_vlimit - clear_vaddr) > 0)
memset(clear_addr, 0, nclear);
/* Overlay the BSS segment onto the proper region. */
bss_vaddr = data_vlimit;
bss_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
bss_addr = mapbase + (bss_vaddr - base_vaddr);
if (bss_vlimit > bss_vaddr) { /* There is something to do */
if (mmap(bss_addr, bss_vlimit - bss_vaddr, protflags(segs[1]->p_flags),
MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0) == (caddr_t) -1) {
_rtld_error("mmap of bss failed: %s", xstrerror(errno));
return NULL;
mapbase = mmap(base_addr, mapsize, protflags(segs[0]->p_flags),
MAP_FILE | MAP_PRIVATE, fd, base_offset);
if (mapbase == (caddr_t) - 1) {
_rtld_error("mmap of entire address space failed: %s",
xstrerror(errno));
return NULL;
}
if (base_addr != NULL && mapbase != base_addr) {
_rtld_error("mmap returned wrong address: wanted %p, got %p", base_addr,
mapbase);
munmap(mapbase, mapsize);
return NULL;
}
/* Overlay the data segment onto the proper region. */
data_offset = round_down(segs[1]->p_offset);
data_vaddr = round_down(segs[1]->p_vaddr);
data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);
data_addr = mapbase + (data_vaddr - base_vaddr);
if (mmap(data_addr, data_vlimit - data_vaddr,
protflags(segs[1]->p_flags), MAP_FILE | MAP_PRIVATE | MAP_FIXED,
fd, data_offset) == (caddr_t)-1) {
_rtld_error("mmap of data failed: %s", xstrerror(errno));
return NULL;
}
#ifdef RTLD_LOADER
/* Clear any BSS in the last page of the data segment. */
clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz;
clear_addr = mapbase + (clear_vaddr - base_vaddr);
if ((nclear = data_vlimit - clear_vaddr) > 0)
memset(clear_addr, 0, nclear);
/* Overlay the BSS segment onto the proper region. */
bss_vaddr = data_vlimit;
bss_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
bss_addr = mapbase + (bss_vaddr - base_vaddr);
if (bss_vlimit > bss_vaddr) { /* There is something to do */
if (mmap(bss_addr, bss_vlimit - bss_vaddr,
protflags(segs[1]->p_flags),
MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1,
0) == (caddr_t)-1) {
_rtld_error("mmap of bss failed: %s", xstrerror(errno));
return NULL;
}
}
}
#endif
obj = CNEW(Obj_Entry);
obj->mapbase = mapbase;
obj->mapsize = mapsize;
obj->textsize = round_up(segs[0]->p_vaddr + segs[0]->p_memsz) - base_vaddr;
obj->vaddrbase = base_vaddr;
obj->relocbase = mapbase - base_vaddr;
obj->dynamic = (Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr);
if (u.hdr.e_entry != 0)
obj->entry = (caddr_t) (obj->relocbase + u.hdr.e_entry);
if (phphdr != NULL) {
obj->phdr = (const Elf_Phdr *) (obj->relocbase + phphdr->p_vaddr);
obj->phsize = phphdr->p_memsz;
}
return obj;
obj = CNEW(Obj_Entry);
obj->mapbase = mapbase;
obj->mapsize = mapsize;
obj->textsize = round_up(segs[0]->p_vaddr + segs[0]->p_memsz) -
base_vaddr;
obj->vaddrbase = base_vaddr;
obj->relocbase = mapbase - base_vaddr;
obj->dynamic = (Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr);
if (u.hdr.e_entry != 0)
obj->entry = (caddr_t)(obj->relocbase + u.hdr.e_entry);
if (phphdr != NULL) {
obj->phdr = (const Elf_Phdr *)
(obj->relocbase + phphdr->p_vaddr);
obj->phsize = phphdr->p_memsz;
}
return obj;
}
/*
@ -259,13 +259,17 @@ _rtld_map_object(
* flags for MMAP.
*/
static int
protflags(int elfflags)
protflags(elfflags)
int elfflags;
{
int prot = 0;
if (elfflags & Elf_pf_r) prot |= PROT_READ;
int prot = 0;
if (elfflags & Elf_pf_r)
prot |= PROT_READ;
#ifdef RTLD_LOADER
if (elfflags & Elf_pf_w) prot |= PROT_WRITE;
if (elfflags & Elf_pf_w)
prot |= PROT_WRITE;
#endif
if (elfflags & Elf_pf_x) prot |= PROT_EXEC;
return prot;
if (elfflags & Elf_pf_x)
prot |= PROT_EXEC;
return prot;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: paths.c,v 1.3 1999/02/24 18:31:00 christos Exp $ */
/* $NetBSD: paths.c,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@ -43,68 +43,66 @@
#include "debug.h"
#include "rtld.h"
Search_Path *_rtld_find_path(Search_Path *, const char *, size_t);
static Search_Path *_rtld_find_path __P((Search_Path *, const char *, size_t));
Search_Path *
_rtld_find_path(
Search_Path *path,
const char *pathstr,
size_t pathlen)
static Search_Path *
_rtld_find_path(path, pathstr, pathlen)
Search_Path *path;
const char *pathstr;
size_t pathlen;
{
for (; path != NULL; path = path->sp_next) {
if (pathlen == path->sp_pathlen
&& memcmp(path->sp_path, pathstr, pathlen) == 0)
return path;
}
return NULL;
for (; path != NULL; path = path->sp_next) {
if (pathlen == path->sp_pathlen &&
memcmp(path->sp_path, pathstr, pathlen) == 0)
return path;
}
return NULL;
}
void
_rtld_add_paths(
Search_Path **path_p,
const char *pathstr,
bool dodebug)
_rtld_add_paths(path_p, pathstr, dodebug)
Search_Path ** path_p;
const char *pathstr;
bool dodebug;
{
Search_Path *path, **head_p = path_p;
Search_Path *path, **head_p = path_p;
if (pathstr == NULL)
return;
if (pathstr == NULL)
return;
if (pathstr[0] == ':') {
/*
* Leading colon means append to current path
*/
while ((*path_p) != NULL)
path_p = &(*path_p)->sp_next;
pathstr++;
}
for (;;) {
const char *bp = pathstr;
const char *ep = strchr(bp, ':');
if (ep == NULL)
ep = &pathstr[strlen(pathstr)];
if (bp < ep && (path = _rtld_find_path(*head_p, bp, ep - bp)) == NULL) {
char *cp;
path = CNEW(Search_Path);
path->sp_pathlen = ep - bp;
cp = xmalloc(path->sp_pathlen + 1);
strncpy(cp, bp, path->sp_pathlen);
cp[path->sp_pathlen] = '\0';
path->sp_path = cp;
path->sp_next = (*path_p);
(*path_p) = path;
path_p = &path->sp_next;
if (dodebug)
dbg(" added path \"%s\"", path->sp_path);
if (pathstr[0] == ':') {
/*
* Leading colon means append to current path
*/
while ((*path_p) != NULL)
path_p = &(*path_p)->sp_next;
pathstr++;
}
for (;;) {
const char *bp = pathstr;
const char *ep = strchr(bp, ':');
if (ep == NULL)
ep = &pathstr[strlen(pathstr)];
if (ep[0] == '\0')
break;
pathstr = ep + 1;
}
if (bp < ep &&
(path = _rtld_find_path(*head_p, bp, ep - bp)) == NULL) {
char *cp;
path = CNEW(Search_Path);
path->sp_pathlen = ep - bp;
cp = xmalloc(path->sp_pathlen + 1);
strncpy(cp, bp, path->sp_pathlen);
cp[path->sp_pathlen] = '\0';
path->sp_path = cp;
path->sp_next = (*path_p);
(*path_p) = path;
path_p = &path->sp_next;
if (dodebug)
dbg((" added path \"%s\"", path->sp_path));
}
if (ep[0] == '\0')
break;
pathstr = ep + 1;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: reloc.c,v 1.15 1999/02/27 21:38:04 scottr Exp $ */
/* $NetBSD: reloc.c,v 1.16 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -53,6 +53,9 @@
#include "rtld.h"
#ifndef RTLD_INHIBIT_COPY_RELOCS
static int _rtld_do_copy_relocation __P((const Obj_Entry *, const Elf_RelA *,
bool));
/*
* XXX: These don't work for the alpha and i386; don't know about powerpc
* The alpha and the i386 avoid the problem by compiling everything PIC.
@ -63,10 +66,10 @@
* not an indirect call.
*/
static int
_rtld_do_copy_relocation(
const Obj_Entry *dstobj,
const Elf_RelA *rela,
bool dodebug)
_rtld_do_copy_relocation(dstobj, rela, dodebug)
const Obj_Entry *dstobj;
const Elf_RelA *rela;
bool dodebug;
{
void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
@ -89,9 +92,9 @@ _rtld_do_copy_relocation(
}
srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value);
(void)memcpy(dstaddr, srcaddr, size);
rdbg(dodebug, "COPY %s %s %s --> src=%p dst=%p *dst= %p size %d",
rdbg(dodebug, ("COPY %s %s %s --> src=%p dst=%p *dst= %p size %d",
dstobj->path, srcobj->path, name, (void *)srcaddr,
(void *)dstaddr, (void *)*(long *)dstaddr, size);
(void *)dstaddr, (void *)*(long *)dstaddr, size));
return (0);
}
#endif /* RTLD_INHIBIT_COPY_RELOCS */
@ -105,9 +108,9 @@ _rtld_do_copy_relocation(
* Returns 0 on success, -1 on failure.
*/
int
_rtld_do_copy_relocations(
const Obj_Entry *dstobj,
bool dodebug)
_rtld_do_copy_relocations(dstobj, dodebug)
const Obj_Entry *dstobj;
bool dodebug;
{
#ifndef RTLD_INHIBIT_COPY_RELOCS
@ -146,10 +149,10 @@ _rtld_do_copy_relocations(
#ifndef __sparc__
int
_rtld_relocate_nonplt_object(
const Obj_Entry * obj,
const Elf_RelA * rela,
bool dodebug)
_rtld_relocate_nonplt_object(obj, rela, dodebug)
const Obj_Entry *obj;
const Elf_RelA *rela;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Sym *def;
@ -176,9 +179,9 @@ _rtld_relocate_nonplt_object(
tmp = (Elf_Addr)(defobj->relocbase + def->st_value);
if (*where != tmp)
*where = tmp;
rdbg(dodebug, "GOT32 %s in %s --> %p in %s",
rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
case R_TYPE(PC32):
@ -195,9 +198,9 @@ _rtld_relocate_nonplt_object(
*where += (Elf_Addr)(defobj->relocbase + def->st_value) -
(Elf_Addr)where;
rdbg(dodebug, "PC32 %s in %s --> %p in %s",
rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
case R_TYPE(32):
@ -207,9 +210,9 @@ _rtld_relocate_nonplt_object(
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, "32 %s in %s --> %p in %s",
rdbg(dodebug, ("32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
#endif /* __i386__ */
@ -224,9 +227,9 @@ _rtld_relocate_nonplt_object(
*where + rela->r_addend;
if (*where != tmp)
*where = tmp;
rdbg(dodebug, "REFQUAD %s in %s --> %p in %s",
rdbg(dodebug, ("REFQUAD %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
#endif /* __alpha__ */
@ -239,21 +242,21 @@ _rtld_relocate_nonplt_object(
if (*where != (Elf_Addr)(defobj->relocbase + def->st_value))
*where = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, "GLOB_DAT %s in %s --> %p in %s",
rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE):
if ((caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
(caddr_t)where >= (caddr_t)&_DYNAMIC) {
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, "RELATIVE in %s --> %p", obj->path,
(void *)*where);
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
}
else
rdbg(dodebug, "RELATIVE in %s stays at %p",
obj->path, (void *)*where);
rdbg(dodebug, ("RELATIVE in %s stays at %p",
obj->path, (void *)*where));
break;
case R_TYPE(COPY):
@ -269,7 +272,7 @@ _rtld_relocate_nonplt_object(
obj->path);
return -1;
}
rdbg(dodebug, "COPY (avoid in main)");
rdbg(dodebug, ("COPY (avoid in main)"));
break;
#endif /* __i386__ || __alpha__ */
@ -282,8 +285,8 @@ _rtld_relocate_nonplt_object(
(ELF_SYM_TYPE(def->st_info) == Elf_estt_section ||
ELF_SYM_TYPE(def->st_info) == Elf_estt_notype)) {
*where += (Elf_Addr)obj->relocbase;
rdbg(dodebug, "REL32 in %s --> %p", obj->path,
(void *)*where);
rdbg(dodebug, ("REL32 in %s --> %p", obj->path,
(void *)*where));
} else {
/* XXX maybe do something re: bootstrapping? */
def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
@ -291,9 +294,9 @@ _rtld_relocate_nonplt_object(
if (def == NULL)
return -1;
*where += (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, "REL32 %s in %s --> %p in %s",
rdbg(dodebug, ("REL32 %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
}
break;
@ -312,17 +315,17 @@ _rtld_relocate_nonplt_object(
if (*where != tmp)
*where = tmp;
rdbg(dodebug, "32/GLOB_DAT %s in %s --> %p in %s",
rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
defobj->strtab + def->st_name, obj->path,
(void *)*where, defobj->path);
(void *)*where, defobj->path));
break;
case R_TYPE(COPY):
rdbg(dodebug, "COPY");
rdbg(dodebug, ("COPY"));
break;
case R_TYPE(JMP_SLOT):
rdbg(dodebug, "JMP_SLOT");
rdbg(dodebug, ("JMP_SLOT"));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
@ -331,21 +334,21 @@ _rtld_relocate_nonplt_object(
break; /* GOT - already done */
*where = tmp;
rdbg(dodebug, "RELATIVE in %s --> %p", obj->path,
(void *)*where);
rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
(void *)*where));
break;
#endif /* __powerpc__ */
default:
def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
&defobj, true);
rdbg(dodebug, "sym = %lu, type = %lu, offset = %p, "
rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)ELF_R_SYM(rela->r_info),
(u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
def ? defobj->strtab + def->st_name : "??");
def ? defobj->strtab + def->st_name : "??"));
_rtld_error("%s: Unsupported relocation type %d"
"in non-PLT relocations\n",
obj->path, ELF_R_TYPE(rela->r_info));
@ -357,15 +360,15 @@ _rtld_relocate_nonplt_object(
int
_rtld_relocate_plt_object(
const Obj_Entry * obj,
const Elf_RelA * rela,
caddr_t *addrp,
bool bind_now,
bool dodebug)
_rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
const Obj_Entry *obj;
const Elf_RelA *rela;
caddr_t *addrp;
bool bind_now;
bool dodebug;
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
Elf_Addr new_value;
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
Elf_Addr new_value;
/* Fully resolve procedure addresses now */
@ -386,17 +389,17 @@ _rtld_relocate_plt_object(
return -1;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(dodebug, "bind now %d/fixup in %s --> old=%p new=%p",
rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
(int)bind_now,
defobj->strtab + def->st_name,
(void *)*where, (void *)new_value);
(void *)*where, (void *)new_value));
} else
#endif /* __alpha__ || __i386__ */
if (!obj->mainprog) {
/* Just relocate the GOT slots pointing into the PLT */
new_value = *where + (Elf_Addr)(obj->relocbase);
rdbg(dodebug, "fixup !main in %s --> %p", obj->path,
(void *)*where);
rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
(void *)*where));
} else {
return 0;
}
@ -413,9 +416,9 @@ _rtld_relocate_plt_object(
#endif /* __sparc__ */
caddr_t
_rtld_bind(
const Obj_Entry *obj,
Elf_Word reloff)
_rtld_bind(obj, reloff)
const Obj_Entry *obj;
Elf_Word reloff;
{
const Elf_RelA *rela;
Elf_RelA ourrela;
@ -445,29 +448,29 @@ _rtld_bind(
* or -1 on failure.
*/
int
_rtld_relocate_objects(
Obj_Entry * first,
bool bind_now,
bool dodebug)
_rtld_relocate_objects(first, bind_now, dodebug)
Obj_Entry *first;
bool bind_now;
bool dodebug;
{
Obj_Entry *obj;
int ok = 1;
Obj_Entry *obj;
int ok = 1;
for (obj = first; obj != NULL; obj = obj->next) {
if (obj->nbuckets == 0 || obj->nchains == 0
|| obj->buckets == NULL || obj->symtab == NULL
|| obj->strtab == NULL) {
if (obj->nbuckets == 0 || obj->nchains == 0 ||
obj->buckets == NULL || obj->symtab == NULL ||
obj->strtab == NULL) {
_rtld_error("%s: Shared object has no run-time"
" symbol table", obj->path);
return -1;
}
rdbg(dodebug, " relocating %s (%ld/%ld rel/rela, "
rdbg(dodebug, (" relocating %s (%ld/%ld rel/rela, "
"%ld/%ld plt rel/rela)",
obj->path,
(long)(obj->rellim - obj->rel),
(long)(obj->relalim - obj->rela),
(long)(obj->pltrellim - obj->pltrel),
(long)(obj->pltrelalim - obj->pltrela));
(long)(obj->pltrelalim - obj->pltrela)));
if (obj->textrel) {
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.c,v 1.14 1999/02/27 10:35:16 pk Exp $ */
/* $NetBSD: rtld.c,v 1.15 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -61,55 +61,63 @@
* Debugging support.
*/
typedef void (*funcptr)(void);
typedef void (*funcptr) __P((void));
/*
* Function declarations.
*/
static void _rtld_init(caddr_t);
static void _rtld_exit(void);
static void _rtld_init __P((caddr_t));
static void _rtld_exit __P((void));
Elf_Addr _rtld __P((Elf_Word *));
/*
* Data declarations.
*/
static char *error_message; /* Message for dlopen(), or NULL */
static char *error_message; /* Message for dlopen(), or NULL */
struct r_debug _rtld_debug; /* for GDB; */
bool _rtld_trust; /* False for setuid and setgid programs */
Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
Obj_Entry **_rtld_objtail; /* Link field of last object in list */
Obj_Entry *_rtld_objmain; /* The main program shared object */
Obj_Entry _rtld_objself; /* The dynamic linker shared object */
char _rtld_path[] = _PATH_RTLD;
struct r_debug _rtld_debug; /* for GDB; */
bool _rtld_trust; /* False for setuid and setgid programs */
Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
Obj_Entry **_rtld_objtail; /* Link field of last object in list */
Obj_Entry *_rtld_objmain; /* The main program shared object */
Obj_Entry _rtld_objself; /* The dynamic linker shared object */
char _rtld_path[] = _PATH_RTLD;
Search_Path *_rtld_paths;
Search_Path *_rtld_paths;
/*
* Global declarations normally provided by crt0.
*/
char *__progname;
char **environ;
char *__progname;
char **environ;
#ifdef OLD_GOT
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
#else
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Dyn _DYNAMIC;
extern Elf_Dyn _DYNAMIC;
#endif
static void _rtld_call_fini_functions __P((Obj_Entry *));
static void _rtld_call_init_functions __P((Obj_Entry *));
static Obj_Entry *_rtld_dlcheck __P((void *));
static void _rtld_unref_object_dag __P((Obj_Entry *));
static void
_rtld_call_fini_functions(
Obj_Entry *first)
_rtld_call_fini_functions(first)
Obj_Entry *first;
{
Obj_Entry *obj;
for (obj = first; obj != NULL; obj = obj->next)
for (obj = first; obj != NULL; obj = obj->next)
if (obj->fini != NULL)
(*obj->fini)();
}
static void
_rtld_call_init_functions(
Obj_Entry *first)
_rtld_call_init_functions(first)
Obj_Entry *first;
{
if (first != NULL) {
_rtld_call_init_functions(first->next);
@ -124,10 +132,10 @@ _rtld_call_init_functions(
* this function is to relocate the dynamic linker.
*/
static void
_rtld_init(
caddr_t mapbase)
_rtld_init(mapbase)
caddr_t mapbase;
{
Obj_Entry objself; /* The dynamic linker shared object */
Obj_Entry objself;/* The dynamic linker shared object */
#ifdef RTLD_RELOCATE_SELF
int dodebug = false;
#else
@ -154,16 +162,16 @@ _rtld_init(
objself.pltgot = NULL;
#ifdef OLD_GOT
objself.dynamic = (Elf_Dyn *)_GLOBAL_OFFSET_TABLE_[0];
objself.dynamic = (Elf_Dyn *) _GLOBAL_OFFSET_TABLE_[0];
#else
objself.dynamic = (Elf_Dyn *)&_DYNAMIC;
objself.dynamic = (Elf_Dyn *) & _DYNAMIC;
#endif
#ifdef RTLD_RELOCATE_SELF
/* We have not been relocated yet, so fix the dynamic address */
objself.dynamic = (Elf_Dyn *)
((u_long)mapbase + (char *) objself.dynamic);
#endif /* RTLD_RELOCATE_SELF */
((u_long) mapbase + (char *) objself.dynamic);
#endif /* RTLD_RELOCATE_SELF */
_rtld_digest_dynamic(&objself);
@ -206,9 +214,9 @@ _rtld_init(
* before the process exits.
*/
static void
_rtld_exit(void)
_rtld_exit()
{
dbg("rtld_exit()");
dbg(("rtld_exit()"));
_rtld_call_fini_functions(_rtld_objlist->next);
}
@ -229,336 +237,339 @@ _rtld_exit(void)
* Such values are returned with their most-significant 32 bits in %edx,
* and their least-significant 32 bits in %eax.
*/
Elf_Addr _rtld(Elf_Word *);
Elf_Addr
_rtld(
Elf_Word *sp)
_rtld(sp)
Elf_Word *sp;
{
const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd,
*pAUX_phdr, *pAUX_phent, *pAUX_phnum;
char **env;
const AuxInfo *aux;
const AuxInfo *auxp;
Elf_Word * const osp = sp;
bool bind_now = 0;
const char *ld_bind_now;
const char **argv;
const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
*pAUX_phent, *pAUX_phnum;
char **env;
const AuxInfo *aux;
const AuxInfo *auxp;
Elf_Word *const osp = sp;
bool bind_now = 0;
const char *ld_bind_now;
const char **argv;
#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
int i = 0;
int i = 0;
#endif
/*
* On entry, the dynamic linker itself has not been relocated yet.
* Be very careful not to reference any global data until after
* _rtld_init has returned. It is OK to reference file-scope statics
* and string constants, and to call static and global functions.
*/
/* Find the auxiliary vector on the stack. */
/* first Elf_Word reserved to address of exit routine */
/*
* On entry, the dynamic linker itself has not been relocated yet.
* Be very careful not to reference any global data until after
* _rtld_init has returned. It is OK to reference file-scope statics
* and string constants, and to call static and global functions.
*/
/* Find the auxiliary vector on the stack. */
/* first Elf_Word reserved to address of exit routine */
#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
dbg("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2],
&sp[3], (char *)sp[3]);
dbg("got is at %p, dynamic is at %p\n", _GLOBAL_OFFSET_TABLE_, &_DYNAMIC);
debug = 1;
dbg("_ctype_ is %p\n", _ctype_);
dbg(("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2],
&sp[3], (char *) sp[3]));
dbg(("got is at %p, dynamic is at %p\n",
_GLOBAL_OFFSET_TABLE_, &_DYNAMIC));
debug = 1;
dbg(("_ctype_ is %p\n", _ctype_));
#endif
sp += 2; /* skip over return argument space */
argv = (const char **) &sp[1];
sp += sp[0] + 2; /* Skip over argc, arguments, and NULL terminator */
env = (char **) sp;
while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
sp += 2; /* skip over return argument space */
argv = (const char **) &sp[1];
sp += sp[0] + 2; /* Skip over argc, arguments, and NULL
* terminator */
env = (char **) sp;
while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
dbg("env[%d] = %p %s\n", i++, (void *)sp[-1], (char *)sp[-1]);
dbg(("env[%d] = %p %s\n", i++, (void *)sp[-1], (char *)sp[-1]));
#endif
}
aux = (const AuxInfo *) sp;
/* Digest the auxiliary vector. */
pAUX_base = pAUX_entry = pAUX_execfd =
pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
for (auxp = aux; auxp->au_id != AUX_null; ++auxp) {
switch(auxp->au_id) {
case AUX_base:
pAUX_base = auxp; break;
case AUX_entry:
pAUX_entry = auxp; break;
case AUX_execfd:
pAUX_execfd = auxp; break;
case AUX_phdr:
pAUX_phdr = auxp; break;
case AUX_phent:
pAUX_phent = auxp; break;
case AUX_phnum:
pAUX_phnum = auxp; break;
}
}
aux = (const AuxInfo *) sp;
/* Initialize and relocate ourselves. */
assert(pAUX_base != NULL);
_rtld_init((caddr_t) pAUX_base->au_v);
/* Digest the auxiliary vector. */
pAUX_base = pAUX_entry = pAUX_execfd = NULL;
pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
for (auxp = aux; auxp->au_id != AUX_null; ++auxp) {
switch (auxp->au_id) {
case AUX_base:
pAUX_base = auxp;
break;
case AUX_entry:
pAUX_entry = auxp;
break;
case AUX_execfd:
pAUX_execfd = auxp;
break;
case AUX_phdr:
pAUX_phdr = auxp;
break;
case AUX_phent:
pAUX_phent = auxp;
break;
case AUX_phnum:
pAUX_phnum = auxp;
break;
}
}
/* Initialize and relocate ourselves. */
assert(pAUX_base != NULL);
_rtld_init((caddr_t) pAUX_base->au_v);
#ifdef RTLD_DEBUG
dbg("_ctype_ is %p\n", _ctype_);
dbg(("_ctype_ is %p\n", _ctype_));
#endif
__progname = _rtld_objself.path;
environ = env;
__progname = _rtld_objself.path;
environ = env;
_rtld_trust = geteuid() == getuid() && getegid() == getgid();
_rtld_trust = geteuid() == getuid() && getegid() == getgid();
ld_bind_now = getenv("LD_BIND_NOW");
if (ld_bind_now != NULL && *ld_bind_now != '\0')
bind_now = true;
if (_rtld_trust) {
ld_bind_now = getenv("LD_BIND_NOW");
if (ld_bind_now != NULL && *ld_bind_now != '\0')
bind_now = true;
if (_rtld_trust) {
#ifdef DEBUG
const char *ld_debug = getenv("LD_DEBUG");
if (ld_debug != NULL && *ld_debug != '\0')
debug = 1;
const char *ld_debug = getenv("LD_DEBUG");
if (ld_debug != NULL && *ld_debug != '\0')
debug = 1;
#endif
_rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"), true);
}
_rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"), true);
}
dbg(("%s is initialized, base address = %p", __progname,
(void *) pAUX_base->au_v));
dbg("%s is initialized, base address = %p", __progname,
(void *)pAUX_base->au_v);
/*
* Load the main program, or process its program header if it is
* already loaded.
*/
if (pAUX_execfd != NULL) { /* Load the main program. */
int fd = pAUX_execfd->au_v;
dbg(("loading main program"));
_rtld_objmain = _rtld_map_object(argv[0], fd);
close(fd);
if (_rtld_objmain == NULL)
_rtld_die();
} else { /* Main program already loaded. */
const Elf_Phdr *phdr;
int phnum;
caddr_t entry;
/*
* Load the main program, or process its program header if it is
* already loaded.
*/
if (pAUX_execfd != NULL) { /* Load the main program. */
int fd = pAUX_execfd->au_v;
dbg("loading main program");
_rtld_objmain = _rtld_map_object(argv[0], fd);
close(fd);
if (_rtld_objmain == NULL)
_rtld_die();
} else { /* Main program already loaded. */
const Elf_Phdr *phdr;
int phnum;
caddr_t entry;
dbg(("processing main program's program header"));
assert(pAUX_phdr != NULL);
phdr = (const Elf_Phdr *) pAUX_phdr->au_v;
assert(pAUX_phnum != NULL);
phnum = pAUX_phnum->au_v;
assert(pAUX_phent != NULL);
assert(pAUX_phent->au_v == sizeof(Elf_Phdr));
assert(pAUX_entry != NULL);
entry = (caddr_t) pAUX_entry->au_v;
_rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
}
dbg("processing main program's program header");
assert(pAUX_phdr != NULL);
phdr = (const Elf_Phdr *) pAUX_phdr->au_v;
assert(pAUX_phnum != NULL);
phnum = pAUX_phnum->au_v;
assert(pAUX_phent != NULL);
assert(pAUX_phent->au_v == sizeof(Elf_Phdr));
assert(pAUX_entry != NULL);
entry = (caddr_t) pAUX_entry->au_v;
_rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
}
_rtld_objmain->path = xstrdup("main program");
_rtld_objmain->mainprog = true;
_rtld_digest_dynamic(_rtld_objmain);
_rtld_objmain->path = xstrdup("main program");
_rtld_objmain->mainprog = true;
_rtld_digest_dynamic(_rtld_objmain);
_rtld_linkmap_add(_rtld_objmain);
_rtld_linkmap_add(&_rtld_objself);
_rtld_linkmap_add(_rtld_objmain);
_rtld_linkmap_add(&_rtld_objself);
/* Link the main program into the list of objects. */
*_rtld_objtail = _rtld_objmain;
_rtld_objtail = &_rtld_objmain->next;
++_rtld_objmain->refcount;
/* Link the main program into the list of objects. */
*_rtld_objtail = _rtld_objmain;
_rtld_objtail = &_rtld_objmain->next;
++_rtld_objmain->refcount;
dbg(("loading needed objects"));
if (_rtld_load_needed_objects(_rtld_objmain) == -1)
_rtld_die();
dbg("loading needed objects");
if (_rtld_load_needed_objects(_rtld_objmain) == -1)
_rtld_die();
dbg(("relocating objects"));
if (_rtld_relocate_objects(_rtld_objmain, bind_now, true) == -1)
_rtld_die();
dbg("relocating objects");
if (_rtld_relocate_objects(_rtld_objmain, bind_now, true) == -1)
_rtld_die();
dbg(("doing copy relocations"));
if (_rtld_do_copy_relocations(_rtld_objmain, true) == -1)
_rtld_die();
dbg("doing copy relocations");
if (_rtld_do_copy_relocations(_rtld_objmain, true) == -1)
_rtld_die();
dbg(("calling _init functions"));
_rtld_call_init_functions(_rtld_objmain->next);
dbg("calling _init functions");
_rtld_call_init_functions(_rtld_objmain->next);
dbg(("control at program entry point = %p, obj = %p, exit = %p",
_rtld_objmain->entry, _rtld_objmain, _rtld_exit));
dbg("control at program entry point = %p, obj = %p, exit = %p",
_rtld_objmain->entry, _rtld_objmain, _rtld_exit);
/*
* Return with the entry point and the exit procedure in at the top
* of stack.
*/
/* Return with the entry point and the exit procedure in at the top of
* stack.
*/
_rtld_debug_state(); /* say hello to gdb! */
_rtld_debug_state(); /* say hello to gdb! */
((void **) osp)[0] = _rtld_exit;
((void **) osp)[1] = _rtld_objmain;
return (Elf_Addr) _rtld_objmain->entry;
((void **) osp)[0] = _rtld_exit;
((void **) osp)[1] = _rtld_objmain;
return (Elf_Addr) _rtld_objmain->entry;
}
void
_rtld_die(
void)
_rtld_die()
{
const char *msg = _rtld_dlerror();
const char *msg = _rtld_dlerror();
if (msg == NULL)
msg = "Fatal error";
xerrx(1, "%s\n", msg);
if (msg == NULL)
msg = "Fatal error";
xerrx(1, "%s\n", msg);
}
static Obj_Entry *
_rtld_dlcheck(
void *handle)
_rtld_dlcheck(handle)
void *handle;
{
Obj_Entry *obj;
Obj_Entry *obj;
for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
if (obj == (Obj_Entry *) handle)
break;
for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
if (obj == (Obj_Entry *) handle)
break;
if (obj == NULL || obj->dl_refcount == 0) {
xwarnx("Invalid shared object handle %p", handle);
return NULL;
}
return obj;
if (obj == NULL || obj->dl_refcount == 0) {
xwarnx("Invalid shared object handle %p", handle);
return NULL;
}
return obj;
}
static void
_rtld_unref_object_dag(
Obj_Entry *root)
_rtld_unref_object_dag(root)
Obj_Entry *root;
{
assert(root->refcount != 0);
--root->refcount;
if (root->refcount == 0) {
const Needed_Entry *needed;
assert(root->refcount != 0);
--root->refcount;
if (root->refcount == 0) {
const Needed_Entry *needed;
for (needed = root->needed; needed != NULL; needed = needed->next)
_rtld_unref_object_dag(needed->obj);
}
for (needed = root->needed; needed != NULL;
needed = needed->next)
_rtld_unref_object_dag(needed->obj);
}
}
int
_rtld_dlclose(
void *handle)
_rtld_dlclose(handle)
void *handle;
{
Obj_Entry *root = _rtld_dlcheck(handle);
Obj_Entry *root = _rtld_dlcheck(handle);
if (root == NULL)
return -1;
if (root == NULL)
return -1;
_rtld_debug.r_state = RT_DELETE;
_rtld_debug_state();
_rtld_debug.r_state = RT_DELETE;
_rtld_debug_state();
--root->dl_refcount;
_rtld_unref_object_dag(root);
if (root->refcount == 0) { /* We are finished with some objects. */
Obj_Entry *obj;
Obj_Entry **linkp;
--root->dl_refcount;
_rtld_unref_object_dag(root);
if (root->refcount == 0) { /* We are finished with some objects. */
Obj_Entry *obj;
Obj_Entry **linkp;
/* Finalize objects that are about to be unmapped. */
for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
if (obj->refcount == 0 && obj->fini != NULL)
(*obj->fini)();
/* Finalize objects that are about to be unmapped. */
for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
if (obj->refcount == 0 && obj->fini != NULL)
(*obj->fini) ();
/* Unmap all objects that are no longer referenced. */
linkp = &_rtld_objlist->next;
while((obj = *linkp) != NULL) {
if (obj->refcount == 0) {
munmap(obj->mapbase, obj->mapsize);
free(obj->path);
while(obj->needed != NULL) {
Needed_Entry *needed = obj->needed;
obj->needed = needed->next;
free(needed);
/* Unmap all objects that are no longer referenced. */
linkp = &_rtld_objlist->next;
while ((obj = *linkp) != NULL) {
if (obj->refcount == 0) {
munmap(obj->mapbase, obj->mapsize);
free(obj->path);
while (obj->needed != NULL) {
Needed_Entry *needed = obj->needed;
obj->needed = needed->next;
free(needed);
}
_rtld_linkmap_delete(obj);
*linkp = obj->next;
if (obj->next == NULL)
_rtld_objtail = linkp;
free(obj);
} else
linkp = &obj->next;
}
_rtld_linkmap_delete(obj);
*linkp = obj->next;
if (obj->next == NULL)
_rtld_objtail = linkp;
free(obj);
} else
linkp = &obj->next;
}
}
_rtld_debug.r_state = RT_CONSISTENT;
_rtld_debug_state();
_rtld_debug.r_state = RT_CONSISTENT;
_rtld_debug_state();
return 0;
return 0;
}
char *
_rtld_dlerror(
void)
_rtld_dlerror()
{
char *msg = error_message;
error_message = NULL;
return msg;
char *msg = error_message;
error_message = NULL;
return msg;
}
void *
_rtld_dlopen(
const char *name,
int mode)
_rtld_dlopen(name, mode)
const char *name;
int mode;
{
Obj_Entry **old_obj_tail = _rtld_objtail;
Obj_Entry *obj = NULL;
Obj_Entry **old_obj_tail = _rtld_objtail;
Obj_Entry *obj = NULL;
_rtld_debug.r_state = RT_ADD;
_rtld_debug_state();
_rtld_debug.r_state = RT_ADD;
_rtld_debug_state();
if (name == NULL) {
obj = _rtld_objmain;
} else {
char *path = _rtld_find_library(name, NULL);
if (path != NULL)
obj = _rtld_load_object(path, true);
}
if (obj != NULL) {
++obj->dl_refcount;
if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj);
/* FIXME - Clean up properly after an error. */
if (_rtld_load_needed_objects(obj) == -1) {
--obj->dl_refcount;
obj = NULL;
} else if (_rtld_relocate_objects(obj, (mode & 3) == RTLD_NOW,
true) == -1) {
--obj->dl_refcount;
obj = NULL;
} else {
_rtld_call_init_functions(obj);
}
if (name == NULL) {
obj = _rtld_objmain;
} else {
char *path = _rtld_find_library(name, NULL);
if (path != NULL)
obj = _rtld_load_object(path, true);
}
}
_rtld_debug.r_state = RT_CONSISTENT;
_rtld_debug_state();
if (obj != NULL) {
++obj->dl_refcount;
if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj);
return obj;
/* FIXME - Clean up properly after an error. */
if (_rtld_load_needed_objects(obj) == -1) {
--obj->dl_refcount;
obj = NULL;
} else if (_rtld_relocate_objects(obj,
(mode & 3) == RTLD_NOW, true) == -1) {
--obj->dl_refcount;
obj = NULL;
} else {
_rtld_call_init_functions(obj);
}
}
}
_rtld_debug.r_state = RT_CONSISTENT;
_rtld_debug_state();
return obj;
}
void *
_rtld_dlsym(
void *handle,
const char *name)
_rtld_dlsym(handle, name)
void *handle;
const char *name;
{
const Obj_Entry *obj = _rtld_dlcheck(handle);
const Elf_Sym *def;
const Obj_Entry *defobj;
const Obj_Entry *obj = _rtld_dlcheck(handle);
const Elf_Sym *def;
const Obj_Entry *defobj;
if (obj == NULL)
if (obj == NULL)
return NULL;
/*
* FIXME - This isn't correct. The search should include the whole
* DAG rooted at the given object.
*/
def = _rtld_find_symdef(_rtld_objlist, 0, name, obj, &defobj, false);
if (def != NULL)
return defobj->relocbase + def->st_value;
_rtld_error("Undefined symbol \"%s\"", name);
return NULL;
/*
* FIXME - This isn't correct. The search should include the whole
* DAG rooted at the given object.
*/
def = _rtld_find_symdef(_rtld_objlist, 0, name, obj, &defobj, false);
if (def != NULL)
return defobj->relocbase + def->st_value;
_rtld_error("Undefined symbol \"%s\"", name);
return NULL;
}
/*
@ -567,64 +578,70 @@ _rtld_dlsym(
* will return the message.
*/
void
_rtld_error(
const char *fmt, ...)
#ifdef __STDC__
_rtld_error(const char *fmt,...)
#else
_rtld_error(va_alist)
va_dcl
#endif
{
static char buf[512];
va_list ap;
static char buf[512];
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
const char *fmt;
va_start(ap, fmt);
xvsnprintf(buf, sizeof buf, fmt, ap);
error_message = buf;
va_end(ap);
va_start(ap);
fmt = va_arg(ap, const char *);
#endif
xvsnprintf(buf, sizeof buf, fmt, ap);
error_message = buf;
va_end(ap);
}
void
_rtld_debug_state(
void)
_rtld_debug_state()
{
/* do nothing */
/* do nothing */
}
void
_rtld_linkmap_add(
Obj_Entry *obj)
_rtld_linkmap_add(obj)
Obj_Entry *obj;
{
struct link_map *l = &obj->linkmap;
struct link_map *prev;
struct link_map *l = &obj->linkmap;
struct link_map *prev;
obj->linkmap.l_name = obj->path;
obj->linkmap.l_addr = obj->mapbase;
obj->linkmap.l_ld = obj->dynamic;
obj->linkmap.l_name = obj->path;
obj->linkmap.l_addr = obj->mapbase;
obj->linkmap.l_ld = obj->dynamic;
#ifdef __mips__
/* GDB needs load offset on MIPS to use the symbols */
obj->linkmap.l_offs = obj->relocbase;
/* GDB needs load offset on MIPS to use the symbols */
obj->linkmap.l_offs = obj->relocbase;
#endif
if (_rtld_debug.r_map == NULL) {
_rtld_debug.r_map = l;
return;
}
for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next)
;
l->l_prev = prev;
prev->l_next = l;
l->l_next = NULL;
if (_rtld_debug.r_map == NULL) {
_rtld_debug.r_map = l;
return;
}
for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
l->l_prev = prev;
prev->l_next = l;
l->l_next = NULL;
}
void
_rtld_linkmap_delete(
Obj_Entry *obj)
_rtld_linkmap_delete(obj)
Obj_Entry *obj;
{
struct link_map *l = &obj->linkmap;
struct link_map *l = &obj->linkmap;
if (l->l_prev == NULL) {
if ((_rtld_debug.r_map = l->l_next) != NULL)
l->l_next->l_prev = NULL;
return;
}
if ((l->l_prev->l_next = l->l_next) != NULL)
l->l_next->l_prev = l->l_prev;
if (l->l_prev == NULL) {
if ((_rtld_debug.r_map = l->l_next) != NULL)
l->l_next->l_prev = NULL;
return;
}
if ((l->l_prev->l_next = l->l_next) != NULL)
l->l_next->l_prev = l->l_prev;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.7 1999/02/24 18:31:00 christos Exp $ */
/* $NetBSD: rtld.h,v 1.8 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -31,8 +31,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RTLD_H /* { */
#define RTLD_H 1
#ifndef RTLD_H
#define RTLD_H
#include <stddef.h>
#include <sys/param.h>
@ -57,6 +57,7 @@
# define PAGESIZE 8192 /* NPBG is not constant! */
# endif
#endif
#define round_down(x) ((x) & ~(PAGESIZE-1))
#define round_up(x) round_down((x) + PAGESIZE - 1)
@ -74,16 +75,16 @@ typedef unsigned char bool;
struct Struct_Obj_Entry;
typedef struct Struct_Needed_Entry {
struct Struct_Needed_Entry *next;
struct Struct_Obj_Entry *obj;
unsigned long name; /* Offset of name in string table */
} Needed_Entry;
struct Struct_Needed_Entry *next;
struct Struct_Obj_Entry *obj;
unsigned long name; /* Offset of name in string table */
} Needed_Entry;
typedef struct _rtld_search_path_t {
struct _rtld_search_path_t *sp_next;
const char *sp_path;
size_t sp_pathlen;
} Search_Path;
struct _rtld_search_path_t *sp_next;
const char *sp_path;
size_t sp_pathlen;
} Search_Path;
/*
* Shared object descriptor.
@ -96,68 +97,72 @@ typedef struct _rtld_search_path_t {
#define RTLD_VERSION 1
typedef struct Struct_Obj_Entry {
Elf32_Word magic; /* Magic number (sanity check) */
Elf32_Word version; /* Version number of struct format */
Elf32_Word magic; /* Magic number (sanity check) */
Elf32_Word version; /* Version number of struct format */
struct Struct_Obj_Entry *next;
char *path; /* Pathname of underlying file (%) */
int refcount;
int dl_refcount; /* Number of times loaded by dlopen */
struct Struct_Obj_Entry *next;
char *path; /* Pathname of underlying file (%) */
int refcount;
int dl_refcount; /* Number of times loaded by dlopen */
/* These items are computed by map_object() or by digest_phdr(). */
caddr_t mapbase; /* Base address of mapped region */
size_t mapsize; /* Size of mapped region in bytes */
size_t textsize; /* Size of text segment in bytes */
Elf_Addr vaddrbase; /* Base address in shared object file */
caddr_t relocbase; /* Relocation constant = mapbase - vaddrbase */
Elf_Dyn *dynamic; /* Dynamic section */
caddr_t entry; /* Entry point */
const Elf_Phdr *phdr; /* Program header if it is mapped, else NULL */
size_t phsize; /* Size of program header in bytes */
/* These items are computed by map_object() or by digest_phdr(). */
caddr_t mapbase; /* Base address of mapped region */
size_t mapsize; /* Size of mapped region in bytes */
size_t textsize; /* Size of text segment in bytes */
Elf_Addr vaddrbase; /* Base address in shared object file */
caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */
Elf_Dyn *dynamic; /* Dynamic section */
caddr_t entry; /* Entry point */
const Elf_Phdr *phdr; /* Program header if mapped, ow NULL */
size_t phsize; /* Size of program header in bytes */
/* Items from the dynamic section. */
Elf_Addr *pltgot; /* PLTGOT table */
const Elf_Rel *rel; /* Relocation entries */
const Elf_Rel *rellim; /* Limit of Relocation entries */
const Elf_RelA *rela; /* Relocation entries */
const Elf_RelA *relalim; /* Limit of Relocation entries */
const Elf_Rel *pltrel; /* PLT relocation entries */
const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */
const Elf_RelA *pltrela; /* PLT relocation entries */
const Elf_RelA *pltrelalim; /* Limit of PLT relocation entries */
const Elf_Sym *symtab; /* Symbol table */
const char *strtab; /* String table */
unsigned long strsize; /* Size in bytes of string table */
/* Items from the dynamic section. */
Elf_Addr *pltgot; /* PLTGOT table */
const Elf_Rel *rel; /* Relocation entries */
const Elf_Rel *rellim; /* Limit of Relocation entries */
const Elf_RelA *rela; /* Relocation entries */
const Elf_RelA *relalim; /* Limit of Relocation entries */
const Elf_Rel *pltrel; /* PLT relocation entries */
const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */
const Elf_RelA *pltrela; /* PLT relocation entries */
const Elf_RelA *pltrelalim; /* Limit of PLT relocation entries */
const Elf_Sym *symtab; /* Symbol table */
const char *strtab; /* String table */
unsigned long strsize; /* Size in bytes of string table */
#if defined(__mips__)
Elf_Word local_gotno; /* Number of local GOT entries */
Elf_Word symtabno; /* Number of dynamic symbols */
Elf_Word gotsym; /* First dynamic symbol in GOT */
Elf_Word local_gotno; /* Number of local GOT entries */
Elf_Word symtabno; /* Number of dynamic symbols */
Elf_Word gotsym; /* First dynamic symbol in GOT */
#endif
const Elf_Word *buckets; /* Hash table buckets array */
unsigned long nbuckets; /* Number of buckets */
const Elf_Word *chains; /* Hash table chain array */
unsigned long nchains; /* Number of chains */
const Elf_Word *buckets; /* Hash table buckets array */
unsigned long nbuckets; /* Number of buckets */
const Elf_Word *chains; /* Hash table chain array */
unsigned long nchains; /* Number of chains */
Search_Path *rpaths; /* Search path specified in object */
Needed_Entry *needed; /* Shared objects needed by this one (%) */
Search_Path *rpaths; /* Search path specified in object */
Needed_Entry *needed; /* Shared objects needed by this (%) */
void (*init)(void); /* Initialization function to call */
void (*fini)(void); /* Termination function to call */
void (*init) /* Initialization function to call */
__P((void));
void (*fini) /* Termination function to call */
__P((void));
/* Entry points for dlopen() and friends. */
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
char *(*dlerror)(void);
int (*dlclose)(void *);
/* Entry points for dlopen() and friends. */
void *(*dlopen) __P((const char *, int));
void *(*dlsym) __P((void *, const char *));
char *(*dlerror) __P((void));
int (*dlclose) __P((void *));
int mainprog : 1; /* True if this is the main program */
int rtld : 1; /* True if this is the dynamic linker */
int textrel : 1; /* True if there are relocations to text seg */
int symbolic : 1; /* True if generated with "-Bsymbolic" */
int printed : 1; /* True if ldd has printed it */
int mainprog:1; /* True if this is the main program */
int rtld:1; /* True if this is the dynamic linker */
int textrel:1; /* True if there are relocations to
* text seg */
int symbolic:1; /* True if generated with
* "-Bsymbolic" */
int printed:1; /* True if ldd has printed it */
struct link_map linkmap; /* for GDB */
struct link_map linkmap; /* for GDB */
} Obj_Entry;
extern struct r_debug _rtld_debug;
@ -169,71 +174,63 @@ extern bool _rtld_trust;
extern const char *_rtld_error_message;
/* rtld_start.S */
extern void _rtld_bind_start(void);
void _rtld_bind_start __P((void));
/* rtld.c */
extern void _rtld_error(const char *, ...);
extern void _rtld_die(void);
extern char *_rtld_dlerror(void);
extern void *_rtld_dlopen(const char *, int);
extern void *_rtld_dlsym(void *, const char *);
extern int _rtld_dlclose(void *);
extern void _rtld_debug_state(void);
extern void _rtld_linkmap_add(Obj_Entry *);
extern void _rtld_linkmap_delete(Obj_Entry *);
void _rtld_error __P((const char *, ...));
void _rtld_die __P((void));
char *_rtld_dlerror __P((void));
void *_rtld_dlopen __P((const char *, int));
void *_rtld_dlsym __P((void *, const char *));
int _rtld_dlclose __P((void *));
void _rtld_debug_state __P((void));
void _rtld_linkmap_add __P((Obj_Entry *));
void _rtld_linkmap_delete __P((Obj_Entry *));
/* headers.c */
extern void _rtld_digest_dynamic(Obj_Entry *);
extern Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t);
void _rtld_digest_dynamic __P((Obj_Entry *));
Obj_Entry *_rtld_digest_phdr __P((const Elf_Phdr *, int, caddr_t));
/* load.c */
extern Obj_Entry *_rtld_load_object(char *path, bool);
extern int _rtld_load_needed_objects(Obj_Entry *);
Obj_Entry *_rtld_load_object __P((char *, bool));
int _rtld_load_needed_objects __P((Obj_Entry *));
/* path.c */
extern void _rtld_add_paths(Search_Path **, const char *, bool);
void _rtld_add_paths __P((Search_Path **, const char *, bool));
/* reloc.c */
extern int _rtld_do_copy_relocations(const Obj_Entry *, bool);
extern caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
extern int _rtld_relocate_objects(Obj_Entry *, bool, bool);
extern int _rtld_relocate_nonplt_object(const Obj_Entry *, const Elf_RelA *,
bool);
extern int _rtld_relocate_plt_object(const Obj_Entry *, const Elf_RelA *,
caddr_t *, bool, bool);
int _rtld_do_copy_relocations __P((const Obj_Entry *, bool));
caddr_t _rtld_bind __P((const Obj_Entry *, Elf_Word));
int _rtld_relocate_objects __P((Obj_Entry *, bool, bool));
int _rtld_relocate_nonplt_object __P((const Obj_Entry *,
const Elf_RelA *, bool));
int _rtld_relocate_plt_object __P((const Obj_Entry *, const Elf_RelA *,
caddr_t *, bool, bool));
/* search.c */
extern char *_rtld_find_library(const char *, const Obj_Entry *);
char *_rtld_find_library __P((const char *, const Obj_Entry *));
/* symbol.c */
extern unsigned long _rtld_elf_hash(const char *);
extern const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long,
const Obj_Entry *, bool);
extern const Elf_Sym *_rtld_find_symdef(const Obj_Entry *, Elf_Word,
const char *, const Obj_Entry *, const Obj_Entry **, bool);
unsigned long _rtld_elf_hash __P((const char *));
const Elf_Sym *_rtld_symlook_obj __P((const char *, unsigned long,
const Obj_Entry *, bool));
const Elf_Sym *_rtld_find_symdef __P((const Obj_Entry *, Elf_Word,
const char *, const Obj_Entry *, const Obj_Entry **, bool));
/* map_object.c */
extern Obj_Entry *_rtld_map_object(const char *, int);
Obj_Entry *_rtld_map_object __P((const char *, int));
#if defined(__mips__)
/* mips_reloc.c */
extern void _rtld_relocate_mips_got(Obj_Entry *);
extern caddr_t _rtld_bind_mips (Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr);
void _rtld_relocate_mips_got __P((Obj_Entry *));
caddr_t _rtld_bind_mips __P((Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr));
#endif
#if defined(__powerpc__)
/* ppc_reloc.c */
extern caddr_t _rtld_bind_powerpc(const Obj_Entry *, Elf_Word);
extern int _rtld_reloc_powerpc_plt(const Obj_Entry *, const Elf_RelA *, bool);
extern void _rtld_setup_powerpc_plt(const Obj_Entry *);
caddr_t _rtld_bind_powerpc __P((const Obj_Entry *, Elf_Word));
int _rtld_reloc_powerpc_plt __P((const Obj_Entry *, const Elf_RelA *, bool));
void _rtld_setup_powerpc_plt __P((const Obj_Entry *));
#endif
#endif /* } */
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtldenv.h,v 1.2 1997/10/08 08:55:38 mrg Exp $ */
/* $NetBSD: rtldenv.h,v 1.3 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@ -33,40 +33,49 @@
#include <stddef.h>
#include <stdarg.h>
extern void *xcalloc(size_t);
extern void *xmalloc(size_t);
extern char *xstrdup(const char *);
void *xcalloc __P((size_t));
void *xmalloc __P((size_t));
char *xstrdup __P((const char *));
#ifdef RTLD_LOADER
extern void xprintf(const char *fmt, ...);
extern void xvprintf(const char *fmt, va_list ap);
extern void xsnprintf(char *buf, size_t buflen, const char *fmt, ...);
extern size_t xvsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap);
extern void xwarn(const char *fmt, ...);
extern void xwarnx(const char *fmt, ...);
extern void xerr(int eval, const char *fmt, ...);
extern void xerrx(int eval, const char *fmt, ...);
extern void xassert(const char *file, int line, const char *failedexpr);
extern const char *xstrerror(int error);
void xprintf __P((const char *, ...))
__attribute__((__format__(__printf__, 1, 2)));
void xvprintf __P((const char *, va_list))
__attribute__((__format__(__printf__, 1, 0)));
void xsnprintf __P((char *, size_t, const char *, ...))
__attribute__((__format__(__printf__, 3, 4)));
size_t xvsnprintf __P((char *, size_t, const char *, va_list))
__attribute__((__format__(__printf__, 3, 0)));
void xwarn __P((const char *, ...))
__attribute__((__format__(__printf__, 1, 2)));
void xwarnx __P((const char *, ...))
__attribute__((__format__(__printf__, 1, 2)));
void xerr __P((int, const char *, ...))
__attribute__((__format__(__printf__, 2, 3)));
void xerrx __P((int, const char *, ...))
__attribute__((__format__(__printf__, 2, 3)));
#define assert(cond) ((cond) \
void xassert __P((const char *, int, const char *));
const char *xstrerror __P((int));
# define assert(cond) ((cond) \
? (void) 0 :\
(xassert(__FILE__, __LINE__, #cond "\n"), abort()))
#else
#include <assert.h>
#include <stdio.h>
#include <err.h>
#define xprintf printf
#define xvprintf vprintf
#define xsnprintf snprintf
#define xvsnprintf vsnprintf
#define xwarn warn
#define xwarnx warnx
#define xerr err
#define xerrx errx
#define xassert assert
#define xstrerror strerror
# include <assert.h>
# include <stdio.h>
# include <err.h>
# define xprintf printf
# define xvprintf vprintf
# define xsnprintf snprintf
# define xvsnprintf vsnprintf
# define xwarn warn
# define xwarnx warnx
# define xerr err
# define xerrx errx
# define xassert assert
# define xstrerror strerror
#endif
#endif /* _RTLDENV_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: search.c,v 1.3 1997/02/17 19:32:05 cgd Exp $ */
/* $NetBSD: search.c,v 1.4 1999/03/01 16:40:07 christos Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@ -61,66 +61,74 @@
/*
* Data declarations.
*/
static bool _rtld_check_library __P((const char *));
static char *_rtld_search_library_path __P((const char *, size_t, const char *,
size_t));
static bool
_rtld_check_library(
const char *pathname)
_rtld_check_library(pathname)
const char *pathname;
{
struct stat mystat;
Elf_Ehdr ehdr;
int fd;
struct stat mystat;
Elf_Ehdr ehdr;
int fd;
if (stat(pathname, &mystat) >= 0 && S_ISREG(mystat.st_mode)) {
if ((fd = open(pathname, O_RDONLY)) >= 0) {
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
if (stat(pathname, &mystat) == -1 || !S_ISREG(mystat.st_mode))
return false;
if ((fd = open(pathname, O_RDONLY)) == -1)
return false;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto lose;
/* Elf_e_ident includes class */
if (memcmp(Elf_e_ident, ehdr.e_ident, Elf_e_siz) != 0)
/* Elf_e_ident includes class */
if (memcmp(Elf_e_ident, ehdr.e_ident, Elf_e_siz) != 0)
goto lose;
switch (ehdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES)
default:
switch (ehdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES)
default:
goto lose;
}
}
if (ehdr.e_ident[Elf_ei_version] != Elf_ev_current ||
ehdr.e_version != Elf_ev_current ||
ehdr.e_ident[Elf_ei_data] != ELFDEFNNAME(MACHDEP_ENDIANNESS) ||
ehdr.e_type != Elf_et_dyn)
if (ehdr.e_ident[Elf_ei_version] != Elf_ev_current ||
ehdr.e_version != Elf_ev_current ||
ehdr.e_ident[Elf_ei_data] != ELFDEFNNAME(MACHDEP_ENDIANNESS) ||
ehdr.e_type != Elf_et_dyn)
goto lose;
close(fd);
return true;
close(fd);
return true;
lose:
close(fd);
}
}
return false;
close(fd);
return false;
}
static char *
_rtld_search_library_path(const char *name, int namelen, const char *dir, int dirlen)
_rtld_search_library_path(name, namelen, dir, dirlen)
const char *name;
size_t namelen;
const char *dir;
size_t dirlen;
{
char *pathname;
pathname = xmalloc(dirlen + 1 + namelen + 1);
strncpy(pathname, dir, dirlen);
(void)strncpy(pathname, dir, dirlen);
pathname[dirlen] = '/';
strcpy(pathname + dirlen + 1, name);
dbg(" Trying \"%s\"", pathname);
if(_rtld_check_library(pathname)) /* We found it */
dbg((" Trying \"%s\"", pathname));
if (_rtld_check_library(pathname)) /* We found it */
return pathname;
free(pathname);
return NULL;
}
/*
* Find the library with the given name, and return its full pathname.
* The returned string is dynamically allocated. Generates an error
@ -130,42 +138,47 @@ _rtld_search_library_path(const char *name, int namelen, const char *dir, int di
* loaded shared object, whose library search path will be searched.
*/
char *
_rtld_find_library(
const char *name,
const Obj_Entry *refobj)
_rtld_find_library(name, refobj)
const char *name;
const Obj_Entry *refobj;
{
Search_Path *sp;
char *pathname;
int namelen;
Search_Path *sp;
char *pathname;
int namelen;
if (strchr(name, '/') != NULL) { /* Hard coded pathname */
if (name[0] != '/' && !_rtld_trust) {
_rtld_error("Absolute pathname required for shared object \"%s\"",
name);
return NULL;
}
if (strchr(name, '/') != NULL) { /* Hard coded pathname */
if (name[0] != '/' && !_rtld_trust) {
_rtld_error(
"Absolute pathname required for shared object \"%s\"",
name);
return NULL;
}
#ifdef SVR4_LIBDIR
if (strncmp(name, SVR4_LIBDIR, SVR4_LIBDIRLEN) == 0
&& name[SVR4_LIBDIRLEN] == '/') { /* In "/usr/lib" */
/* Map hard-coded "/usr/lib" onto our ELF library directory. */
pathname = xmalloc(strlen(name) + LIBDIRLEN - SVR4_LIBDIRLEN + 1);
strcpy(pathname, LIBDIR);
strcpy(pathname + LIBDIRLEN, name + SVR4_LIBDIRLEN);
return pathname;
}
if (strncmp(name, SVR4_LIBDIR, SVR4_LIBDIRLEN) == 0
&& name[SVR4_LIBDIRLEN] == '/') { /* In "/usr/lib" */
/*
* Map hard-coded "/usr/lib" onto our ELF library
* directory.
*/
pathname = xmalloc(strlen(name) + LIBDIRLEN -
SVR4_LIBDIRLEN + 1);
(void)strcpy(pathname, LIBDIR);
(void)strcpy(pathname + LIBDIRLEN, name +
SVR4_LIBDIRLEN);
return pathname;
}
#endif /* SVR4_LIBDIR */
return xstrdup(name);
}
dbg(" Searching for \"%s\" (%p)", name, refobj);
return xstrdup(name);
}
dbg((" Searching for \"%s\" (%p)", name, refobj));
namelen = strlen(name);
if (refobj != NULL)
for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, namelen,
sp->sp_path, sp->sp_pathlen)) != NULL)
return (pathname);
if (refobj != NULL)
for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, namelen,
sp->sp_path, sp->sp_pathlen)) != NULL)
return (pathname);
for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, namelen,
@ -173,17 +186,19 @@ _rtld_find_library(
return (pathname);
#if 0
if((refobj != NULL &&
(pathname = _rtld_search_library_path(name, refobj->rpath)) != NULL) ||
(pathname = _rtld_search_library_path(name, ld_library_path)) != NULL
if ((refobj != NULL &&
(pathname = _rtld_search_library_path(name,
refobj->rpath)) != NULL) ||
(pathname = _rtld_search_library_path(name,
ld_library_path)) != NULL
#ifdef SVR4_LIBDIR
LOSE!
|| (pathname = _rtld_search_library_path(name, SVR4_LIBDIR)) != NULL
LOSE !
||(pathname = _rtld_search_library_path(name, SVR4_LIBDIR)) != NULL
#endif
)
)
return pathname;
#endif
_rtld_error("Shared object \"%s\" not found", name);
return NULL;
_rtld_error("Shared object \"%s\" not found", name);
return NULL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: symbol.c,v 1.2 1998/03/25 04:13:02 mhitch Exp $ */
/* $NetBSD: symbol.c,v 1.3 1999/03/01 16:40:08 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -57,20 +57,20 @@
* this. It is specified by the System V ABI.
*/
unsigned long
_rtld_elf_hash(
const char *name)
_rtld_elf_hash(name)
const char *name;
{
const unsigned char *p = (const unsigned char *) name;
unsigned long h = 0;
unsigned long g;
const unsigned char *p = (const unsigned char *) name;
unsigned long h = 0;
unsigned long g;
while(*p != '\0') {
h = (h << 4) + *p++;
if ((g = h & 0xf0000000) != 0)
h ^= g >> 24;
h &= ~g;
}
return h;
while (*p != '\0') {
h = (h << 4) + *p++;
if ((g = h & 0xf0000000) != 0)
h ^= g >> 24;
h &= ~g;
}
return h;
}
/*
@ -82,40 +82,39 @@ _rtld_elf_hash(
* eliminates many recomputations of the hash value.
*/
const Elf_Sym *
_rtld_symlook_obj(
const char *name,
unsigned long hash,
const Obj_Entry *obj,
bool in_plt)
_rtld_symlook_obj(name, hash, obj, in_plt)
const char *name;
unsigned long hash;
const Obj_Entry *obj;
bool in_plt;
{
unsigned long symnum = obj->buckets[hash % obj->nbuckets];
unsigned long symnum = obj->buckets[hash % obj->nbuckets];
while (symnum != ELF_SYM_UNDEFINED) {
const Elf_Sym *symp;
const char *strp;
while (symnum != ELF_SYM_UNDEFINED) {
const Elf_Sym *symp;
const char *strp;
assert(symnum < obj->nchains);
symp = obj->symtab + symnum;
strp = obj->strtab + symp->st_name;
assert(symnum < obj->nchains);
symp = obj->symtab + symnum;
strp = obj->strtab + symp->st_name;
#if 0
assert(symp->st_name != 0);
assert(symp->st_name != 0);
#endif
if (strcmp(name, strp) == 0) {
if (symp->st_shndx != Elf_eshn_undefined
#if !defined(__mips__) /* Following doesn't work on MIPS? mhitch */
|| (!in_plt && symp->st_value != 0 &&
ELF_SYM_TYPE(symp->st_info) == Elf_estt_func)) {
if (strcmp(name, strp) == 0) {
if (symp->st_shndx != Elf_eshn_undefined
#if !defined(__mips__) /* Following doesn't work on MIPS? mhitch */
|| (!in_plt && symp->st_value != 0 &&
ELF_SYM_TYPE(symp->st_info) == Elf_estt_func)) {
#else
) {
) {
#endif
return symp;
}
return symp;
}
}
symnum = obj->chains[symnum];
}
symnum = obj->chains[symnum];
}
return NULL;
return NULL;
}
/*
@ -125,51 +124,55 @@ _rtld_symlook_obj(
* defining object via the reference parameter DEFOBJ_OUT.
*/
const Elf_Sym *
_rtld_find_symdef(
const Obj_Entry *obj_list,
Elf_Word r_info,
const char *name,
const Obj_Entry *refobj,
const Obj_Entry **defobj_out,
bool in_plt)
_rtld_find_symdef(obj_list, r_info, name, refobj, defobj_out, in_plt)
const Obj_Entry *obj_list;
Elf_Word r_info;
const char *name;
const Obj_Entry *refobj;
const Obj_Entry **defobj_out;
bool in_plt;
{
Elf_Word symnum = ELF_R_SYM(r_info);
const Elf_Sym *ref;
const Obj_Entry *obj;
unsigned long hash;
Elf_Word symnum = ELF_R_SYM(r_info);
const Elf_Sym *ref;
const Obj_Entry *obj;
unsigned long hash;
if (name == NULL) {
ref = refobj->symtab + symnum;
name = refobj->strtab + ref->st_name;
}
hash = _rtld_elf_hash(name);
if (refobj->symbolic) { /* Look first in the referencing object */
const Elf_Sym *def = _rtld_symlook_obj(name, hash, refobj, in_plt);
if (def != NULL) {
*defobj_out = refobj;
return def;
if (name == NULL) {
ref = refobj->symtab + symnum;
name = refobj->strtab + ref->st_name;
}
}
hash = _rtld_elf_hash(name);
/*
* Look in all loaded objects. Skip the referencing object, if
* we have already searched it.
*/
for (obj = obj_list; obj != NULL; obj = obj->next) {
if (obj != refobj || !refobj->symbolic) {
const Elf_Sym *def = _rtld_symlook_obj(name, hash, obj, in_plt);
if (def != NULL) {
*defobj_out = obj;
return def;
}
if (refobj->symbolic) { /* Look first in the referencing object */
const Elf_Sym *def;
def = _rtld_symlook_obj(name, hash, refobj, in_plt);
if (def != NULL) {
*defobj_out = refobj;
return def;
}
}
}
/*
* Look in all loaded objects. Skip the referencing object, if
* we have already searched it.
*/
for (obj = obj_list; obj != NULL; obj = obj->next) {
if (obj != refobj || !refobj->symbolic) {
const Elf_Sym *def;
if (ELF_R_TYPE(r_info) != R_TYPE(NONE)) {
_rtld_error("%s: Undefined %ssymbol \"%s\" (reloc type = %d, symnum = %d)",
refobj->path, in_plt ? "PLT " : "", name,
ELF_R_TYPE(r_info), symnum);
}
return NULL;
def = _rtld_symlook_obj(name, hash, obj, in_plt);
if (def != NULL) {
*defobj_out = obj;
return def;
}
}
}
if (ELF_R_TYPE(r_info) != R_TYPE(NONE)) {
_rtld_error(
"%s: Undefined %ssymbol \"%s\" (reloc type = %d, symnum = %d)",
refobj->path, in_plt ? "PLT " : "", name,
ELF_R_TYPE(r_info), symnum);
}
return NULL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: xmalloc.c,v 1.1 1996/12/16 20:38:07 cgd Exp $ */
/* $NetBSD: xmalloc.c,v 1.2 1999/03/01 16:40:08 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -31,31 +31,36 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include "rtldenv.h"
#include <stddef.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
void *
xcalloc(size_t size)
xcalloc(size)
size_t size;
{
return memset(xmalloc(size), 0, size);
return memset(xmalloc(size), 0, size);
}
void *
xmalloc(size_t size)
xmalloc(size)
size_t size;
{
void *p = malloc(size);
if(p == NULL)
xerr(1, "Out of memory");
return p;
void *p = malloc(size);
if (p == NULL)
xerr(1, "%s", xstrerror(errno));
return p;
}
char *
xstrdup(const char *s)
char*
xstrdup(s)
const char *s;
{
char *p = strdup(s);
if(p == NULL)
xerr(1, "Out of memory");
return p;
char *p = strdup(s);
if (p == NULL)
xerr(1, "%s", xstrerror(errno));
return p;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: xprintf.c,v 1.3 1999/02/27 21:52:23 scottr Exp $ */
/* $NetBSD: xprintf.c,v 1.4 1999/03/01 16:40:08 christos Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@ -27,10 +27,16 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include "rtldenv.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#define SZ_SHORT 0x01
#define SZ_INT 0x02
@ -46,263 +52,333 @@
* deals withs formats %x, %p, %s, and %d.
*/
size_t
xvsnprintf(
char *buf,
size_t buflen,
const char *fmt,
va_list ap)
xvsnprintf(buf, buflen, fmt, ap)
char *buf;
size_t buflen;
const char *fmt;
va_list ap;
{
char *bp = buf;
char * const ep = buf + buflen - 4;
int size;
char *bp = buf;
char *const ep = buf + buflen - 4;
int size;
while (*fmt != NULL && bp < ep) {
switch (*fmt) {
case '\\': {
if (fmt[1] != '\0')
*bp++ = *++fmt;
continue;
}
case '%': {
size = SZ_INT;
rflag: switch (fmt[1]) {
case 'h':
size = (size & SZ_MASK) | SZ_SHORT;
fmt++;
goto rflag;
case 'l':
size = (size & SZ_MASK) | SZ_LONG;
fmt++;
if (fmt[1] == 'l') {
case 'q':
size = (size & SZ_MASK) | SZ_QUAD;
fmt++;
while (*fmt != NULL && bp < ep) {
switch (*fmt) {
case '\\':{
if (fmt[1] != '\0')
*bp++ = *++fmt;
continue;
}
goto rflag;
case 'u':
size |= SZ_UNSIGNED;
/* FALLTHROUGH*/
case 'd': {
long long sval;
unsigned long long uval;
char digits[sizeof(int) * 3], *dp = digits;
case '%':{
size = SZ_INT;
rflag: switch (fmt[1]) {
case 'h':
size = (size&SZ_MASK)|SZ_SHORT;
fmt++;
goto rflag;
case 'l':
size = (size&SZ_MASK)|SZ_LONG;
fmt++;
if (fmt[1] == 'l') {
case 'q':
size = (size&SZ_MASK)|SZ_QUAD;
fmt++;
}
goto rflag;
case 'u':
size |= SZ_UNSIGNED;
/* FALLTHROUGH */
case 'd':{
long long sval;
unsigned long long uval;
char digits[sizeof(int) * 3], *dp = digits;
#define SARG() \
(size & SZ_SHORT ? va_arg(ap, short) : \
size & SZ_LONG ? va_arg(ap, long) : \
size & SZ_QUAD ? va_arg(ap, long long) : \
va_arg(ap, int))
(size & SZ_SHORT ? va_arg(ap, short) : \
size & SZ_LONG ? va_arg(ap, long) : \
size & SZ_QUAD ? va_arg(ap, long long) : \
va_arg(ap, int))
#define UARG() \
(size & SZ_SHORT ? va_arg(ap, unsigned short) : \
size & SZ_LONG ? va_arg(ap, unsigned long) : \
size & SZ_QUAD ? va_arg(ap, unsigned long long) : \
va_arg(ap, unsigned int))
(size & SZ_SHORT ? va_arg(ap, unsigned short) : \
size & SZ_LONG ? va_arg(ap, unsigned long) : \
size & SZ_QUAD ? va_arg(ap, unsigned long long) : \
va_arg(ap, unsigned int))
#define ARG() (size & SZ_UNSIGNED ? UARG() : SARG())
if (fmt[1] == 'd') {
sval = ARG();
if (sval < 0) {
if ((sval << 1) == 0) {
/*
* We can't flip the sign of this since
* it's can't represented as a postive
* number in two complement, handle the
* first digit. After that, it can be
* flipped since it is now not 2^(n-1).
*/
*dp++ = '0' - (sval % 10);
sval /= 10;
if (fmt[1] == 'd') {
sval = ARG();
if (sval < 0) {
if ((sval << 1) == 0) {
/*
* We can't flip the
* sign of this since
* it can't be
* represented as a
* positive number in
* two complement,
* handle the first
* digit. After that,
* it can be flipped
* since it is now not
* 2^(n-1).
*/
*dp++ = '0'-(sval % 10);
sval /= 10;
}
*bp++ = '-';
uval = -sval;
} else {
uval = sval;
}
} else {
uval = ARG();
}
do {
*dp++ = '0' + (uval % 10);
uval /= 10;
} while (uval != 0);
do {
*bp++ = *--dp;
} while (dp != digits && bp < ep);
fmt += 2;
break;
}
*bp++ = '-';
uval = -sval;
} else {
uval = sval;
}
} else {
uval = ARG();
}
do {
*dp++ = '0' + (uval % 10);
uval /= 10;
} while (uval != 0);
do {
*bp++ = *--dp;
} while (dp != digits && bp < ep);
fmt += 2;
break;
}
case 'x': case 'p': {
unsigned long val = va_arg(ap, unsigned long);
unsigned long mask = ~(~0UL >> 4);
int bits = sizeof(val) * 8 - 4;
const char hexdigits[] = "0123456789abcdef";
if (fmt[1] == 'p') {
*bp++ = '0';
*bp++ = 'x';
}
/* handle the border case */
if (val == 0) {
*bp++ = '0';
fmt += 2;
break;
}
/* suppress 0s */
while ((val & mask) == 0)
bits -= 4, mask >>= 4;
case 'x':
case 'p':{
unsigned long val = va_arg(ap, unsigned long);
unsigned long mask = ~(~0UL >> 4);
int bits = sizeof(val) * 8 - 4;
const char hexdigits[] = "0123456789abcdef";
if (fmt[1] == 'p') {
*bp++ = '0';
*bp++ = 'x';
}
/* handle the border case */
if (val == 0) {
*bp++ = '0';
fmt += 2;
break;
}
/* suppress 0s */
while ((val & mask) == 0)
bits -= 4, mask >>= 4;
/* emit the hex digits */
while (bits >= 0 && bp < ep) {
*bp++ = hexdigits[(val & mask) >> bits];
bits -= 4, mask >>= 4;
}
fmt += 2;
break;
}
case 's': {
const char *str = va_arg(ap, const char *);
int len;
if (str == NULL)
str = "(null)";
/* emit the hex digits */
while (bits >= 0 && bp < ep) {
*bp++ = hexdigits[(val & mask) >> bits];
bits -= 4, mask >>= 4;
}
fmt += 2;
break;
}
case 's':{
const char *str = va_arg(ap, const char *);
int len;
len = strlen(str);
if (ep - bp < len)
len = ep - bp;
memcpy(bp, str, len);
bp += len;
fmt += 2;
break;
}
default:
*bp++ = *fmt;
break;
}
break;
if (str == NULL)
str = "(null)";
len = strlen(str);
if (ep - bp < len)
len = ep - bp;
memcpy(bp, str, len);
bp += len;
fmt += 2;
break;
}
default:
*bp++ = *fmt;
break;
}
break;
}
default:
*bp++ = *fmt++;
break;
}
}
default:
*bp++ = *fmt++;
break;
}
}
*bp = '\0';
return bp - buf;
*bp = '\0';
return bp - buf;
}
void
xvprintf(
const char *fmt,
va_list ap)
xvprintf(fmt, ap)
const char *fmt;
va_list ap;
{
char buf[256];
(void) write(2, buf, xvsnprintf(buf, sizeof(buf), fmt, ap));
char buf[256];
(void) write(2, buf, xvsnprintf(buf, sizeof(buf), fmt, ap));
}
void
xprintf(
const char *fmt,
...)
#ifdef __STDC__
xprintf(const char *fmt, ...)
#else
xprintf(va_alist)
va_dcl
#endif
{
va_list ap;
va_start(ap, fmt);
va_list ap;
xvprintf(fmt, ap);
#ifdef __STDC__
va_start(ap, fmt);
#else
const char *fmt;
va_end(ap);
va_start(ap);
fmt = va_arg(ap, const char *);
#endif
xvprintf(fmt, ap);
va_end(ap);
}
void
xsnprintf(
char *buf,
size_t buflen,
const char *fmt,
...)
#ifdef __STDC__
xsnprintf(char *buf, size_t buflen, const char *fmt, ...)
#else
xsnprintf(va_alist)
va_dcl
#endif
{
va_list ap;
va_start(ap, fmt);
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
char *buf;
size_t buflen;
const char *fmt;
xvprintf(fmt, ap);
va_start(ap);
buf = va_arg(ap, char *);
buflen = va_arg(ap, size_t);
fmt = va_arg(ap, const char *);
#endif
xvsnprintf(buf, buflen, fmt, ap);
va_end(ap);
va_end(ap);
}
const char *
xstrerror(
int error)
xstrerror(error)
int error;
{
if (error >= sys_nerr) {
static char buf[128];
xsnprintf(buf, sizeof(buf), "Unknown error: %d", error);
return buf;
}
return sys_errlist[error];
if (error >= sys_nerr || error < 0) {
static char buf[128];
xsnprintf(buf, sizeof(buf), "Unknown error: %d", error);
return buf;
}
return sys_errlist[error];
}
void
xerrx(
int eval,
const char *fmt,
...)
#ifdef __STDC__
xerrx(int eval, const char *fmt, ...)
#else
xerrx(va_alist)
va_dcl
#endif
{
va_list ap;
va_start(ap, fmt);
xvprintf(fmt, ap);
va_end(ap);
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
int eval;
const char *fmt;
exit(eval);
va_start(ap);
eval = va_arg(ap, int);
fmt = va_arg(ap, const char *);
#endif
xvprintf(fmt, ap);
va_end(ap);
exit(eval);
}
void
xerr(
int eval,
const char *fmt,
...)
#ifdef __STDC__
xerr(int eval, const char *fmt, ...)
#else
xerr(va_alist)
va_dcl
#endif
{
int saved_errno = errno;
int saved_errno = errno;
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
int eval;
const char *fmt;
va_list ap;
va_start(ap, fmt);
xvprintf(fmt, ap);
va_end(ap);
va_start(ap);
eval = va_arg(ap, int);
fmt = va_arg(ap, const char *);
#endif
xvprintf(fmt, ap);
va_end(ap);
xprintf(": %s\n", xstrerror(saved_errno));
exit(eval);
xprintf(": %s\n", xstrerror(saved_errno));
exit(eval);
}
void
xwarn(
const char *fmt,
...)
#ifdef __STDC__
xwarn(const char *fmt, ...)
#else
xwarn(va_alist)
va_dcl
#endif
{
int saved_errno = errno;
int saved_errno = errno;
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
const char *fmt;
va_list ap;
va_start(ap, fmt);
xvprintf(fmt, ap);
va_end(ap);
va_start(ap);
fmt = va_arg(ap, const char *);
#endif
xvprintf(fmt, ap);
va_end(ap);
xprintf(": %s\n", xstrerror(saved_errno));
errno = saved_errno;
xprintf(": %s\n", xstrerror(saved_errno));
errno = saved_errno;
}
void
xwarnx(
const char *fmt,
...)
#ifdef __STDC__
xwarnx(const char *fmt, ...)
#else
xwarnx(va_alist)
va_dcl
#endif
{
va_list ap;
va_start(ap, fmt);
xvprintf(fmt, ap);
va_end(ap);
va_list ap;
#ifdef __STDC__
va_start(ap, fmt);
#else
const char *fmt;
va_start(ap);
fmt = va_arg(ap, const char *);
#endif
xvprintf(fmt, ap);
va_end(ap);
}
void
xassert(
const char *file,
int line,
const char *failedexpr)
xassert(file, line, failedexpr)
const char *file;
int line;
const char *failedexpr;
{
xprintf("assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
abort();
/* NOTREACHED */
xprintf("assertion \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
abort();
/* NOTREACHED */
}