Index: trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 87728)
@@ -788,29 +788,15 @@
   ifdef VBOX_WITH_KMOD_WRAPPED_R0_MODS
 #
-# The wrapper modules.
-#
-INSTALLS.linux += vbox_vmmr0-src
-vbox_vmmr0-src_INST = bin/src/vbox_vmmr0/
-vbox_vmmr0-src_SOURCES = \
+# Common wrapper module files.
+#
+INSTALLS.linux += vboxwrappermod-common-src
+vboxwrappermod-common-src_INST = bin/src/common/
+vboxwrappermod-common-src_SOURCES = \
 	linux/SUPWrapperMod-linux.c=>SUPWrapperMod-linux.c \
-	linux/Makefile-vbox_vmmr0.gmk=>Makefile \
 	linux/Makefile-wrapper.gmk=>Makefile-wrapper.gmk \
-       $(PATH_ROOT)/src/VBox/Installer/linux/Makefile-header.gmk=>Makefile-header.gmk \
-       $(PATH_ROOT)/src/VBox/Installer/linux/Makefile-footer.gmk=>Makefile-footer.gmk \
-	$(PATH_OBJ)/VMMR0/VMMR0.r0=>VMMR0.r0 \
-	$(PATH_OBJ)/VMMR0/VMMR0.debug=>VMMR0.debug \
-
-INSTALLS.linux += vbox_vboxddr0-src
-vbox_vboxddr0-src_INST = bin/src/vbox_vboxddr0/
-vbox_vboxddr0-src_SOURCES = \
-	linux/SUPWrapperMod-linux.c=>SUPWrapperMod-linux.c \
-	linux/Makefile-vbox_vboxddr0.gmk=>Makefile \
-	linux/Makefile-wrapper.gmk=>Makefile-wrapper.gmk \
-       $(PATH_ROOT)/src/VBox/Installer/linux/Makefile-header.gmk=>Makefile-header.gmk \
-       $(PATH_ROOT)/src/VBox/Installer/linux/Makefile-footer.gmk=>Makefile-footer.gmk \
-	$(PATH_OBJ)/VBoxDDR0/VBoxDDR0.r0=>VBoxDDR0.r0 \
-	$(PATH_OBJ)/VBoxDDR0/VBoxDDR0.debug=>VBoxDDR0.debug \
-
+	$(PATH_ROOT)/src/VBox/Installer/linux/Makefile-header.gmk=>Makefile-header.gmk \
+	$(PATH_ROOT)/src/VBox/Installer/linux/Makefile-footer.gmk=>Makefile-footer.gmk
   endif
+
  endif # supported host arch
 endif # linux freebsd
Index: trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vboxddr0.gmk
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vboxddr0.gmk	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vboxddr0.gmk	(revision 87728)
@@ -30,5 +30,5 @@
 WRAPPER_NEED_VMMR0   := yes
 
-include $(dir $(lastword $(MAKEFILE_LIST)))/Makefile-wrapper.gmk
+include $(dir $(lastword $(MAKEFILE_LIST)))Makefile-wrapper.gmk
 
 
Index: trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vmmr0.gmk
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vmmr0.gmk	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/linux/Makefile-vbox_vmmr0.gmk	(revision 87728)
@@ -31,4 +31,4 @@
 WRAPPED_MODULE_LINUX_EXPORTS   := yes
 
-include $(dir $(lastword $(MAKEFILE_LIST)))/Makefile-wrapper.gmk
+include $(dir $(lastword $(MAKEFILE_LIST)))Makefile-wrapper.gmk
 
Index: trunk/src/VBox/HostDrivers/Support/linux/Makefile-wrapper.gmk
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/Makefile-wrapper.gmk	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/linux/Makefile-wrapper.gmk	(revision 87728)
@@ -35,8 +35,10 @@
 
 # Linux kbuild sets this to our source directory if we are called from there
