svn commit: r281003 - in head/sys: kern sys

Konstantin Belousov kib at FreeBSD.org
Thu Apr 2 20:14:52 UTC 2015


Author: kib
Date: Thu Apr  2 20:14:51 2015
New Revision: 281003
URL: https://svnweb.freebsd.org/changeset/base/281003

Log:
  Speed up symbol lookup for the amd64 kernel modules.
  
  Amd64 uses relocatable object files as the modules format.  It is good
  WRT not having unneeded overhead for PIC code, in particular, due to
  absence of useless GOT and PLT.  But the cost is that the module
  linking process cannot use hash to speed up the symbol lookup, and
  that each reference to the symbol requiring a relocation, instead of
  single-place relocation in GOT.
  
  Cache the successfull symbol lookup results in the module symbol
  table, using the newly allocated SHN_FBSD_CACHED value from
  SHN_LOOS-HIOS range as an indicator.  The SHN_FBSD_CACHED together
  with the non-existent definition of the found symbol are reverted
  after successfull relocations, which is done under kld_sx lock, so it
  should not be visible to other consumers of the symbol table.
  
  Submitted by:	Conrad Meyer
  Differential Revision:  https://reviews.freebsd.org/D1718
  MFC after:	3 weeks

Modified:
  head/sys/kern/link_elf_obj.c
  head/sys/sys/elf_common.h

Modified: head/sys/kern/link_elf_obj.c
==============================================================================
--- head/sys/kern/link_elf_obj.c	Thu Apr  2 20:07:05 2015	(r281002)
+++ head/sys/kern/link_elf_obj.c	Thu Apr  2 20:14:51 2015	(r281003)
@@ -173,6 +173,7 @@ static struct linker_class link_elf_clas
 };
 
 static int	relocate_file(elf_file_t ef);
+static void	elf_obj_cleanup_globals_cache(elf_file_t);
 
 static void
 link_elf_error(const char *filename, const char *s)
@@ -1075,6 +1076,13 @@ relocate_file(elf_file_t ef)
 		}
 	}
 
+	/*
+	 * Only clean SHN_FBSD_CACHED for successfull return.  If we
+	 * modified symbol table for the object but found an
+	 * unresolved symbol, there is no reason to roll back.
+	 */
+	elf_obj_cleanup_globals_cache(ef);
+
 	return 0;
 }
 
@@ -1223,6 +1231,21 @@ link_elf_each_function_nameval(linker_fi
 	return (0);
 }
 
+static void
+elf_obj_cleanup_globals_cache(elf_file_t ef)
+{
+	Elf_Sym *sym;
+	Elf_Size i;
+
+	for (i = 0; i < ef->ddbsymcnt; i++) {
+		sym = ef->ddbsymtab + i;
+		if (sym->st_shndx == SHN_FBSD_CACHED) {
+			sym->st_shndx = SHN_UNDEF;
+			sym->st_value = 0;
+		}
+	}
+}
+
 /*
  * Symbol lookup function that can be used when the symbol index is known (ie
  * in relocations). It uses the symbol index instead of doing a fully fledged
@@ -1234,7 +1257,7 @@ static Elf_Addr
 elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps)
 {
 	elf_file_t ef = (elf_file_t)lf;
-	const Elf_Sym *sym;
+	Elf_Sym *sym;
 	const char *symbol;
 	Elf_Addr ret;
 
@@ -1262,7 +1285,22 @@ elf_obj_lookup(linker_file_t lf, Elf_Siz
 		if (*symbol == 0)
 			return (0);
 		ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
-		return ret;
+
+		/*
+		 * Cache global lookups during module relocation. The failure
+		 * case is particularly expensive for callers, who must scan
+		 * through the entire globals table doing strcmp(). Cache to
+		 * avoid doing such work repeatedly.
+		 *
+		 * After relocation is complete, undefined globals will be
+		 * restored to SHN_UNDEF in elf_obj_cleanup_globals_cache(),
+		 * above.
+		 */
+		if (ret != 0) {
+			sym->st_shndx = SHN_FBSD_CACHED;
+			sym->st_value = ret;
+		}
+		return (ret);
 
 	case STB_WEAK:
 		printf("link_elf_obj: Weak symbols not supported\n");

Modified: head/sys/sys/elf_common.h
==============================================================================
--- head/sys/sys/elf_common.h	Thu Apr  2 20:07:05 2015	(r281002)
+++ head/sys/sys/elf_common.h	Thu Apr  2 20:14:51 2015	(r281003)
@@ -363,6 +363,9 @@ typedef struct {
 #define	SHN_LOPROC	0xff00		/* First processor-specific. */
 #define	SHN_HIPROC	0xff1f		/* Last processor-specific. */
 #define	SHN_LOOS	0xff20		/* First operating system-specific. */
+#define	SHN_FBSD_CACHED	SHN_LOOS	/* Transient, for sys/kern/link_elf_obj
+					   linker only: Cached global in local
+					   symtab. */
 #define	SHN_HIOS	0xff3f		/* Last operating system-specific. */
 #define	SHN_ABS		0xfff1		/* Absolute values. */
 #define	SHN_COMMON	0xfff2		/* Common data. */


More information about the svn-src-head mailing list