Module Name:    src
Committed By:   kamil
Date:           Sat Feb 29 04:21:42 UTC 2020

Modified Files:
        src/libexec/ld.elf_so: symbol.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.69 -r1.70 src/libexec/ld.elf_so/symbol.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ld.elf_so/symbol.c
diff -u src/libexec/ld.elf_so/symbol.c:1.69 src/libexec/ld.elf_so/symbol.c:1.70
--- src/libexec/ld.elf_so/symbol.c:1.69	Wed Aug  9 18:44:32 2017
+++ src/libexec/ld.elf_so/symbol.c	Sat Feb 29 04:21:42 2020
@@ -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 @@ _rtld_symlook_needed(const char *name, u
 	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 @@ _rtld_symlook_obj(const char *name, unsi
 {
 	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)

Reply via email to