-obj ?= $(CURDIR)
-include $(obj)/Makefile-header.gmk
-VBOXDRV_DIR     := $(abspath $(VBOX_MODULE_SRC_DIR)../vboxdrv/)/
-VBOX_VMMR0_DIR  := $(abspath $(VBOX_MODULE_SRC_DIR)../vbox_vmmr0/)/
+ifndef VBOX_MODULE_SRC_DIR
+ VBOX_MODULE_SRC_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/
+endif
+VBOXDRV_DIR          := $(abspath $(VBOX_MODULE_SRC_DIR)../vboxdrv/)/
+VBOX_VMMR0_DIR       := $(abspath $(VBOX_MODULE_SRC_DIR)../vbox_vmmr0/)/
+include $(VBOXDRV_DIR)Makefile-header.gmk
 
 # All of these wrappers depend on
@@ -47,5 +49,4 @@
  endif
 endif
-$(warning KBUILD_EXTRA_SYMBOLS=$(KBUILD_EXTRA_SYMBOLS) WRAPPER_NEED_VMMR0=$(WRAPPER_NEED_VMMR0))
 
 VBOXMOD_OBJS = \
@@ -66,6 +67,5 @@
        \
 	WRAPPED_MODULE_NAME=\"$(WRAPPED_MODULE_NAME).r0\" \
-	WRAPPED_MODULE_SYMBOL_INCLUDE=\"$(WRAPPED_MODULE_NAME)-symbols.h\" \
-	WRAPPER_MODULE_KMOD_NAME=\"$(VBOXMOD_NAME)\"
+	WRAPPED_MODULE_SYMBOL_INCLUDE=\"$(WRAPPED_MODULE_NAME)-symbols.h\"
 ifdef WRAPPED_MODULE_FLAGS
 VBOXMOD_DEFS += WRAPPED_MODULE_FLAGS="$(WRAPPED_MODULE_FLAGS)"
@@ -87,4 +87,7 @@
 VBOXMOD_DEFS += WRAPPED_MODULE_TERM=NULL
 endif
+ifdef WRAPPED_MODULE_LICENSE_PROPRIETARY
+VBOXMOD_DEFS += WRAPPED_MODULE_LICENSE_PROPRIETARY
+endif
 
 VBOXMOD_CFLAGS = -include $(VBOXDRV_DIR)include/VBox/SUPDrvMangling.h \
@@ -93,5 +96,5 @@
 ## @todo cleanup
 
-include $(obj)/Makefile-footer.gmk
+include $(VBOXDRV_DIR)Makefile-footer.gmk
 
 
Index: trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 87728)
@@ -758,8 +758,28 @@
  * with device extension prepended to the argument list.
  */
