Module Name:    src
Committed By:   pooka
Date:           Fri Mar  8 19:04:28 UTC 2013

Modified Files:
        src/lib/librumpuser: rumpuser_dl.c
        src/sys/rump/include/rump: rumpuser.h
        src/sys/rump/librump/rumpkern: rump.c

Log Message:
Ensure that rump kernel component constructors from the main object
get processed.  This applies to ones which were linked statically.
Unfortunately, that's where it got a bit tricky, since the dlsym()
interface searches the handle and all its dependencies.  For the main
object the list of dependencies includes all the dynamic rump kernel
components that were included when the binary is linked.  So, a long
story short, make only one pass through the objects to harvest all the
component entries, weed out the dupes, and initialize components from
an in-memory dupe-free list when so requested.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/lib/librumpuser/rumpuser_dl.c
cvs rdiff -u -r1.74 -r1.75 src/sys/rump/include/rump/rumpuser.h
cvs rdiff -u -r1.254 -r1.255 src/sys/rump/librump/rumpkern/rump.c

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

Modified files:

Index: src/lib/librumpuser/rumpuser_dl.c
diff -u src/lib/librumpuser/rumpuser_dl.c:1.12 src/lib/librumpuser/rumpuser_dl.c:1.13
--- src/lib/librumpuser/rumpuser_dl.c:1.12	Mon Jan 14 21:00:16 2013
+++ src/lib/librumpuser/rumpuser_dl.c	Fri Mar  8 19:04:27 2013
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpuser_dl.c,v 1.12 2013/01/14 21:00:16 pooka Exp $	*/
+/*      $NetBSD: rumpuser_dl.c,v 1.13 2013/03/08 19:04:27 pooka Exp $	*/
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -33,7 +33,7 @@
 #include "rumpuser_port.h"
 
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_dl.c,v 1.12 2013/01/14 21:00:16 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_dl.c,v 1.13 2013/03/08 19:04:27 pooka Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -67,12 +67,6 @@ static unsigned char eident;
 #define Elf_Symindx uint32_t
 #endif
 
-/*
- * Linux ld.so requires a valid handle for dlinfo(), so use the main
- * handle.  We initialize this variable in rumpuser_dl_bootstrap()
- */
-static void *mainhandle;
-
 static void *
 reservespace(void *store, size_t *storesize,
 	size_t storeoff, size_t required)
@@ -146,9 +140,13 @@ do {									\
  * the address the dso is mapped at.  On Linux, they seem to contain
  * the absolute address.  I couldn't find anything definite from a quick
  * read of the standard and therefore I will not go and figure beyond ifdef.
+ * On Solaris, the main object works differently ... uuuuh.
  */
-#ifdef __linux__
+#if defined(__linux__)
 #define adjptr(_map_, _ptr_) ((void *)(_ptr_))
+#elif defined(__sun__)
+#define adjptr(_map_, _ptr_) \
+    (mainmap_p(_map_) ? (void *)(_ptr_) : (void *)(_map_->l_addr + (_ptr_)))
 #else
 #define adjptr(_map_, _ptr_) ((void *)(_map_->l_addr + (_ptr_)))
 #endif
@@ -341,29 +339,24 @@ getsymbols(struct link_map *map)
 }
 
 static void
-process(const char *soname, rump_modinit_fn domodinit)
+process_object(void *handle,
+	rump_modinit_fn domodinit, rump_compload_fn docompload)
 {
-	void *handle;
 	const struct modinfo *const *mi_start, *const *mi_end;
-
-	if (strstr(soname, "librump") == NULL)
-		return;
-
-	handle = dlopen(soname, RTLD_LAZY);
-	if (handle == NULL)
-		return;
+	struct rump_component *const *rc, *const *rc_end;
 
 	mi_start = dlsym(handle, "__start_link_set_modules");
-	if (!mi_start)
-		goto out;
 	mi_end = dlsym(handle, "__stop_link_set_modules");
-	if (!mi_end)
-		goto out;
+	if (mi_start && mi_end)
+		domodinit(mi_start, (size_t)(mi_end-mi_start));
 
-	domodinit(mi_start, (size_t)(mi_end-mi_start));
-
- out:
-	dlclose(handle);
+	rc = dlsym(handle, "__start_link_set_rump_components");
+	rc_end = dlsym(handle, "__stop_link_set_rump_components");
+	if (rc && rc_end) {
+		for (; rc < rc_end; rc++)
+			docompload(*rc);
+		assert(rc == rc_end);
+	}
 }
 
 /*
@@ -372,17 +365,20 @@ process(const char *soname, rump_modinit
  */
 void
 rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
-	rump_symload_fn symload)
+	rump_symload_fn symload, rump_compload_fn compload)
 {
-	struct link_map *map, *origmap;
+	struct link_map *map, *origmap, *mainmap;
+	void *mainhandle;
 	int error;
 
 	mainhandle = dlopen(NULL, RTLD_NOW);
-	if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &origmap) == -1) {
+	if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) {
 		fprintf(stderr, "warning: rumpuser module bootstrap "
 		    "failed: %s\n", dlerror());
 		return;
 	}
