diff options
author | 2003-09-04 19:33:48 +0000 | |
---|---|---|
committer | 2003-09-04 19:33:48 +0000 | |
commit | c9cd759c43d2c3c7b96205483592fb5150ff31b3 (patch) | |
tree | 193f226c3fef4300494456f42771aa61c65b6d0e | |
parent | What I blamed on a specific CMMU fault pecularity turned out to be, in fact, (diff) | |
download | wireguard-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.c | 12 | ||||
-rw-r--r-- | libexec/ld.so/dlfcn.c | 9 | ||||
-rw-r--r-- | libexec/ld.so/i386/rtld_machine.c | 7 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 32 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 16 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 41 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 13 | ||||
-rw-r--r-- | libexec/ld.so/sparc/rtld_machine.c | 7 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/rtld_machine.c | 14 |
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 " |