Several small changes that shave 7-8% off the simple-exec-loop test:

* Rename _rtld_find_library() to _rtld_load_library().  It now calls
  _rtld_load_object() if necessary to actually load the object, rather
  than having the caller do it.  To do this, it also takes the `mode'
  argument that gets passed to _rtld_load_object().

* On a related note, remove _rtld_check_library(), and instead call
  _rtld_load_object() to instead try actually loading the object.  We
  save two extra namei's and a bunch of redundant work (almost
  literally the same code) this way.

* In _rtld_map_object(), mmap(2) the first page read-only, rather than
  read(2)ing it.

* In _rtld_symlook_obj(), compare the *second* character of the symbol
  name before calling strcmp().  (This first character is too
  frequently `_', and turns out to not be helpful, in libc.)

* Also in _rtld_symlook_obj(), remove the bogus STT_FUNC special case
  -- this also allows removing the `in_plt' argument to
  _rtld_symlook_list() and _rtld_symlook_obj().

Also:

* In _rtld_obj_from_addr(), rather than trying to look up `_end' in
  the each object, instead use obj->mapsize as the upper bound.
This commit is contained in:
mycroft 2002-09-23 23:56:46 +00:00
parent f0efca630a
commit 86103e2f0e
7 changed files with 116 additions and 186 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: load.c,v 1.18 2002/09/12 22:56:28 mycroft Exp $ */ /* $NetBSD: load.c,v 1.19 2002/09/23 23:56:46 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -101,9 +101,9 @@ _rtld_load_object(filepath, mode)
int fd = -1; int fd = -1;
struct stat sb; struct stat sb;
for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
if (strcmp(obj->path, filepath) == 0) if (!strcmp(obj->path, filepath))
break; break;
/* /*
* If we didn't find a match by pathname, open the file and check * If we didn't find a match by pathname, open the file and check
@ -138,7 +138,6 @@ _rtld_load_object(filepath, mode)
free(filepath); free(filepath);
return NULL; return NULL;
} }
obj->path = filepath;
_rtld_digest_dynamic(obj); _rtld_digest_dynamic(obj);
*_rtld_objtail = obj; *_rtld_objtail = obj;
@ -170,7 +169,6 @@ _rtld_load_by_name(name, obj, needed, mode)
Library_Xform *x = _rtld_xforms; Library_Xform *x = _rtld_xforms;
Obj_Entry *o = NULL; Obj_Entry *o = NULL;
size_t i, j; size_t i, j;
char *libpath;
bool got = false; bool got = false;
union { union {
int i; int i;
@ -219,16 +217,13 @@ _rtld_load_by_name(name, obj, needed, mode)
* what we loaded in the needed objects */ * what we loaded in the needed objects */
for (j = 0; j < RTLD_MAX_LIBRARY && for (j = 0; j < RTLD_MAX_LIBRARY &&
x->entry[i].library[j] != NULL; j++) { x->entry[i].library[j] != NULL; j++) {
libpath = _rtld_find_library( o = _rtld_load_library(x->entry[i].library[j], obj,
x->entry[i].library[j], obj); mode);
if (libpath == NULL) { if (o == NULL) {
xwarnx("could not load %s for %s", xwarnx("could not load %s for %s",
x->entry[i].library[j], name); x->entry[i].library[j], name);
continue; continue;
} }
o = _rtld_load_object(libpath, mode);
if (o == NULL)
continue;
got = true; got = true;
if (j == 0) if (j == 0)
(*needed)->obj = o; (*needed)->obj = o;
@ -249,10 +244,7 @@ _rtld_load_by_name(name, obj, needed, mode)
if (got) if (got)
return true; return true;
libpath = _rtld_find_library(name, obj); return ((*needed)->obj = _rtld_load_library(name, obj, mode)) != NULL;
if (libpath == NULL)
return false;
return ((*needed)->obj = _rtld_load_object(libpath, mode)) != NULL;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: map_object.c,v 1.15 2002/09/13 03:12:40 mycroft Exp $ */ /* $NetBSD: map_object.c,v 1.16 2002/09/23 23:56:47 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -53,7 +53,7 @@ static int protflags __P((int)); /* Elf flags -> mmap protection */
*/ */
Obj_Entry * Obj_Entry *
_rtld_map_object(path, fd, sb) _rtld_map_object(path, fd, sb)
const char *path; char *path;
int fd; int fd;
const struct stat *sb; const struct stat *sb;
{ {
@ -61,8 +61,7 @@ _rtld_map_object(path, fd, sb)
union { union {
Elf_Ehdr hdr; Elf_Ehdr hdr;
char buf[PAGESIZE]; char buf[PAGESIZE];
} u; } *u;
int nbytes;
Elf_Phdr *phdr; Elf_Phdr *phdr;
Elf_Phdr *phlimit; Elf_Phdr *phlimit;
Elf_Phdr *segs[2]; Elf_Phdr *segs[2];
@ -89,33 +88,34 @@ _rtld_map_object(path, fd, sb)
size_t nclear; size_t nclear;
#endif #endif
if ((nbytes = read(fd, u.buf, PAGESIZE)) == -1) { u = mmap(NULL, PAGESIZE, PROT_READ, MAP_FILE | MAP_SHARED, fd,
(off_t)0);
if (u == MAP_FAILED) {
_rtld_error("%s: read error: %s", path, xstrerror(errno)); _rtld_error("%s: read error: %s", path, xstrerror(errno));
return NULL; return NULL;
} }
/* Make sure the file is valid */ /* Make sure the file is valid */
if (nbytes < sizeof(Elf_Ehdr) || if (memcmp(ELFMAG, u->hdr.e_ident, SELFMAG) != 0 ||
memcmp(ELFMAG, u.hdr.e_ident, SELFMAG) != 0 || u->hdr.e_ident[EI_CLASS] != ELFCLASS) {
u.hdr.e_ident[EI_CLASS] != ELFCLASS) {
_rtld_error("%s: unrecognized file format", path); _rtld_error("%s: unrecognized file format", path);
return NULL; goto bad;
} }
/* Elf_e_ident includes class */ /* Elf_e_ident includes class */
if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT || if (u->hdr.e_ident[EI_VERSION] != EV_CURRENT ||
u.hdr.e_version != EV_CURRENT || u->hdr.e_version != EV_CURRENT ||
u.hdr.e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) { u->hdr.e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
_rtld_error("%s: Unsupported file version", path); _rtld_error("%s: unsupported file version", path);
return NULL; goto bad;
} }
if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) { if (u->hdr.e_type != ET_EXEC && u->hdr.e_type != ET_DYN) {
_rtld_error("%s: Unsupported file type", path); _rtld_error("%s: unsupported file type", path);
return NULL; goto bad;
} }
switch (u.hdr.e_machine) { switch (u->hdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES) ELFDEFNNAME(MACHDEP_ID_CASES)
default: default:
_rtld_error("%s: Unsupported machine", path); _rtld_error("%s: unsupported machine", path);
return NULL; goto bad;
} }
/* /*
@ -123,9 +123,8 @@ _rtld_map_object(path, fd, sb)
* not strictly required by the ABI specification, but it seems to * not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably. * always true in practice. And, it simplifies things considerably.
*/ */
assert(u.hdr.e_phentsize == sizeof(Elf_Phdr)); 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) <= PAGESIZE);
assert(u.hdr.e_phoff + u.hdr.e_phnum * sizeof(Elf_Phdr) <= nbytes);
/* /*
* Scan the program header entries, and save key information. * Scan the program header entries, and save key information.
@ -133,8 +132,8 @@ _rtld_map_object(path, fd, sb)
* We rely on there being exactly two load segments, text and data, * We rely on there being exactly two load segments, text and data,
* in that order. * in that order.
*/ */
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff); phdr = (Elf_Phdr *) (u->buf + u->hdr.e_phoff);
phlimit = phdr + u.hdr.e_phnum; phlimit = phdr + u->hdr.e_phnum;
nsegs = 0; nsegs = 0;
phdyn = phphdr = phinterp = NULL; phdyn = phphdr = phinterp = NULL;
while (phdr < phlimit) { while (phdr < phlimit) {
@ -162,12 +161,12 @@ _rtld_map_object(path, fd, sb)
} }
if (phdyn == NULL) { if (phdyn == NULL) {
_rtld_error("%s: not dynamically linked", path); _rtld_error("%s: not dynamically linked", path);
return NULL; goto bad;
} }
if (nsegs != 2) { if (nsegs != 2) {
_rtld_error("%s: wrong number of segments (%d != 2)", path, _rtld_error("%s: wrong number of segments (%d != 2)", path,
nsegs); nsegs);
return NULL; goto bad;
} }
/* /*
@ -189,7 +188,7 @@ _rtld_map_object(path, fd, sb)
mapsize = base_vlimit - base_vaddr; mapsize = base_vlimit - base_vaddr;
#ifdef RTLD_LOADER #ifdef RTLD_LOADER
base_addr = u.hdr.e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL; base_addr = u->hdr.e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
#else #else
base_addr = NULL; base_addr = NULL;
#endif #endif
@ -199,7 +198,7 @@ _rtld_map_object(path, fd, sb)
if (mapbase == MAP_FAILED) { if (mapbase == MAP_FAILED) {
_rtld_error("mmap of entire address space failed: %s", _rtld_error("mmap of entire address space failed: %s",
xstrerror(errno)); xstrerror(errno));
return NULL; goto bad;
} }
base_addr = mapbase; base_addr = mapbase;
@ -215,7 +214,7 @@ _rtld_map_object(path, fd, sb)
== MAP_FAILED) { == MAP_FAILED) {
_rtld_error("mmap of data failed: %s", xstrerror(errno)); _rtld_error("mmap of data failed: %s", xstrerror(errno));
munmap(mapbase, mapsize); munmap(mapbase, mapsize);
return NULL; goto bad;
} }
/* Overlay the bss segment onto the proper region. */ /* Overlay the bss segment onto the proper region. */
@ -225,7 +224,7 @@ _rtld_map_object(path, fd, sb)
== MAP_FAILED) { == MAP_FAILED) {
_rtld_error("mmap of bss failed: %s", xstrerror(errno)); _rtld_error("mmap of bss failed: %s", xstrerror(errno));
munmap(mapbase, mapsize); munmap(mapbase, mapsize);
return NULL; goto bad;
} }
/* Unmap the gap between the text and data. */ /* Unmap the gap between the text and data. */
@ -235,7 +234,7 @@ _rtld_map_object(path, fd, sb)
_rtld_error("munmap of text -> data gap failed: %s", _rtld_error("munmap of text -> data gap failed: %s",
xstrerror(errno)); xstrerror(errno));
munmap(mapbase, mapsize); munmap(mapbase, mapsize);
return NULL; goto bad;
} }
#ifdef RTLD_LOADER #ifdef RTLD_LOADER
@ -249,6 +248,7 @@ _rtld_map_object(path, fd, sb)
#endif #endif
obj = _rtld_obj_new(); obj = _rtld_obj_new();
obj->path = path;
if (sb != NULL) { if (sb != NULL) {
obj->dev = sb->st_dev; obj->dev = sb->st_dev;
obj->ino = sb->st_ino; obj->ino = sb->st_ino;
@ -260,8 +260,8 @@ _rtld_map_object(path, fd, sb)
obj->vaddrbase = base_vaddr; obj->vaddrbase = base_vaddr;
obj->relocbase = mapbase - base_vaddr; obj->relocbase = mapbase - base_vaddr;
obj->dynamic = (Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr); obj->dynamic = (Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr);
if (u.hdr.e_entry != 0) if (u->hdr.e_entry != 0)
obj->entry = (caddr_t)(obj->relocbase + u.hdr.e_entry); obj->entry = (caddr_t)(obj->relocbase + u->hdr.e_entry);
if (phphdr != NULL) { if (phphdr != NULL) {
obj->phdr = (const Elf_Phdr *) obj->phdr = (const Elf_Phdr *)
(obj->relocbase + phphdr->p_vaddr); (obj->relocbase + phphdr->p_vaddr);
@ -269,9 +269,13 @@ _rtld_map_object(path, fd, sb)
} }
if (phinterp != NULL) if (phinterp != NULL)
obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr); obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr);
obj->isdynamic = u.hdr.e_type == ET_DYN; obj->isdynamic = u->hdr.e_type == ET_DYN;
return obj; return obj;
bad:
munmap(u, PAGESIZE);
return NULL;
} }
void void

