KNF
This commit is contained in:
parent
bc97a25328
commit
26475619ed
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 /* } */
|
||||
#ifdef RTLD_DEBUG_RELOC
|
||||
#define rdbg(f, format, args...) if (f) debug_printf(format, ## args)
|
||||
# define dbg(a) debug_printf a
|
||||
#else
|
||||
#define rdbg(f, format, args...) ((void) 0)
|
||||
# define dbg(a) ((void) 0)
|
||||
#endif
|
||||
#ifdef RTLD_DEBUG_RELOC
|
||||
# define rdbg(f, a) if (f) debug_printf a
|
||||
#else
|
||||
# define rdbg(f, a) ((void) 0)
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
# 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
|
||||
# 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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue