Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so Separate matched symbol functionality out ...
details: https://anonhg.NetBSD.org/src/rev/682ffebc7665
branches: trunk
changeset: 969716:682ffebc7665
user: kamil <kamil%NetBSD.org@localhost>
date: Sat Feb 29 04:21:42 2020 +0000
description:
Separate matched symbol functionality out of _rtld_symlook_obj()
Simplifies the code and it will allow to use the matched symbol
functionality by other users.
diffstat:
libexec/ld.elf_so/symbol.c | 221 ++++++++++++++++++++++++--------------------
1 files changed, 118 insertions(+), 103 deletions(-)
diffs (257 lines):
diff -r 7aef404f9cdf -r 682ffebc7665 libexec/ld.elf_so/symbol.c
--- a/libexec/ld.elf_so/symbol.c Sat Feb 29 04:02:06 2020 +0000
+++ b/libexec/ld.elf_so/symbol.c Sat Feb 29 04:21:42 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: symbol.c,v 1.69 2017/08/09 18:44:32 joerg Exp $ */
+/* $NetBSD: symbol.c,v 1.70 2020/02/29 04:21:42 kamil Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.69 2017/08/09 18:44:32 joerg Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.70 2020/02/29 04:21:42 kamil Exp $");
#endif /* not lint */
#include <err.h>
@@ -193,6 +193,119 @@
return def;
}
+static bool
+_rtld_symlook_obj_matched_symbol(const char *name,
+ const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry,
+ unsigned long symnum, const Elf_Sym **vsymp, int *vcount)
+{
+ const Elf_Sym *symp;
+ const char *strp;
+ Elf_Half verndx;
+
+ symp = obj->symtab + symnum;
+ strp = obj->strtab + symp->st_name;
+ rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path));
+ if (name[1] != strp[1] || strcmp(name, strp))
+ return false;
+#if defined(__mips__) || defined(__vax__)
+ if (symp->st_shndx == SHN_UNDEF)
+ continue;
+#else
+ /*
+ * XXX DANGER WILL ROBINSON!
+ * If we have a function pointer in the executable's
+ * data section, it points to the executable's PLT
+ * slot, and there is NO relocation emitted. To make
+ * the function pointer comparable to function pointers
+ * in shared libraries, we must resolve data references
+ * in the libraries to point to PLT slots in the
+ * executable, if they exist.
+ */
+ if (symp->st_shndx == SHN_UNDEF &&
+ ((flags & SYMLOOK_IN_PLT) ||
+ symp->st_value == 0 ||
+ ELF_ST_TYPE(symp->st_info) != STT_FUNC))
+ return false;
+#endif
+
+ if (ventry == NULL) {
+ if (obj->versyms != NULL) {
+ verndx = VER_NDX(obj->versyms[symnum].vs_vers);
+ if (verndx > obj->vertabnum) {
+ _rtld_error("%s: symbol %s references "
+ "wrong version %d", obj->path,
+ &obj->strtab[symnum], verndx);
+ return false;
+ }
+
+ /*
+ * If we are not called from dlsym (i.e. this
+ * is a normal relocation from unversioned
+ * binary), accept the symbol immediately
+ * if it happens to have first version after
+ * this shared object became versioned.
+ * Otherwise, if symbol is versioned and not
+ * hidden, remember it. If it is the only
+ * symbol with this name exported by the shared
+ * object, it will be returned as a match at the
+ * end of the function. If symbol is global
+ * (verndx < 2) accept it unconditionally.
+ */
+ if (!(flags & SYMLOOK_DLSYM) &&
+ verndx == VER_NDX_GIVEN) {
+ *vsymp = symp;
+ return true;
+ } else if (verndx >= VER_NDX_GIVEN) {
+ if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) {
+ if (*vsymp == NULL)
+ *vsymp = symp;
+ (*vcount)++;
+ }
+ return false;
+ }
+ }
+ *vsymp = symp;
+ return true;
+ } else {
+ if (obj->versyms == NULL) {
+ if (_rtld_object_match_name(obj, ventry->name)){
+ _rtld_error("%s: object %s should "
+ "provide version %s for symbol %s",
+ _rtld_objself.path, obj->path,
+ ventry->name, &obj->strtab[symnum]);
+ return false;
+ }
+ } else {
+ verndx = VER_NDX(obj->versyms[symnum].vs_vers);
+ if (verndx > obj->vertabnum) {
+ _rtld_error("%s: symbol %s references "
+ "wrong version %d", obj->path,
+ &obj->strtab[symnum], verndx);
+ return false;
+ }
+ if (obj->vertab[verndx].hash != ventry->hash ||
+ strcmp(obj->vertab[verndx].name, ventry->name)) {
+ /*
+ * Version does not match. Look if this
+ * is a global symbol and if it is not
+ * hidden. If global symbol (verndx < 2)
+ * is available, use it. Do not return
+ * symbol if we are called by dlvsym,
+ * because dlvsym looks for a specific
+ * version and default one is not what
+ * dlvsym wants.
+ */
+ if ((flags & SYMLOOK_DLSYM) ||
+ (obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) ||
+ (verndx >= VER_NDX_GIVEN))
+ return false;
+ }
+ }
+ *vsymp = symp;
+ return true;
+ }
+}
+
/*
* Search the symbol table of a single shared object for a symbol of
* the given name. Returns a pointer to the symbol, or NULL if no
@@ -207,115 +320,17 @@
{
unsigned long symnum;
const Elf_Sym *vsymp = NULL;
- Elf_Half verndx;
int vcount = 0;
for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets,
obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)];
symnum != ELF_SYM_UNDEFINED;
symnum = obj->chains[symnum]) {
- const Elf_Sym *symp;
- const char *strp;
-
assert(symnum < obj->nchains);
- symp = obj->symtab + symnum;
- strp = obj->strtab + symp->st_name;
- rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path));
- if (name[1] != strp[1] || strcmp(name, strp))
- continue;
-#if defined(__mips__) || defined(__vax__)
- if (symp->st_shndx == SHN_UNDEF)
- continue;
-#else
- /*
- * XXX DANGER WILL ROBINSON!
- * If we have a function pointer in the executable's
- * data section, it points to the executable's PLT
- * slot, and there is NO relocation emitted. To make
- * the function pointer comparable to function pointers
- * in shared libraries, we must resolve data references
- * in the libraries to point to PLT slots in the
- * executable, if they exist.
- */
- if (symp->st_shndx == SHN_UNDEF &&
- ((flags & SYMLOOK_IN_PLT) ||
- symp->st_value == 0 ||
- ELF_ST_TYPE(symp->st_info) != STT_FUNC))
- continue;
-#endif
-
- if (ventry == NULL) {
- if (obj->versyms != NULL) {
- verndx = VER_NDX(obj->versyms[symnum].vs_vers);
- if (verndx > obj->vertabnum) {
- _rtld_error("%s: symbol %s references "
- "wrong version %d", obj->path,
- &obj->strtab[symnum], verndx);
- continue;
- }
- /*
- * If we are not called from dlsym (i.e. this
- * is a normal relocation from unversioned
- * binary), accept the symbol immediately
- * if it happens to have first version after
- * this shared object became versioned.
- * Otherwise, if symbol is versioned and not
- * hidden, remember it. If it is the only
- * symbol with this name exported by the shared
- * object, it will be returned as a match at the
- * end of the function. If symbol is global
- * (verndx < 2) accept it unconditionally.
- */
- if (!(flags & SYMLOOK_DLSYM) &&
- verndx == VER_NDX_GIVEN) {
- return symp;
- } else if (verndx >= VER_NDX_GIVEN) {
- if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) {
- if (vsymp == NULL)
- vsymp = symp;
- vcount++;
- }
- continue;
- }
- }
- return symp;
- } else {
- if (obj->versyms == NULL) {
- if (_rtld_object_match_name(obj, ventry->name)){
- _rtld_error("%s: object %s should "
- "provide version %s for symbol %s",
- _rtld_objself.path, obj->path,
- ventry->name, &obj->strtab[symnum]);
- continue;
- }
- } else {
- verndx = VER_NDX(obj->versyms[symnum].vs_vers);
- if (verndx > obj->vertabnum) {
- _rtld_error("%s: symbol %s references "
- "wrong version %d", obj->path,
- &obj->strtab[symnum], verndx);
- continue;
- }
- if (obj->vertab[verndx].hash != ventry->hash ||
- strcmp(obj->vertab[verndx].name, ventry->name)) {
- /*
- * Version does not match. Look if this
- * is a global symbol and if it is not
- * hidden. If global symbol (verndx < 2)
- * is available, use it. Do not return
- * symbol if we are called by dlvsym,
- * because dlvsym looks for a specific
- * version and default one is not what
- * dlvsym wants.
- */
- if ((flags & SYMLOOK_DLSYM) ||
- (obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) ||
- (verndx >= VER_NDX_GIVEN))
- continue;
- }
- }
- return symp;
+ if (_rtld_symlook_obj_matched_symbol(name, obj, flags,
+ ventry, symnum, &vsymp, &vcount)) {
+ return vsymp;
}
}
if (vcount == 1)
Home |
Main Index |
Thread Index |
Old Index