diff options
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ld.elf_so/rtld.c | 19 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.h | 3 | ||||
| -rw-r--r-- | libexec/ld.elf_so/symbol.c | 6 |
3 files changed, 22 insertions, 6 deletions
diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c index bafc6b916f4..84073944cf2 100644 --- a/libexec/ld.elf_so/rtld.c +++ b/libexec/ld.elf_so/rtld.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.c,v 1.178 2016/05/24 20:32:33 christos Exp $ */ +/* $NetBSD: rtld.c,v 1.179 2016/11/30 19:43:32 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: rtld.c,v 1.178 2016/05/24 20:32:33 christos Exp $"); +__RCSID("$NetBSD: rtld.c,v 1.179 2016/11/30 19:43:32 christos Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -1134,6 +1134,21 @@ do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr) break; } } + /* + * Search the dynamic linker itself, and possibly * resolve the symbol from there if it is not defined + * already or weak. This is how the application links + * to dynamic linker services such as dlopen. Only the + * values listed in the "_rtld_exports" array can be + * resolved from the dynamic linker. + */ + if (!def || ELF_ST_BIND(def->st_info) == STB_WEAK) { + const Elf_Sym *symp = _rtld_symlook_obj(name, + hash, &_rtld_objself, flags, ventry); + if (symp != NULL && _rtld_is_exported(symp)) { + def = symp; + defobj = &_rtld_objself; + } + } break; case (intptr_t)RTLD_DEFAULT: diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h index f9d23f9123e..ea2d9117efa 100644 --- a/libexec/ld.elf_so/rtld.h +++ b/libexec/ld.elf_so/rtld.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.125 2016/06/14 13:06:41 christos Exp $ */ +/* $NetBSD: rtld.h,v 1.126 2016/11/30 19:43:32 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -416,6 +416,7 @@ Elf_Addr _rtld_resolve_ifunc(const Obj_Entry *, const Elf_Sym *); Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); /* symbol.c */ +bool _rtld_is_exported(const Elf_Sym *); unsigned long _rtld_elf_hash(const char *); const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, const Obj_Entry *, u_int, const Ver_Entry *); diff --git a/libexec/ld.elf_so/symbol.c b/libexec/ld.elf_so/symbol.c index 4d6033bdc96..ce96425ae15 100644 --- a/libexec/ld.elf_so/symbol.c +++ b/libexec/ld.elf_so/symbol.c @@ -1,4 +1,4 @@ -/* $NetBSD: symbol.c,v 1.65 2014/08/10 23:35:26 matt Exp $ */ +/* $NetBSD: symbol.c,v 1.66 2016/11/30 19:43:32 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: symbol.c,v 1.65 2014/08/10 23:35:26 matt Exp $"); +__RCSID("$NetBSD: symbol.c,v 1.66 2016/11/30 19:43:32 christos Exp $"); #endif /* not lint */ #include <err.h> @@ -80,7 +80,7 @@ _rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) return false; } -static bool +bool _rtld_is_exported(const Elf_Sym *def) { static const fptr_t _rtld_exports[] = { |
