summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.elf_so/rtld.c19
-rw-r--r--libexec/ld.elf_so/rtld.h3
-rw-r--r--libexec/ld.elf_so/symbol.c6
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[] = {