+	origmap = mainmap;
+
 	/*
 	 * Process last->first because that's the most probable
 	 * order for dependencies
@@ -397,10 +393,7 @@ rumpuser_dl_bootstrap(rump_modinit_fn do
 	 */
 	error = 0;
 	for (map = origmap; map && !error; map = map->l_prev) {
-		if (strstr(map->l_name, "librump") != NULL)
-			error = getsymbols(map);
-		/* this should be the main object */
-		else if (!map->l_addr && map->l_prev == NULL)
+		if (strstr(map->l_name, "librump") != NULL || map == mainmap)
 			error = getsymbols(map);
 	}
 
@@ -432,77 +425,45 @@ rumpuser_dl_bootstrap(rump_modinit_fn do
 	free(strtab);
 
 	/*
-	 * Next, load modules from dynlibs.
+	 * Next, load modules and components.
+	 *
+	 * Simply loop through all objects, ones unrelated to rump kernels
+	 * will not contain link_set_rump_components (well, not including
+	 * "sabotage", but that needs to be solved at another level anyway).
 	 */
-	for (map = origmap; map; map = map->l_prev)
-		process(map->l_name, domodinit);
-}
-
-void
-rumpuser_dl_component_init(int type, rump_component_init_fn compinit)
-{
-	struct link_map *map;
-
-	if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &map) == -1) {
-		fprintf(stderr, "warning: rumpuser module bootstrap "
-		    "failed: %s\n", dlerror());
-		return;
-	}
-
-	for (; map->l_next; map = map->l_next)
-		continue;
-	for (; map; map = map->l_prev) {
-		if (strstr(map->l_name, "librump") != NULL) {
-			void *handle;
-			struct rump_component **rc, **rc_end;
+	for (map = origmap; map; map = map->l_prev) {
+		void *handle;
 
+		if (map == mainmap) {
+			handle = mainhandle;
+		} else {
 			handle = dlopen(map->l_name, RTLD_LAZY);
 			if (handle == NULL)
 				continue;
-
-			rc = dlsym(handle,
-			    "__start_link_set_rump_components");
-			if (!rc)
-				goto loop;
-			rc_end = dlsym(handle,
-			    "__stop_link_set_rump_components");
-			if (!rc_end)
-				goto loop;
-
-			for (; rc < rc_end; rc++)
-				compinit(*rc, type);
-			assert(rc == rc_end);
- loop:
-			dlclose(handle);
 		}
+		process_object(handle, domodinit, compload);
+		if (map != mainmap)
+			dlclose(handle);
 	}
 }
 #else
-void
-rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
-	rump_symload_fn symload)
-{
-
-	fprintf(stderr, "Warning, dlinfo() unsupported on host?\n");
-}
-
 /*
  * "default" implementation for platforms where we don't support
  * dynamic linking.  Assumes that all rump kernel components are
- * statically linked with the local client.
+ * statically linked with the local client.  No need to handle modules
+ * since the module code does that all by itself.
  */
-
-extern void *__start_link_set_rump_components;
-extern void *__stop_link_set_rump_components;
 void
-rumpuser_dl_component_init(int type, rump_component_init_fn compinit)
+rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
+	rump_symload_fn symload, rump_compload_fn compload)
 {
+	extern void *__start_link_set_rump_components;
+	extern void *__stop_link_set_rump_components;
 	void **rc = &__start_link_set_rump_components;
 	void **rc_end = &__stop_link_set_rump_components;
 
 	for (; rc < rc_end; rc++)
-		compinit(*rc, type);
-
+		compload(*rc);
 }
 #endif
 

Index: src/sys/rump/include/rump/rumpuser.h
diff -u src/sys/rump/include/rump/rumpuser.h:1.74 src/sys/rump/include/rump/rumpuser.h:1.75
--- src/sys/rump/include/rump/rumpuser.h:1.74	Fri Mar  1 13:52:31 2013
+++ src/sys/rump/include/rump/rumpuser.h	Fri Mar  8 19:04:28 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser.h,v 1.74 2013/03/01 13:52:31 pooka Exp $	*/
+/*	$NetBSD: rumpuser.h,v 1.75 2013/03/08 19:04:28 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -38,7 +38,7 @@
 #include <stdint.h>
 #endif
 
-#define RUMPUSER_VERSION 14
+#define RUMPUSER_VERSION 15
 int rumpuser_getversion(void);
 
 int rumpuser_daemonize_begin(void);
@@ -218,9 +218,8 @@ struct modinfo;
 struct rump_component;
 typedef void (*rump_modinit_fn)(const struct modinfo *const *, size_t);
 typedef int (*rump_symload_fn)(void *, uint64_t, char *, uint64_t);
-typedef void (*rump_component_init_fn)(struct rump_component *, int);
-void rumpuser_dl_bootstrap(rump_modinit_fn, rump_symload_fn);
-void rumpuser_dl_component_init(int, rump_component_init_fn);
+typedef void (*rump_compload_fn)(const struct rump_component *);
+void rumpuser_dl_bootstrap(rump_modinit_fn, rump_symload_fn, rump_compload_fn);
 void *rumpuser_dl_globalsym(const char *);
 
 /* syscall proxy routines */