View File

@ -1,4 +1,4 @@
/* $NetBSD: reloc.c,v 1.68 2002/09/17 07:29:46 junyoung Exp $ */ /* $NetBSD: reloc.c,v 1.69 2002/09/23 23:56:47 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -79,8 +79,7 @@ _rtld_do_copy_relocation(dstobj, rela)
Obj_Entry *srcobj; Obj_Entry *srcobj;
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, if ((srcsym = _rtld_symlook_obj(name, hash, srcobj)) != NULL)
false)) != NULL)
break; break;
if (srcobj == NULL) { if (srcobj == NULL) {
@ -236,6 +235,7 @@ _rtld_relocate_objects(first, bind_now, self)
return -1; return -1;
} }
} }
dbg(("a\n"));
if (_rtld_relocate_nonplt_objects(obj, self) < 0) if (_rtld_relocate_nonplt_objects(obj, self) < 0)
ok = 0; ok = 0;
if (obj->textrel) { /* Re-protected the text segment. */ if (obj->textrel) { /* Re-protected the text segment. */
@ -246,6 +246,7 @@ _rtld_relocate_objects(first, bind_now, self)
return -1; return -1;
} }
} }
dbg(("b\n"));
if (_rtld_relocate_plt_lazy(obj) < 0) if (_rtld_relocate_plt_lazy(obj) < 0)
ok = 0; ok = 0;
#if defined(__i386__) #if defined(__i386__)
@ -268,6 +269,7 @@ _rtld_relocate_objects(first, bind_now, self)
obj->dlclose = _rtld_dlclose; obj->dlclose = _rtld_dlclose;
obj->dladdr = _rtld_dladdr; obj->dladdr = _rtld_dladdr;
dbg(("c\n"));
/* Set the special PLTGOT entries. */ /* Set the special PLTGOT entries. */
if (obj->pltgot != NULL) if (obj->pltgot != NULL)
_rtld_setup_pltgot(obj); _rtld_setup_pltgot(obj);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.c,v 1.66 2002/09/21 05:24:17 junyoung Exp $ */ /* $NetBSD: rtld.c,v 1.67 2002/09/23 23:56:48 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -418,7 +418,8 @@ _rtld(sp, relocbase)
if (pAUX_execfd != NULL) { /* Load the main program. */ if (pAUX_execfd != NULL) { /* Load the main program. */
int fd = pAUX_execfd->a_v; int fd = pAUX_execfd->a_v;
dbg(("loading main program")); dbg(("loading main program"));
_rtld_objmain = _rtld_map_object(argv[0], fd, NULL); _rtld_objmain = _rtld_map_object(argv[0] ? xstrdup(argv[0]) :
xstrdup("main program"), fd, NULL);
close(fd); close(fd);
if (_rtld_objmain == NULL) if (_rtld_objmain == NULL)
_rtld_die(); _rtld_die();
@ -439,10 +440,6 @@ _rtld(sp, relocbase)
_rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
} }
if (argv[0] != NULL)
_rtld_objmain->path = xstrdup(argv[0]);
else
_rtld_objmain->path = xstrdup("main program");
_rtld_objmain->mainprog = true; _rtld_objmain->mainprog = true;
/* /*
@ -690,11 +687,8 @@ _rtld_dlopen(name, mode)
if (name == NULL) { if (name == NULL) {
obj = _rtld_objmain; obj = _rtld_objmain;
obj->refcount++; obj->refcount++;
} else { } else
char *path = _rtld_find_library(name, _rtld_objmain); obj = _rtld_load_library(name, _rtld_objmain, mode);
if (path != NULL)
obj = _rtld_load_object(path, mode);
}
if (obj != NULL) { if (obj != NULL) {
++obj->dl_refcount; ++obj->dl_refcount;
@ -732,7 +726,7 @@ _rtld_objmain_sym(name)
hash = _rtld_elf_hash(name); hash = _rtld_elf_hash(name);
obj = _rtld_objmain; obj = _rtld_objmain;
def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, true); def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj);
if (def != NULL) if (def != NULL)
return obj->relocbase + def->st_value; return obj->relocbase + def->st_value;
@ -766,11 +760,11 @@ _rtld_dlsym(handle, name)
return NULL; return NULL;
} }
if (handle == NULL) { /* Just the caller's shared object. */ if (handle == NULL) { /* Just the caller's shared object. */
def = _rtld_symlook_obj(name, hash, obj, true); def = _rtld_symlook_obj(name, hash, obj);
defobj = obj; defobj = obj;
} else { /* All the shared objects after the caller's */ } else { /* All the shared objects after the caller's */
while ((obj = obj->next) != NULL) { while ((obj = obj->next) != NULL) {
if ((def = _rtld_symlook_obj(name, hash, obj, true)) != NULL) { if ((def = _rtld_symlook_obj(name, hash, obj)) != NULL) {
defobj = obj; defobj = obj;
break; break;
} }
@ -782,13 +776,13 @@ _rtld_dlsym(handle, name)
if (obj->mainprog) { if (obj->mainprog) {
/* Search main program and all libraries loaded by it. */ /* Search main program and all libraries loaded by it. */
def = _rtld_symlook_list(name, hash, &_rtld_list_main, &defobj, true); def = _rtld_symlook_list(name, hash, &_rtld_list_main, &defobj);
} else { } else {
/* /*
* XXX - This isn't correct. The search should include the whole * XXX - This isn't correct. The search should include the whole
* DAG rooted at the given object. * DAG rooted at the given object.
*/ */
def = _rtld_symlook_obj(name, hash, obj, true); def = _rtld_symlook_obj(name, hash, obj);
defobj = obj; defobj = obj;
} }
} }
@ -943,18 +937,12 @@ _rtld_linkmap_delete(obj)
static Obj_Entry * static Obj_Entry *
_rtld_obj_from_addr(const void *addr) _rtld_obj_from_addr(const void *addr)
{ {
unsigned long endhash;
Obj_Entry *obj; Obj_Entry *obj;
endhash = _rtld_elf_hash(END_SYM);
for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
const Elf_Sym *endsym;
if (addr < (void *) obj->mapbase) if (addr < (void *) obj->mapbase)
continue; continue;
if ((endsym = _rtld_symlook_obj(END_SYM, endhash, obj, true)) == NULL) if (addr < (void *) (obj->mapbase + obj->mapsize))
continue; /* No "end" symbol?! */
if (addr < (void *) (obj->relocbase + endsym->st_value))
return obj; return obj;
} }
return NULL; return NULL;

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.52 2002/09/19 14:05:37 junyoung Exp $ */ /* $NetBSD: rtld.h,v 1.53 2002/09/23 23:56:49 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -269,19 +269,19 @@ int _rtld_relocate_plt_objects __P((const Obj_Entry *));
void _rtld_setup_pltgot __P((const Obj_Entry *)); void _rtld_setup_pltgot __P((const Obj_Entry *));
/* search.c */ /* search.c */
char *_rtld_find_library __P((const char *, const Obj_Entry *)); Obj_Entry *_rtld_load_library __P((const char *, const Obj_Entry *, int));
/* symbol.c */ /* symbol.c */
unsigned long _rtld_elf_hash __P((const char *)); unsigned long _rtld_elf_hash __P((const char *));
const Elf_Sym *_rtld_symlook_obj __P((const char *, unsigned long, const Elf_Sym *_rtld_symlook_obj __P((const char *, unsigned long,
const Obj_Entry *, bool)); const Obj_Entry *));
const Elf_Sym *_rtld_find_symdef __P((unsigned long, const Obj_Entry *, const Elf_Sym *_rtld_find_symdef __P((unsigned long, const Obj_Entry *,
const Obj_Entry **, bool)); const Obj_Entry **, bool));
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
Objlist *, const Obj_Entry **, bool in_plt); Objlist *, const Obj_Entry **);
/* map_object.c */ /* map_object.c */
Obj_Entry *_rtld_map_object __P((const char *, int, const struct stat *)); Obj_Entry *_rtld_map_object __P((char *, int, const struct stat *));
void _rtld_obj_free(Obj_Entry *); void _rtld_obj_free(Obj_Entry *);
Obj_Entry *_rtld_obj_new(void); Obj_Entry *_rtld_obj_new(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: search.c,v 1.10 2000/07/27 10:44:39 kleink Exp $ */ /* $NetBSD: search.c,v 1.11 2002/09/23 23:56:49 mycroft Exp $ */
/* /*
* Copyright 1996 Matt Thomas <matt@3am-software.com> * Copyright 1996 Matt Thomas <matt@3am-software.com>
@ -55,61 +55,19 @@
/* /*
* Data declarations. * Data declarations.
*/ */
static bool _rtld_check_library __P((const char *)); static Obj_Entry *_rtld_search_library_path __P((const char *, size_t,
static char *_rtld_search_library_path __P((const char *, size_t, const char *, const char *, size_t, int));
size_t));
static bool static Obj_Entry *
_rtld_check_library(pathname) _rtld_search_library_path(name, namelen, dir, dirlen, mode)
const char *pathname;
{
struct stat mystat;
Elf_Ehdr ehdr;
int fd;
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_Ehdr.e_ident includes class */
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
ehdr.e_ident[EI_CLASS] != ELFCLASS)
goto lose;
switch (ehdr.e_machine) {
ELFDEFNNAME(MACHDEP_ID_CASES)
default:
goto lose;
}
if (ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
ehdr.e_version != EV_CURRENT ||
ehdr.e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS) ||
ehdr.e_type != ET_DYN)
goto lose;
close(fd);
return true;
lose:
close(fd);
return false;
}
static char *
_rtld_search_library_path(name, namelen, dir, dirlen)
const char *name; const char *name;
size_t namelen; size_t namelen;
const char *dir; const char *dir;
size_t dirlen; size_t dirlen;
int mode;
{ {
char *pathname; char *pathname;
Obj_Entry *obj;
pathname = xmalloc(dirlen + 1 + namelen + 1); pathname = xmalloc(dirlen + 1 + namelen + 1);
(void)strncpy(pathname, dir, dirlen); (void)strncpy(pathname, dir, dirlen);
@ -117,11 +75,10 @@ _rtld_search_library_path(name, namelen, dir, dirlen)
strcpy(pathname + dirlen + 1, name); strcpy(pathname + dirlen + 1, name);
dbg((" Trying \"%s\"", pathname)); dbg((" Trying \"%s\"", pathname));
if (_rtld_check_library(pathname)) /* We found it */ obj = _rtld_load_object(pathname, mode);
return pathname; if (obj == NULL)
free(pathname);
free(pathname); return obj;
return NULL;
} }
/* /*
@ -132,14 +89,16 @@ _rtld_search_library_path(name, namelen, dir, dirlen)
* If the second argument is non-NULL, then it refers to an already- * If the second argument is non-NULL, then it refers to an already-
* loaded shared object, whose library search path will be searched. * loaded shared object, whose library search path will be searched.
*/ */
char * Obj_Entry *
_rtld_find_library(name, refobj) _rtld_load_library(name, refobj, mode)
const char *name; const char *name;
const Obj_Entry *refobj; const Obj_Entry *refobj;
int mode;
{ {
Search_Path *sp; Search_Path *sp;
char *pathname; char *pathname;
int namelen; int namelen;
Obj_Entry *obj;
if (strchr(name, '/') != NULL) { /* Hard coded pathname */ if (strchr(name, '/') != NULL) { /* Hard coded pathname */
if (name[0] != '/' && !_rtld_trust) { if (name[0] != '/' && !_rtld_trust) {
@ -160,45 +119,39 @@ _rtld_find_library(name, refobj)
(void)strcpy(pathname, LIBDIR); (void)strcpy(pathname, LIBDIR);
(void)strcpy(pathname + LIBDIRLEN, name + (void)strcpy(pathname + LIBDIRLEN, name +
SVR4_LIBDIRLEN); SVR4_LIBDIRLEN);
return pathname; goto found2;
} }
#endif /* SVR4_LIBDIR */ #endif /* SVR4_LIBDIR */
return xstrdup(name); pathname = xstrdup(name);
goto found2;
} }
dbg((" Searching for \"%s\" (%p)", name, refobj)); dbg((" Searching for \"%s\" (%p)", name, refobj));
namelen = strlen(name); namelen = strlen(name);
for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next) for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, namelen, if ((obj = _rtld_search_library_path(name, namelen,
sp->sp_path, sp->sp_pathlen)) != NULL) sp->sp_path, sp->sp_pathlen, mode)) != NULL)
return (pathname); goto found;
if (refobj != NULL) if (refobj != NULL)
for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next) for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, if ((obj = _rtld_search_library_path(name,
namelen, sp->sp_path, sp->sp_pathlen)) != NULL) namelen, sp->sp_path, sp->sp_pathlen, mode)) != NULL)
return (pathname); goto found;
for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next) for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next)
if ((pathname = _rtld_search_library_path(name, namelen, if ((obj = _rtld_search_library_path(name, namelen,
sp->sp_path, sp->sp_pathlen)) != NULL) sp->sp_path, sp->sp_pathlen, mode)) != NULL)
return (pathname); goto found;
#if 0
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
#endif
)
return pathname;
#endif
_rtld_error("Shared object \"%s\" not found", name); _rtld_error("Shared object \"%s\" not found", name);
return NULL; return NULL;
found2:
obj = _rtld_load_object(pathname, mode);
if (obj == NULL)
free(pathname);
found:
return obj;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: symbol.c,v 1.19 2002/09/13 03:40:40 mycroft Exp $ */ /* $NetBSD: symbol.c,v 1.20 2002/09/23 23:56:49 mycroft Exp $ */
/* /*
* Copyright 1996 John D. Polstra. * Copyright 1996 John D. Polstra.
@ -75,7 +75,7 @@ _rtld_elf_hash(name)
const Elf_Sym * const Elf_Sym *
_rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist, _rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist,
const Obj_Entry **defobj_out, bool in_plt) const Obj_Entry **defobj_out)
{ {
const Elf_Sym *symp; const Elf_Sym *symp;
const Elf_Sym *def; const Elf_Sym *def;
@ -85,7 +85,7 @@ _rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist,
def = NULL; def = NULL;
defobj = NULL; defobj = NULL;
SIMPLEQ_FOREACH(elm, objlist, link) { SIMPLEQ_FOREACH(elm, objlist, link) {
if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt)) if ((symp = _rtld_symlook_obj(name, hash, elm->obj))
!= NULL) { != NULL) {
if ((def == NULL) || if ((def == NULL) ||
(ELF_ST_BIND(symp->st_info) != STB_WEAK)) { (ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
@ -110,36 +110,28 @@ _rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist,
* eliminates many recomputations of the hash value. * eliminates many recomputations of the hash value.
*/ */
const Elf_Sym * const Elf_Sym *
_rtld_symlook_obj(name, hash, obj, in_plt) _rtld_symlook_obj(name, hash, obj)
const char *name; const char *name;
unsigned long hash; unsigned long hash;
const Obj_Entry *obj; const Obj_Entry *obj;
bool in_plt;
{ {
unsigned long symnum = obj->buckets[hash % obj->nbuckets]; unsigned long symnum;
while (symnum != ELF_SYM_UNDEFINED) { for (symnum = obj->buckets[hash % obj->nbuckets];
symnum != ELF_SYM_UNDEFINED;
symnum = obj->chains[symnum]) {
const Elf_Sym *symp; const Elf_Sym *symp;
const char *strp; const char *strp;
assert(symnum < obj->nchains); assert(symnum < obj->nchains);
symp = obj->symtab + symnum; symp = obj->symtab + symnum;
strp = obj->strtab + symp->st_name; strp = obj->strtab + symp->st_name;
#if 0 if (name[1] == strp[1] && !strcmp(name, strp)) {
assert(symp->st_name != 0); if (symp->st_shndx != SHN_UNDEF)
#endif
if (strcmp(name, strp) == 0) {
if (symp->st_shndx != SHN_UNDEF
#if !defined(__mips__) /* Following doesn't work on MIPS? mhitch */
|| (!in_plt && symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC)
#endif
)
return symp; return symp;
else else
return NULL; return NULL;
} }
symnum = obj->chains[symnum];
} }
return NULL; return NULL;
@ -175,7 +167,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
defobj = NULL; defobj = NULL;
if (refobj->symbolic) { /* Look first in the referencing object */ if (refobj->symbolic) { /* Look first in the referencing object */
symp = _rtld_symlook_obj(name, hash, refobj, in_plt); symp = _rtld_symlook_obj(name, hash, refobj);
if (symp != NULL) { if (symp != NULL) {
def = symp; def = symp;
defobj = refobj; defobj = refobj;
@ -184,7 +176,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
/* Search all objects loaded at program start up. */ /* Search all objects loaded at program start up. */
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, in_plt); symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj);
if (symp != NULL && if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp; def = symp;
@ -196,8 +188,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { SIMPLEQ_FOREACH(elm, &refobj->dldags, link) {
if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
break; break;
symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, &obj, symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, &obj);
in_plt);
if (symp != NULL && if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp; def = symp;
@ -207,7 +198,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
/* Search all RTLD_GLOBAL objects. */ /* Search all RTLD_GLOBAL objects. */
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
symp = _rtld_symlook_list(name, hash, &_rtld_list_global, &obj, in_plt); symp = _rtld_symlook_list(name, hash, &_rtld_list_global, &obj);
if (symp != NULL && if (symp != NULL &&
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
def = symp; def = symp;