summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordrahn <drahn@openbsd.org>2003-09-04 19:33:48 +0000
committerdrahn <drahn@openbsd.org>2003-09-04 19:33:48 +0000
commitc9cd759c43d2c3c7b96205483592fb5150ff31b3 (patch)
tree193f226c3fef4300494456f42771aa61c65b6d0e
parentWhat I blamed on a specific CMMU fault pecularity turned out to be, in fact, (diff)
downloadwireguard-openbsd-c9cd759c43d2c3c7b96205483592fb5150ff31b3.tar.xz
wireguard-openbsd-c9cd759c43d2c3c7b96205483592fb5150ff31b3.zip
Symbol cache for GOT lookup. When a symbol is found it is saved in a cache
for future lookups in the same GOT relocation table. Uses static buffer for small symbol tables, mmap for larger ones. ok deraadt@
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c12
-rw-r--r--libexec/ld.so/dlfcn.c9
-rw-r--r--libexec/ld.so/i386/rtld_machine.c7
-rw-r--r--libexec/ld.so/loader.c32
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c16
-rw-r--r--libexec/ld.so/resolve.c41
-rw-r--r--libexec/ld.so/resolve.h13
-rw-r--r--libexec/ld.so/sparc/rtld_machine.c7
-rw-r--r--libexec/ld.so/sparc64/rtld_machine.c14
9 files changed, 123 insertions, 28 deletions
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c
index 8a2c61b9230..5dfd9864f13 100644
--- a/libexec/ld.so/alpha/rtld_machine.c
+++ b/libexec/ld.so/alpha/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.26 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.27 2003/09/04 19:33:49 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -107,9 +107,10 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
this = NULL;
switch (ELF64_R_TYPE(relas->r_info)) {
case R_TYPE(REFQUAD):
- ooff = _dl_find_symbol(symn, _dl_objects, &this,
+ ooff = _dl_find_symbol_bysym(object,
+ ELF64_R_SYM(relas->r_info), _dl_objects, &this,
SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
- sym->st_size, object);
+ sym->st_size);
if (this == NULL)
goto resolve_failed;
*r_addr += ooff + this->st_value + relas->r_addend;
@@ -140,9 +141,10 @@ _dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr,
*r_addr = ooff + this->st_value + relas->r_addend;
break;
case R_TYPE(GLOB_DAT):
- ooff = _dl_find_symbol(symn, _dl_objects, &this,
+ ooff = _dl_find_symbol_bysym(object,
+ ELF64_R_SYM(relas->r_info), _dl_objects, &this,
SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
- sym->st_size, object);
+ sym->st_size);
if (this == NULL)
goto resolve_failed;
*r_addr = ooff + this->st_value + relas->r_addend;
diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c
index b1e03fcca79..752c70a2085 100644
--- a/libexec/ld.so/dlfcn.c
+++ b/libexec/ld.so/dlfcn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dlfcn.c,v 1.30 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: dlfcn.c,v 1.31 2003/09/04 19:33:48 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -304,6 +304,13 @@ _dl_show_objects(void)
objtypename, object->refcount, object->load_name);
object = object->next;
}
+ {
+ extern int _dl_symcachestat_hits;
+ extern int _dl_symcachestat_lookups;
+ DL_DEB(("symcache lookups %d hits %d ratio %d% hits\n",
+ _dl_symcachestat_lookups, _dl_symcachestat_hits,
+ (_dl_symcachestat_hits * 100) / _dl_symcachestat_lookups));
+ }
}
static void
diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c
index 971c1a9ea3e..326321ef763 100644
--- a/libexec/ld.so/i386/rtld_machine.c
+++ b/libexec/ld.so/i386/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.11 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.12 2003/09/04 19:33:49 drahn Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -237,11 +237,12 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
value += loff;
} else {
this = NULL;
- ooff = _dl_find_symbol(symn, _dl_objects,
+ ooff = _dl_find_symbol_bysym(object,
+ ELF_R_SYM(rels->r_info), _dl_objects,
&this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
((type == R_TYPE(JUMP_SLOT))?
SYM_PLT:SYM_NOTPLT),
- sym->st_size, object);
+ sym->st_size);
if (this == NULL) {
resolve_failed:
_dl_printf("%s: %s: can't resolve "
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index a6d77780a1f..dac1f42f17b 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.67 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: loader.c,v 1.68 2003/09/04 19:33:48 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -42,6 +42,7 @@
#include "archdep.h"
#include "resolve.h"
#include "sod.h"
+#include "stdlib.h"
/*
* Local decls.
@@ -599,21 +600,50 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
*/
}
+#define DL_SM_SYMBUF_CNT 512
+sym_cache _dl_sm_symcache_buffer[DL_SM_SYMBUF_CNT];
+
void
_dl_rtld(elf_object_t *object)
{
+ size_t sz;
if (object->next)
_dl_rtld(object->next);
if (object->status & STAT_RELOC_DONE)
return;
+ sz = 0;
+ if (object->nchains < DL_SM_SYMBUF_CNT) {
+ _dl_symcache = _dl_sm_symcache_buffer;
+ DL_DEB(("using static buffer for %d entries\n",
+ object->nchains));
+ _dl_memset(_dl_symcache, 0,
+ sizeof (sym_cache) * object->nchains);
+ } else {
+ sz = ELF_ROUND(sizeof (sym_cache) * object->nchains,
+ _dl_pagesz);
+ DL_DEB(("allocating symcache sz %x with mmap\n", sz));
+
+ _dl_symcache = (void *)_dl_mmap(0, sz, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (_dl_symcache == (void *)MAP_FAILED) {
+ sz = 0;
+ _dl_symcache = NULL;
+ }
+ }
/*
* Do relocation information first, then GOT.
*/
_dl_md_reloc(object, DT_REL, DT_RELSZ);
_dl_md_reloc(object, DT_RELA, DT_RELASZ);
_dl_md_reloc_got(object, !(_dl_bindnow || object->dyn.bind_now));
+
+ if (_dl_symcache != NULL) {
+ if (sz != 0)
+ _dl_munmap( _dl_symcache, sz);
+ _dl_symcache = NULL;
+ }
object->status |= STAT_RELOC_DONE;
}
diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c
index bd4f2040e94..3500e888f53 100644
--- a/libexec/ld.so/powerpc/rtld_machine.c
+++ b/libexec/ld.so/powerpc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.30 2003/09/02 15:17:52 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.31 2003/09/04 19:33:49 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -204,10 +204,11 @@ _dl_printf("object relocation size %x, numrela %x\n",
if (ELF32_R_SYM(relas->r_info) &&
!(ELF32_ST_BIND(sym->st_info) == STB_LOCAL &&
ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) {
- ooff = _dl_find_symbol(symn, _dl_objects, &this,
- SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|
+ ooff = _dl_find_symbol_bysym(object,
+ ELF32_R_SYM(relas->r_info), _dl_objects,
+ &this, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|
((type == RELOC_JMP_SLOT) ? SYM_PLT:SYM_NOTPLT),
- sym->st_size, object);
+ sym->st_size);
if (!this && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) {
_dl_printf("%s: %s :can't resolve reference '%s'\n",
@@ -393,12 +394,13 @@ _dl_printf(" symn [%s] val 0x%x\n", symn, val);
cobj = cobj->next) {
if (object != cobj) {
/* only look in this object */
- src_loff = _dl_find_symbol(symn, cobj,
- &cpysrc,
+ src_loff = _dl_find_symbol_bysym(object,
+ ELF32_R_SYM(relas->r_info),
+ cobj, &cpysrc,
SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|
((type == RELOC_JMP_SLOT) ?
SYM_PLT : SYM_NOTPLT),
- sym->st_size, object);
+ sym->st_size);
}
}
if (cpysrc == NULL) {
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 07b464ff2cf..f08b07707c8 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.20 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: resolve.c,v 1.21 2003/09/04 19:33:48 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -188,6 +188,45 @@ int find_symbol_obj(elf_object_t *object, const char *name, unsigned long hash,
int flags, const Elf_Sym **ref, const Elf_Sym **weak_sym,
elf_object_t **weak_object);
+sym_cache *_dl_symcache;
+int _dl_symcachestat_hits;
+int _dl_symcachestat_lookups;
+
+Elf_Addr
+_dl_find_symbol_bysym(elf_object_t *req_obj, unsigned int symidx,
+ elf_object_t *startlook, const Elf_Sym **ref, int flags, int req_size)
+{
+ Elf_Addr ret;
+ const Elf_Sym *sym;
+ const char *symn;
+
+ _dl_symcachestat_lookups ++;
+ if ((_dl_symcache != NULL) &&
+ (symidx < req_obj->nchains) &&
+ (_dl_symcache[symidx].sym != NULL) &&
+ (_dl_symcache[symidx].flags == flags)) {
+
+ _dl_symcachestat_hits++;
+ *ref = _dl_symcache[symidx].sym;
+ return _dl_symcache[symidx].offset;
+ }
+
+ sym = req_obj->dyn.symtab;
+ sym += symidx;
+ symn = req_obj->dyn.strtab + sym->st_name;
+
+ ret = _dl_find_symbol(symn, startlook, ref, flags, req_size, req_obj);
+
+ if ((_dl_symcache != NULL) &&
+ (symidx < req_obj->nchains)) {
+ _dl_symcache[symidx].sym = *ref;
+ _dl_symcache[symidx].offset = ret;
+ _dl_symcache[symidx].flags = flags;
+ }
+
+ return ret;
+}
+
Elf_Addr
_dl_find_symbol(const char *name, elf_object_t *startlook,
const Elf_Sym **ref, int flags, int req_size, elf_object_t *req_obj)
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index e5b31ae562b..49c0e6f6740 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.28 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: resolve.h,v 1.29 2003/09/04 19:33:48 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -145,6 +145,8 @@ extern void _dl_md_reloc_got(elf_object_t *object, int lazy);
Elf_Addr _dl_find_symbol(const char *name, elf_object_t *startlook,
const Elf_Sym **ref, int flags, int sym_size, elf_object_t *object);
+Elf_Addr _dl_find_symbol_bysym(elf_object_t *req_obj, unsigned int symidx,
+ elf_object_t *startlook, const Elf_Sym **ref, int flags, int req_size);
/*
* defines for _dl_find_symbol() flag field, three bits of meaning
* myself - clear: search all objects, set: search only this object
@@ -209,4 +211,13 @@ extern char *_dl_debug;
#define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1))
#define ELF_TRUNC(x,malign) ((x) & ~((malign)-1))
+/* symbol lookup cache */
+typedef struct sym_cache {
+ const Elf_Sym *sym;
+ Elf_Addr offset;
+ int flags;
+} sym_cache;
+
+extern sym_cache *_dl_symcache;
+
#endif /* _RESOLVE_H_ */
diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c
index c39b6886ed2..3ec0a6705df 100644
--- a/libexec/ld.so/sparc/rtld_machine.c
+++ b/libexec/ld.so/sparc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.18 2003/09/02 15:17:52 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.19 2003/09/04 19:33:49 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -251,12 +251,13 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
value += loff;
} else {
this = NULL;
- ooff = _dl_find_symbol(symn,
+ ooff = _dl_find_symbol_bysym(object,
+ ELF_R_SYM(relas->r_info),
_dl_objects, &this,
SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
((type == R_TYPE(JMP_SLOT)) ?
SYM_PLT : SYM_NOTPLT),
- sym->st_size, object);
+ sym->st_size);
if (this == NULL) {
resolve_failed:
_dl_printf("%s: %s: can't resolve "
diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c
index dbdf035323c..9e4fa21efed 100644
--- a/libexec/ld.so/sparc64/rtld_machine.c
+++ b/libexec/ld.so/sparc64/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.29 2003/09/02 15:17:52 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.30 2003/09/04 19:33:50 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -272,11 +272,13 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
value += loff;
} else {
this = NULL;
- ooff = _dl_find_symbol(symn, _dl_objects,
- &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
- ((type == R_TYPE(JMP_SLOT))?
- SYM_PLT:SYM_NOTPLT),
- sym->st_size, object);
+ ooff = _dl_find_symbol_bysym(object,
+ ELF_R_SYM(relas->r_info),
+ _dl_objects, &this,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
+ ((type == R_TYPE(JMP_SLOT)) ?
+ SYM_PLT : SYM_NOTPLT),
+ sym->st_size);
if (this == NULL) {
resolve_failed:
_dl_printf("%s: %s: can't resolve "