Index: src/sys/rump/librump/rumpkern/rump.c
diff -u src/sys/rump/librump/rumpkern/rump.c:1.254 src/sys/rump/librump/rumpkern/rump.c:1.255
--- src/sys/rump/librump/rumpkern/rump.c:1.254	Thu Mar  7 22:12:34 2013
+++ src/sys/rump/librump/rumpkern/rump.c	Fri Mar  8 19:04:28 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump.c,v 1.254 2013/03/07 22:12:34 pooka Exp $	*/
+/*	$NetBSD: rump.c,v 1.255 2013/03/08 19:04:28 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.254 2013/03/07 22:12:34 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.255 2013/03/08 19:04:28 pooka Exp $");
 
 #include <sys/systm.h>
 #define ELFSIZE ARCH_ELFSIZE
@@ -106,6 +106,9 @@ static int rump_proxy_rfork(void *, int,
 static void rump_proxy_lwpexit(void);
 static void rump_proxy_execnotify(const char *);
 
+static void rump_component_load(const struct rump_component *);
+static struct lwp *bootlwp;
+
 static char rump_msgbuf[16*1024]; /* 16k should be enough for std rump needs */
 
 #ifdef LOCKDEBUG
@@ -348,6 +351,7 @@ rump__init(int rump_version)
 	rumpuser_set_curlwp(NULL);
 	initproc = &proc0; /* borrow proc0 before we get initproc started */
 	rump_schedule();
+	bootlwp = curlwp;
 
 	percpu_init();
 	inittimecounter();
@@ -400,7 +404,8 @@ rump__init(int rump_version)
 		uvm.pagedaemon_lwp = NULL; /* doesn't match curlwp */
 
 	/* process dso's */
-	rumpuser_dl_bootstrap(add_linkedin_modules, rump_kernelfsym_load);
+	rumpuser_dl_bootstrap(add_linkedin_modules,
+	    rump_kernelfsym_load, rump_component_load);
 
 	rump_component_init(RUMP_COMPONENT_KERN);
 
@@ -520,6 +525,7 @@ rump__init(int rump_version)
 	rump_component_init(RUMP_COMPONENT_POSTINIT);
 
 	/* release cpu */
+	bootlwp = NULL;
 	rump_unschedule();
 
 	return 0;
@@ -665,33 +671,58 @@ rump_cred_put(kauth_cred_t cred)
 static int compcounter[RUMP_COMPONENT_MAX];
 static int compinited[RUMP_COMPONENT_MAX];
 
+/*
+ * Yea, this is O(n^2), but we're only looking at a handful of components.
+ * Components are always initialized from the thread that called rump_init().
+ * Could also free these when done with them, but prolly not worth it.
+ */
+struct compstore {
+	const struct rump_component *cs_rc;
+	LIST_ENTRY(compstore) cs_entries;
+};
+static LIST_HEAD(, compstore) cshead = LIST_HEAD_INITIALIZER(cshead);
+
 static void
-rump_component_init_cb(struct rump_component *rc, int type)
+rump_component_load(const struct rump_component *rc)
 {
+	struct compstore *cs;
 
-	KASSERT(type < RUMP_COMPONENT_MAX);
+	KASSERT(curlwp == bootlwp);
 
-	if (rc->rc_type == type) {
-		rc->rc_init();
-		compcounter[type]++;
+	LIST_FOREACH(cs, &cshead, cs_entries) {
+		if (rc == cs->cs_rc)
+			return;
 	}
+
+	cs = kmem_alloc(sizeof(*cs), KM_SLEEP);
+	cs->cs_rc = rc;
+	LIST_INSERT_HEAD(&cshead, cs, cs_entries);
+	KASSERT(rc->rc_type < RUMP_COMPONENT_MAX);
+	compcounter[rc->rc_type]++;
 }
 
 int
 rump_component_count(enum rump_component_type type)
 {
 
-	KASSERT(type <= RUMP_COMPONENT_MAX);
-	KASSERT(compinited[type]);
+	KASSERT(curlwp == bootlwp);
+	KASSERT(type < RUMP_COMPONENT_MAX);
 	return compcounter[type];
 }
 
 void
 rump_component_init(enum rump_component_type type)
 {
+	struct compstore *cs;
+	const struct rump_component *rc;
 
+	KASSERT(curlwp == bootlwp);
 	KASSERT(!compinited[type]);
-	rumpuser_dl_component_init(type, rump_component_init_cb);
+	LIST_FOREACH(cs, &cshead, cs_entries) {
+		rc = cs->cs_rc;
+		if (rc->rc_type == type)
+			rc->rc_init();
+	}
 	compinited[type] = 1;
 }
 

Reply via email to