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:
parent
f0efca630a
commit
86103e2f0e
|
@ -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.
|
||||
|
@ -101,9 +101,9 @@ _rtld_load_object(filepath, mode)
|
|||
int fd = -1;
|
||||
struct stat sb;
|
||||
|
||||
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))
|
||||
break;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
return NULL;
|
||||
}
|
||||
obj->path = filepath;
|
||||
_rtld_digest_dynamic(obj);
|
||||
|
||||
*_rtld_objtail = obj;
|
||||
|
@ -170,7 +169,6 @@ _rtld_load_by_name(name, obj, needed, mode)
|
|||
Library_Xform *x = _rtld_xforms;
|
||||
Obj_Entry *o = NULL;
|
||||
size_t i, j;
|
||||
char *libpath;
|
||||
bool got = false;
|
||||
union {
|
||||
int i;
|
||||
|
@ -219,16 +217,13 @@ _rtld_load_by_name(name, obj, needed, mode)
|
|||
* what we loaded in the needed objects */
|
||||
for (j = 0; j < RTLD_MAX_LIBRARY &&
|
||||
x->entry[i].library[j] != NULL; j++) {
|
||||
libpath = _rtld_find_library(
|
||||
x->entry[i].library[j], obj);
|
||||
if (libpath == NULL) {
|
||||
o = _rtld_load_library(x->entry[i].library[j], obj,
|
||||
mode);
|
||||
if (o == NULL) {
|
||||
xwarnx("could not load %s for %s",
|
||||
x->entry[i].library[j], name);
|
||||
continue;
|
||||
}
|
||||
o = _rtld_load_object(libpath, mode);
|
||||
if (o == NULL)
|
||||
continue;
|
||||
got = true;
|
||||
if (j == 0)
|
||||
(*needed)->obj = o;
|
||||
|
@ -249,10 +244,7 @@ _rtld_load_by_name(name, obj, needed, mode)
|
|||
if (got)
|
||||
return true;
|
||||
|
||||
libpath = _rtld_find_library(name, obj);
|
||||
if (libpath == NULL)
|
||||
return false;
|
||||
return ((*needed)->obj = _rtld_load_object(libpath, mode)) != NULL;
|
||||
return ((*needed)->obj = _rtld_load_library(name, obj, mode)) != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -53,7 +53,7 @@ static int protflags __P((int)); /* Elf flags -> mmap protection */
|
|||
*/
|
||||
Obj_Entry *
|
||||
_rtld_map_object(path, fd, sb)
|
||||
const char *path;
|
||||
char *path;
|
||||
int fd;
|
||||
const struct stat *sb;
|
||||
{
|
||||
|
@ -61,8 +61,7 @@ _rtld_map_object(path, fd, sb)
|
|||
union {
|
||||
Elf_Ehdr hdr;
|
||||
char buf[PAGESIZE];
|
||||
} u;
|
||||
int nbytes;
|
||||
} *u;
|
||||
Elf_Phdr *phdr;
|
||||
Elf_Phdr *phlimit;
|
||||
Elf_Phdr *segs[2];
|
||||
|
@ -89,33 +88,34 @@ _rtld_map_object(path, fd, sb)
|
|||
size_t nclear;
|
||||
#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));
|
||||
return NULL;
|
||||
}
|
||||
/* Make sure the file is valid */
|
||||
if (nbytes < sizeof(Elf_Ehdr) ||
|
||||
memcmp(ELFMAG, u.hdr.e_ident, SELFMAG) != 0 ||
|
||||
u.hdr.e_ident[EI_CLASS] != ELFCLASS) {
|
||||
if (memcmp(ELFMAG, u->hdr.e_ident, SELFMAG) != 0 ||
|
||||
u->hdr.e_ident[EI_CLASS] != ELFCLASS) {
|
||||
_rtld_error("%s: unrecognized file format", path);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
/* Elf_e_ident includes class */
|
||||
if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
u.hdr.e_version != EV_CURRENT ||
|
||||
u.hdr.e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
|
||||
_rtld_error("%s: Unsupported file version", path);
|
||||
return NULL;
|
||||
if (u->hdr.e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
u->hdr.e_version != EV_CURRENT ||
|
||||
u->hdr.e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) {
|
||||
_rtld_error("%s: unsupported file version", path);
|
||||
goto bad;
|
||||
}
|
||||
if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) {
|
||||
_rtld_error("%s: Unsupported file type", path);
|
||||
return NULL;
|
||||
if (u->hdr.e_type != ET_EXEC && u->hdr.e_type != ET_DYN) {
|
||||
_rtld_error("%s: unsupported file type", path);
|
||||
goto bad;
|
||||
}
|
||||
switch (u.hdr.e_machine) {
|
||||
switch (u->hdr.e_machine) {
|
||||
ELFDEFNNAME(MACHDEP_ID_CASES)
|
||||
default:
|
||||
_rtld_error("%s: Unsupported machine", path);
|
||||
return NULL;
|
||||
_rtld_error("%s: unsupported machine", path);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -123,9 +123,8 @@ _rtld_map_object(path, fd, sb)
|
|||
* 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);
|
||||
assert(u->hdr.e_phentsize == sizeof(Elf_Phdr));
|
||||
assert(u->hdr.e_phoff + u->hdr.e_phnum * sizeof(Elf_Phdr) <= PAGESIZE);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
* in that order.
|
||||
*/
|
||||
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
|
||||
phlimit = phdr + u.hdr.e_phnum;
|
||||
phdr = (Elf_Phdr *) (u->buf + u->hdr.e_phoff);
|
||||
phlimit = phdr + u->hdr.e_phnum;
|
||||
nsegs = 0;
|
||||
phdyn = phphdr = phinterp = NULL;
|
||||
while (phdr < phlimit) {
|
||||
|
@ -162,12 +161,12 @@ _rtld_map_object(path, fd, sb)
|
|||
}
|
||||
if (phdyn == NULL) {
|
||||
_rtld_error("%s: not dynamically linked", path);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
if (nsegs != 2) {
|
||||
_rtld_error("%s: wrong number of segments (%d != 2)", path,
|
||||
nsegs);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -189,7 +188,7 @@ _rtld_map_object(path, fd, sb)
|
|||
mapsize = base_vlimit - base_vaddr;
|
||||
|
||||
#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
|
||||
base_addr = NULL;
|
||||
#endif
|
||||
|
@ -199,7 +198,7 @@ _rtld_map_object(path, fd, sb)
|
|||
if (mapbase == MAP_FAILED) {
|
||||
_rtld_error("mmap of entire address space failed: %s",
|
||||
xstrerror(errno));
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
base_addr = mapbase;
|
||||
|
@ -215,7 +214,7 @@ _rtld_map_object(path, fd, sb)
|
|||
== MAP_FAILED) {
|
||||
_rtld_error("mmap of data failed: %s", xstrerror(errno));
|
||||
munmap(mapbase, mapsize);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Overlay the bss segment onto the proper region. */
|
||||
|
@ -225,7 +224,7 @@ _rtld_map_object(path, fd, sb)
|
|||
== MAP_FAILED) {
|
||||
_rtld_error("mmap of bss failed: %s", xstrerror(errno));
|
||||
munmap(mapbase, mapsize);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* 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",
|
||||
xstrerror(errno));
|
||||
munmap(mapbase, mapsize);
|
||||
return NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
#ifdef RTLD_LOADER
|
||||
|
@ -249,6 +248,7 @@ _rtld_map_object(path, fd, sb)
|
|||
#endif
|
||||
|
||||
obj = _rtld_obj_new();
|
||||
obj->path = path;
|
||||
if (sb != NULL) {
|
||||
obj->dev = sb->st_dev;
|
||||
obj->ino = sb->st_ino;
|
||||
|
@ -260,8 +260,8 @@ _rtld_map_object(path, fd, sb)
|
|||
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 (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);
|
||||
|
@ -269,9 +269,13 @@ _rtld_map_object(path, fd, sb)
|
|||
}
|
||||
if (phinterp != NULL)
|
||||
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;
|
||||
|
||||
bad:
|
||||
munmap(u, PAGESIZE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -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.
|
||||
|
@ -79,8 +79,7 @@ _rtld_do_copy_relocation(dstobj, rela)
|
|||
Obj_Entry *srcobj;
|
||||
|
||||
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
|
||||
if ((srcsym = _rtld_symlook_obj(name, hash, srcobj,
|
||||
false)) != NULL)
|
||||
if ((srcsym = _rtld_symlook_obj(name, hash, srcobj)) != NULL)
|
||||
break;
|
||||
|
||||
if (srcobj == NULL) {
|
||||
|
@ -236,6 +235,7 @@ _rtld_relocate_objects(first, bind_now, self)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
dbg(("a\n"));
|
||||
if (_rtld_relocate_nonplt_objects(obj, self) < 0)
|
||||
ok = 0;
|
||||
if (obj->textrel) { /* Re-protected the text segment. */
|
||||
|
@ -246,6 +246,7 @@ _rtld_relocate_objects(first, bind_now, self)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
dbg(("b\n"));
|
||||
if (_rtld_relocate_plt_lazy(obj) < 0)
|
||||
ok = 0;
|
||||
#if defined(__i386__)
|
||||
|
@ -268,6 +269,7 @@ _rtld_relocate_objects(first, bind_now, self)
|
|||
obj->dlclose = _rtld_dlclose;
|
||||
obj->dladdr = _rtld_dladdr;
|
||||
|
||||
dbg(("c\n"));
|
||||
/* Set the special PLTGOT entries. */
|
||||
if (obj->pltgot != NULL)
|
||||
_rtld_setup_pltgot(obj);
|
||||
|
|
|
@ -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.
|
||||
|
@ -418,7 +418,8 @@ _rtld(sp, relocbase)
|
|||
if (pAUX_execfd != NULL) { /* Load the main program. */
|
||||
int fd = pAUX_execfd->a_v;
|
||||
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);
|
||||
if (_rtld_objmain == NULL)
|
||||
_rtld_die();
|
||||
|
@ -439,10 +440,6 @@ _rtld(sp, relocbase)
|
|||
_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;
|
||||
|
||||
/*
|
||||
|
@ -690,11 +687,8 @@ _rtld_dlopen(name, mode)
|
|||
if (name == NULL) {
|
||||
obj = _rtld_objmain;
|
||||
obj->refcount++;
|
||||
} else {
|
||||
char *path = _rtld_find_library(name, _rtld_objmain);
|
||||
if (path != NULL)
|
||||
obj = _rtld_load_object(path, mode);
|
||||
}
|
||||
} else
|
||||
obj = _rtld_load_library(name, _rtld_objmain, mode);
|
||||
|
||||
if (obj != NULL) {
|
||||
++obj->dl_refcount;
|
||||
|
@ -732,7 +726,7 @@ _rtld_objmain_sym(name)
|
|||
hash = _rtld_elf_hash(name);
|
||||
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)
|
||||
return obj->relocbase + def->st_value;
|
||||
|
@ -766,11 +760,11 @@ _rtld_dlsym(handle, name)
|
|||
return NULL;
|
||||
}
|
||||
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;
|
||||
} else { /* All the shared objects after the caller's */
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -782,13 +776,13 @@ _rtld_dlsym(handle, name)
|
|||
|
||||
if (obj->mainprog) {
|
||||
/* 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 {
|
||||
/*
|
||||
* XXX - This isn't correct. The search should include the whole
|
||||
* DAG rooted at the given object.
|
||||
*/
|
||||
def = _rtld_symlook_obj(name, hash, obj, true);
|
||||
def = _rtld_symlook_obj(name, hash, obj);
|
||||
defobj = obj;
|
||||
}
|
||||
}
|
||||
|
@ -943,18 +937,12 @@ _rtld_linkmap_delete(obj)
|
|||
static Obj_Entry *
|
||||
_rtld_obj_from_addr(const void *addr)
|
||||
{
|
||||
unsigned long endhash;
|
||||
Obj_Entry *obj;
|
||||
|
||||
endhash = _rtld_elf_hash(END_SYM);
|
||||
for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
|
||||
const Elf_Sym *endsym;
|
||||
|
||||
if (addr < (void *) obj->mapbase)
|
||||
continue;
|
||||
if ((endsym = _rtld_symlook_obj(END_SYM, endhash, obj, true)) == NULL)
|
||||
continue; /* No "end" symbol?! */
|
||||
if (addr < (void *) (obj->relocbase + endsym->st_value))
|
||||
if (addr < (void *) (obj->mapbase + obj->mapsize))
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -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.
|
||||
|
@ -269,19 +269,19 @@ int _rtld_relocate_plt_objects __P((const Obj_Entry *));
|
|||
void _rtld_setup_pltgot __P((const Obj_Entry *));
|
||||
|
||||
/* 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 */
|
||||
unsigned long _rtld_elf_hash __P((const char *));
|
||||
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 Obj_Entry **, bool));
|
||||
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
|
||||
Objlist *, const Obj_Entry **, bool in_plt);
|
||||
Objlist *, const Obj_Entry **);
|
||||
|
||||
/* 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 *);
|
||||
Obj_Entry *_rtld_obj_new(void);
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -55,61 +55,19 @@
|
|||
/*
|
||||
* 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 Obj_Entry *_rtld_search_library_path __P((const char *, size_t,
|
||||
const char *, size_t, int));
|
||||
|
||||
static bool
|
||||
_rtld_check_library(pathname)
|
||||
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)
|
||||
static Obj_Entry *
|
||||
_rtld_search_library_path(name, namelen, dir, dirlen, mode)
|
||||
const char *name;
|
||||
size_t namelen;
|
||||
const char *dir;
|
||||
size_t dirlen;
|
||||
int mode;
|
||||
{
|
||||
char *pathname;
|
||||
Obj_Entry *obj;
|
||||
|
||||
pathname = xmalloc(dirlen + 1 + namelen + 1);
|
||||
(void)strncpy(pathname, dir, dirlen);
|
||||
|
@ -117,11 +75,10 @@ _rtld_search_library_path(name, namelen, dir, dirlen)
|
|||
strcpy(pathname + dirlen + 1, name);
|
||||
|
||||
dbg((" Trying \"%s\"", pathname));
|
||||
if (_rtld_check_library(pathname)) /* We found it */
|
||||
return pathname;
|
||||
|
||||
free(pathname);
|
||||
return NULL;
|
||||
obj = _rtld_load_object(pathname, mode);
|
||||
if (obj == NULL)
|
||||
free(pathname);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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-
|
||||
* loaded shared object, whose library search path will be searched.
|
||||
*/
|
||||
char *
|
||||
_rtld_find_library(name, refobj)
|
||||
Obj_Entry *
|
||||
_rtld_load_library(name, refobj, mode)
|
||||
const char *name;
|
||||
const Obj_Entry *refobj;
|
||||
int mode;
|
||||
{
|
||||
Search_Path *sp;
|
||||
char *pathname;
|
||||
int namelen;
|
||||
Obj_Entry *obj;
|
||||
|
||||
if (strchr(name, '/') != NULL) { /* Hard coded pathname */
|
||||
if (name[0] != '/' && !_rtld_trust) {
|
||||
|
@ -160,45 +119,39 @@ _rtld_find_library(name, refobj)
|
|||
(void)strcpy(pathname, LIBDIR);
|
||||
(void)strcpy(pathname + LIBDIRLEN, name +
|
||||
SVR4_LIBDIRLEN);
|
||||
return pathname;
|
||||
goto found2;
|
||||
}
|
||||
#endif /* SVR4_LIBDIR */
|
||||
return xstrdup(name);
|
||||
pathname = xstrdup(name);
|
||||
goto found2;
|
||||
}
|
||||
dbg((" Searching for \"%s\" (%p)", name, refobj));
|
||||
|
||||
namelen = strlen(name);
|
||||
|
||||
for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
|
||||
if ((pathname = _rtld_search_library_path(name, namelen,
|
||||
sp->sp_path, sp->sp_pathlen)) != NULL)
|
||||
return (pathname);
|
||||
if ((obj = _rtld_search_library_path(name, namelen,
|
||||
sp->sp_path, sp->sp_pathlen, mode)) != NULL)
|
||||
goto found;
|
||||
|
||||
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 ((obj = _rtld_search_library_path(name,
|
||||
namelen, sp->sp_path, sp->sp_pathlen, mode)) != NULL)
|
||||
goto found;
|
||||
|
||||
for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next)
|
||||
if ((pathname = _rtld_search_library_path(name, namelen,
|
||||
sp->sp_path, sp->sp_pathlen)) != NULL)
|
||||
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
|
||||
#ifdef SVR4_LIBDIR
|
||||
LOSE !
|
||||
||(pathname = _rtld_search_library_path(name, SVR4_LIBDIR)) != NULL
|
||||
#endif
|
||||
)
|
||||
return pathname;
|
||||
#endif
|
||||
if ((obj = _rtld_search_library_path(name, namelen,
|
||||
sp->sp_path, sp->sp_pathlen, mode)) != NULL)
|
||||
goto found;
|
||||
|
||||
_rtld_error("Shared object \"%s\" not found", name);
|
||||
return NULL;
|
||||
|
||||
found2:
|
||||
obj = _rtld_load_object(pathname, mode);
|
||||
if (obj == NULL)
|
||||
free(pathname);
|
||||
found:
|
||||
return obj;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -75,7 +75,7 @@ _rtld_elf_hash(name)
|
|||
|
||||
const Elf_Sym *
|
||||
_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 *def;
|
||||
|
@ -85,7 +85,7 @@ _rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist,
|
|||
def = NULL;
|
||||
defobj = NULL;
|
||||
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) {
|
||||
if ((def == NULL) ||
|
||||
(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.
|
||||
*/
|
||||
const Elf_Sym *
|
||||
_rtld_symlook_obj(name, hash, obj, in_plt)
|
||||
_rtld_symlook_obj(name, hash, obj)
|
||||
const char *name;
|
||||
unsigned long hash;
|
||||
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 char *strp;
|
||||
|
||||
assert(symnum < obj->nchains);
|
||||
symp = obj->symtab + symnum;
|
||||
strp = obj->strtab + symp->st_name;
|
||||
#if 0
|
||||
assert(symp->st_name != 0);
|
||||
#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
|
||||
)
|
||||
if (name[1] == strp[1] && !strcmp(name, strp)) {
|
||||
if (symp->st_shndx != SHN_UNDEF)
|
||||
return symp;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
symnum = obj->chains[symnum];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -175,7 +167,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
|
|||
defobj = NULL;
|
||||
|
||||
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) {
|
||||
def = symp;
|
||||
defobj = refobj;
|
||||
|
@ -184,7 +176,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
|
|||
|
||||
/* Search all objects loaded at program start up. */
|
||||
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 &&
|
||||
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
|
||||
def = symp;
|
||||
|
@ -196,8 +188,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
|
|||
SIMPLEQ_FOREACH(elm, &refobj->dldags, link) {
|
||||
if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
|
||||
break;
|
||||
symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, &obj,
|
||||
in_plt);
|
||||
symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, &obj);
|
||||
if (symp != NULL &&
|
||||
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
|
||||
def = symp;
|
||||
|
@ -207,7 +198,7 @@ _rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
|
|||
|
||||
/* Search all RTLD_GLOBAL objects. */
|
||||
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 &&
|
||||
(def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
|
||||
def = symp;
|
||||
|
|
Loading…
Reference in New Issue