-SUPR0DECL(int)  SUPDrvLinuxLdrRegisterWrappedModule(PCSUPLDRWRAPPEDMODULE pWrappedModInfo, void *pvLnxModule, void **phMod)
-{
-    AssertPtrReturn(pvLnxModule, VERR_INVALID_POINTER);
-    return supdrvLdrRegisterWrappedModule(&g_DevExt, pWrappedModInfo, pvLnxModule, phMod);
+SUPR0DECL(int)  SUPDrvLinuxLdrRegisterWrappedModule(PCSUPLDRWRAPPEDMODULE pWrappedModInfo,
+                                                    const char *pszLnxModName, void **phMod)
+{
+    /* Locate the module structure for the caller so can later reference
+       and dereference it to prevent unloading while it is being used.
+
+       Before Linux v5.9 this could be done by address (__module_address()
+       or __module_text_address()), but someone (guess who) apparently on
+       a mission to make life miserable for out-of-tree modules or something,
+       decided it was only used by build-in code and unexported both of them.
+
+       I could find no init callouts getting a struct module pointer either,
+       nor any module name hint anywhere I could see.  So, we're left with
+       hardcoding the module name via the compiler and pass it along to
+       SUPDrv so we can call find_module() here.
+
+       Sigh^2. */
+    AssertPtrReturn(pszLnxModName, VERR_INVALID_POINTER);
+    AssertReturn(*pszLnxModName, VERR_INVALID_NAME);
+    struct module *pLnxModule = find_module(pszLnxModName);
+    if (pLnxModule)
+        return supdrvLdrRegisterWrappedModule(&g_DevExt, pWrappedModInfo, pLnxModule, phMod);
+    printk("vboxdrv: find_module(%s) failed in SUPDrvLinuxLdrRegisterWrappedModule!\n", pszLnxModName);
+    return VERR_MODULE_NOT_FOUND;
 }
 EXPORT_SYMBOL(SUPDrvLinuxLdrRegisterWrappedModule);
Index: trunk/src/VBox/HostDrivers/Support/linux/SUPWrapperMod-linux.c
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/SUPWrapperMod-linux.c	(revision 87709)
+++ trunk/src/VBox/HostDrivers/Support/linux/SUPWrapperMod-linux.c	(revision 87728)
@@ -168,27 +168,9 @@
 static int __init VBoxWrapperModInit(void)
 {
-    /* Locate the module structure before we call SUPDrv to register.
-
-       Before Linux v5.9 this could be done by address (__module_address()
-       or __module_text_address()), but someone (guess who) apparently on
-       a mission to make life miserable for out-of-tree modules or something,
-       decided it was only used by build-in code and unexported both of them.
-
-       I could find no init callouts getting a struct module pointer either,
-       nor any module name hint anywhere I could see.  So, we're left with
-       hardcoding the module name via the compiler and call find_module.
-
-       Sigh^2. */
     /*printk("vboxwrap/" WRAPPED_MODULE_NAME ": VBoxWrapperModInit\n");*/
-    struct module *pLnxMod = find_module(WRAPPER_MODULE_KMOD_NAME);
-    if (pLnxMod)
-    {
-        int rc = SUPDrvLinuxLdrRegisterWrappedModule(&g_WrappedMod, pLnxMod, &g_hWrappedRegistration);
-        if (rc == 0)
-            return 0;
-        printk("vboxwrap/" WRAPPED_MODULE_NAME ": SUPDrvLinuxRegisterWrappedModule failed: %d\n", rc);
-    }
-    else
-        printk("vboxwrap/" WRAPPED_MODULE_NAME ": find_module(" WRAPPER_MODULE_KMOD_NAME ") failed\n");
+    int rc = SUPDrvLinuxLdrRegisterWrappedModule(&g_WrappedMod, KBUILD_MODNAME, &g_hWrappedRegistration);
+    if (rc == 0)
+        return 0;
+    printk("vboxwrap/" WRAPPED_MODULE_NAME ": SUPDrvLinuxRegisterWrappedModule failed: %d\n", rc);
     return -EINVAL;
 }
Index: trunk/src/VBox/HostDrivers/linux/Makefile
===================================================================
--- trunk/src/VBox/HostDrivers/linux/Makefile	(revision 87709)
+++ trunk/src/VBox/HostDrivers/linux/Makefile	(revision 87728)
@@ -30,13 +30,13 @@
 
 obj-m = vboxdrv/
-ifneq ($(wildcard $(CURDIR)/vboxnetflt/Makefile),)
- obj-m += vboxnetflt/
-endif
-ifneq ($(wildcard $(CURDIR)/vboxnetadp/Makefile),)
- obj-m += vboxnetadp/
-endif
-ifneq ($(wildcard $(CURDIR)/vboxpci/Makefile),)
- obj-m += vboxpci/
-endif
+ ifneq ($(wildcard $(CURDIR)/vboxnetflt/Makefile),)
+obj-m += vboxnetflt/
+ endif
+ ifneq ($(wildcard $(CURDIR)/vboxnetadp/Makefile),)
+obj-m += vboxnetadp/
+ endif
+ ifneq ($(wildcard $(CURDIR)/vboxpci/Makefile),)
+obj-m += vboxpci/
+ endif
 
 else # ! KERNELRELEASE
@@ -45,5 +45,4 @@
 
 KBUILD_VERBOSE ?=
-KERN_VER ?= $(shell uname -r)
 .PHONY: all install clean check unload load \
     vboxdrv vboxnetflt vboxnetadp vboxpci \
@@ -54,5 +53,6 @@
 
 # We want to build on Linux 2.6.18 and later kernels.
-ifneq ($(filter-out 1.% 2.0.% 2.1.% 2.2.% 2.3.% 2.4.% 2.5.%,$(KERN_VER)),)
+KERN_VER ?= $(shell uname -r)
+ ifneq ($(filter-out 1.% 2.0.% 2.1.% 2.2.% 2.3.% 2.4.% 2.5.%,$(KERN_VER)),)
 
 vboxdrv:
@@ -115,5 +115,57 @@
 install: install-vboxdrv install-vboxnetflt install-vboxnetadp install-vboxpci
 
-else
+# Look for wrapper modules, sorting them so vmmr0 is first.
+VBOX_WRAPPER_DIRS := $(notdir $(wildcard $(CURDIR)/vbox_*))
+  ifneq ($(VBOX_WRAPPER_DIRS),)
+VBOX_WRAPPER_DIRS := $(filter vbox_vmmr0,$(VBOX_WRAPPER_DIRS)) $(sort $(filter-out vbox_vmmr0,$(VBOX_WRAPPER_DIRS)))
+  endif
+  define wrapper_template
+$(wrapper): $(subst $(wrapper),,vbox_vmmr0)
+	$$(MAKE) KBUILD_VERBOSE=$$(KBUILD_VERBOSE) -C $(wrapper)/
+
+load-$(wrapper): $(if $(eq $(wrapper),vbox_vmmr0),,load-vbox_vmmr0)
+	@if ! grep -q "^$(wrapper) " /proc/modules; then \
+       	echo "Loading $(wrapper)..."; \
+		/sbin/insmod $(wrapper)/$(wrapper).ko; \
+	else \
+       	echo "Skipping loading $(wrapper) module (already loaded)."; \
+	fi
+
+unload-$(wrapper):
+	@if grep -q "^$(wrapper) " /proc/modules; then \
+       	echo "Unloading $(wrapper)..."; \
+		/sbin/rmmod $(wrapper)/$(wrapper).ko; \
+	fi
+  endef
+$(foreach wrapper,$(VBOX_WRAPPER_DIRS), $(eval $(wrapper_template)))
+
+wrappers: 	$(VBOX_WRAPPER_DIRS)
+load-wrappers: $(addprefix load-,$(VBOX_WRAPPER_DIRS))
+unload-wrappers:
+	@for module in $(filter-out vbox_vmmr0,$(VBOX_WRAPPER_DIRS)) $(filter vbox_vmmr0,$(VBOX_WRAPPER_DIRS)); \
+	do \
+		if grep -q "^$${module} " /proc/modules; then \
+			echo "Unloading $${module}..."; \
+		if \
+	done
+
+buildid:
+	@for module in $(foreach module,vboxdrv vboxnetflt vboxnetadp $(VBOX_WRAPPER_DIRS),$(module)/$(module).ko); \
+	do \
+		buildid=`readelf -n $${module} | sed -ne 's/^.*Build ID: *\([[:xdigit:]][[:xdigit:]]\)\(.*\)$$/\1\/\2/p' `; \
+		if [ -n "$${buildid}" ]; then \
+			mkdir -p ~/.debug/.build-id/`dirname $${buildid}`; \
+			ln -sfn -- "$(CURDIR)/$${module}" ~/.debug/.build-id/$${buildid}; \
+		else \
+			echo "warning: No build ID for $${module}}"; \
+		fi \
+	done
+
+.PHONY: wrappers load-wrappers unload-wrappers buildid $(VBOX_WRAPPER_DIRS) \
+	$(addprefix load-,$(VBOX_WRAPPER_DIRS)) $(addprefix unload-,$(VBOX_WRAPPER_DIRS))
+
+ else # Too old:
+
+VBOX_WRAPPER_DIRS :=
 
 vboxdrv:
@@ -122,6 +174,10 @@
 vboxpci:
 install:
-
-endif
+wrappers:
+load-wrappers:
+unload-wrappers:
+buildid-wrappers:
+
+ endif
 
 clean-vboxdrv:
@@ -169,2 +225,3 @@
 
 endif # ! KERNELRELEASE
+
