summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/rtld-elf/rtld.c')
-rw-r--r--libexec/rtld-elf/rtld.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 0cffa74..4e907f3 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -427,7 +427,7 @@ _rtld_bind(Obj_Entry *obj, Elf_Word reloff)
rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
- def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL);
if (def == NULL)
die();
@@ -821,7 +821,7 @@ find_library(const char *name, const Obj_Entry *refobj)
*/
const Elf_Sym *
find_symdef(unsigned long symnum, const Obj_Entry *refobj,
- const Obj_Entry **defobj_out, bool in_plt)
+ const Obj_Entry **defobj_out, bool in_plt, SymCache *cache)
{
const Elf_Sym *ref;
const Elf_Sym *def;
@@ -829,6 +829,17 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
const char *name;
unsigned long hash;
+ /*
+ * If we have already found this symbol, get the information from
+ * the cache.
+ */
+ if (symnum >= refobj->nchains)
+ return NULL; /* Bad object */
+ if (cache != NULL && cache[symnum].sym != NULL) {
+ *defobj_out = cache[symnum].obj;
+ return cache[symnum].sym;
+ }
+
ref = refobj->symtab + symnum;
name = refobj->strtab + ref->st_name;
hash = elf_hash(name);
@@ -845,9 +856,14 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
defobj = obj_main;
}
- if (def != NULL)
+ if (def != NULL) {
*defobj_out = defobj;
- else
+ /* Record the information in the cache to avoid subsequent lookups. */
+ if (cache != NULL) {
+ cache[symnum].sym = def;
+ cache[symnum].obj = defobj;
+ }
+ } else
_rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name);
return def;
}
@@ -1926,7 +1942,7 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
symp = obj->symtab + symnum;
strp = obj->strtab + symp->st_name;
- if (strcmp(name, strp) == 0)
+ if (name[0] == strp[0] && strcmp(name, strp) == 0)
return symp->st_shndx != SHN_UNDEF ||
(!in_plt && symp->st_value != 0 &&
ELF_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL;
OpenPOWER on IntegriCloud