Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 58872)
@@ -4650,5 +4650,5 @@
     pReq->u.Out.fNeedsLoading = true;
     pReq->u.Out.fNativeLoader = pImage->fNative;
-    supdrvOSLdrNotifyOpened(pDevExt, pImage);
+    supdrvOSLdrNotifyOpened(pDevExt, pImage, pReq->u.In.szFilename);
 
     supdrvLdrUnlock(pDevExt);
@@ -5399,7 +5399,9 @@
     supdrvTracerModuleUnloading(pDevExt, pImage);
 
-    /* do native unload if appropriate. */
+    /* Do native unload if appropriate, then inform the native code about the
+       unloading (mainly for non-native loading case). */
     if (pImage->fNative)
         supdrvOSLdrUnload(pDevExt, pImage);
+    supdrvOSLdrNotifyUnloaded(pDevExt, pImage);
 
     /* free the image */
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 58872)
@@ -391,4 +391,11 @@
     /** Pointer to the module control structure. */
     struct modctl                  *pSolModCtl;
+#endif
+#ifdef RT_OS_LINUX
+    /** Hack for seeing the module in perf, dtrace and other stack crawlers. */
+    struct module                  *pLnxModHack;
+    /** Hack for seeing the module in perf, dtrace and other stack crawlers .
+     * Required for Linux v3.19+. */
+    struct supdrv_ftrace_ops       *pLnxFTraceHack;
 #endif
     /** Whether it's loaded by the native loader or not. */
@@ -848,10 +855,14 @@
  * Notification call indicating that a image is being opened for the first time.
  *
- * Can be used to log the load address of the image.
+ * Called for both native and non-native images (after supdrvOSLdrOpen).  Can be
+ * used to log the load address of the image or inform the kernel about the
+ * alien image.
  *
  * @param   pDevExt             The device globals.
  * @param   pImage              The image handle.
- */
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
+ * @param   pszFilename         The file name - UTF-8, may containing UNIX
+ *                              slashes on non-UNIX systems.
+ */
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename);
 
 /**
@@ -884,5 +895,5 @@
 
 /**
- * Unload the image.
+ * Unload the image (only called if supdrvOSLdrOpen returned success).
  *
  * @param   pDevExt             The device globals.
@@ -890,4 +901,15 @@
  */
 void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
+
+/**
+ * Notification call indicating that a image is being unloaded.
+ *
+ * Called for both native and non-native images.  In the former case, it's
+ * called after supdrvOSLdrUnload.
+ *
+ * @param   pDevExt             The device globals.
+ * @param   pImage              The image handle.
+ */
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
 
 
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 58872)
@@ -1136,8 +1136,42 @@
 }
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+
+int  VBOXCALL   supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyLoaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
 {
 #if 1
-    NOREF(pDevExt); NOREF(pImage);
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
 #else
     /*
@@ -1163,26 +1197,5 @@
 
 
-int  VBOXCALL   supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
-{
-    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
-    return VERR_NOT_SUPPORTED;
-}
-
-
-int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
-{
-    NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits);
-    return VERR_NOT_SUPPORTED;
-}
-
-
-int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
-{
-    NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
-    return VERR_NOT_SUPPORTED;
-}
-
-
-void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
     NOREF(pDevExt); NOREF(pImage);
Index: /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 58872)
@@ -560,10 +560,4 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
-}
-
-
 int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
 {
@@ -581,4 +575,16 @@
 
 void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
     NOREF(pDevExt); NOREF(pImage);
Index: /trunk/src/VBox/HostDrivers/Support/linux/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/linux/Makefile	(revision 58872)
@@ -288,5 +288,5 @@
 
 # build defs
-EXTRA_CFLAGS  += -include $(MANGLING) $(INCL) $(KFLAGS) $(KDEBUG)
+EXTRA_CFLAGS  += -include $(MANGLING) $(INCL) $(KFLAGS) $(KDEBUG) -fno-omit-frame-pointer
 
 all: $(MODULE)
Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 58872)
@@ -65,4 +65,8 @@
 # include <asm/msr.h>
 #endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_DYNAMIC_FTRACE)
+# include <linux/ftrace.h>
+#endif
+
 #include <iprt/asm-amd64-x86.h>
 
@@ -940,10 +944,4 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
-}
-
-
 int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
 {
@@ -962,4 +960,476 @@
 void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+/** @def VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS
+ * A very crude hack for debugging using perf and dtrace.
+ *
+ * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS!  DEVELOPMENT ONLY!!
+ * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS!  DEVELOPMENT ONLY!!
+ * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS!  DEVELOPMENT ONLY!!
+ *
+ */
+#if 0 || defined(DOXYGEN_RUNNING)
+# define VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS
+#endif
+
+#if defined(VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS) && defined(CONFIG_MODULES_TREE_LOOKUP)
+/** Whether g_pfnModTreeInsert and g_pfnModTreeRemove have been initialized.
+ * @remarks can still be NULL after init. */
+static volatile bool g_fLookedForModTreeFunctions = false;
+static void (*g_pfnModTreeInsert)(struct mod_tree_node *) = NULL;   /**< __mod_tree_insert */
+static void (*g_pfnModTreeRemove)(struct mod_tree_node *) = NULL;   /**< __mod_tree_remove */
+#endif
+
+#if 0 /* instant host lockup, can't be bothered debugging it */
+#if defined(VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS) \
+ && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) \
+ && defined(CONFIG_MODULES_TREE_LOOKUP) \
+ && defined(CONFIG_DYNAMIC_FTRACE)
+
+/**
+ * Using a static array here because that's what is suggested in the docs to
+ * avoid/reduce potential race conditions.
+ */
+static struct supdrv_ftrace_ops
+{
+    struct ftrace_ops   Core;
+    bool volatile       fUsed;
+} g_aFTraceOps[16] __read_mostly;
+
+/** Stub function for the ugly debug hack below. */
+static void notrace __attribute__((optimize("-fomit-frame-pointer")))
+supdrvLnxFTraceStub(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct pt_regs *regs)
+{
+     return;
+}
+
+#endif
+#endif
+
+
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */
+    /*
+     * This trick stops working with 4.2 when CONFIG_MODULES_TREE_LOOKUP is
+     * defined.  The module lookups are done via a tree structure and we
+     * cannot get at the root of it. :-(
+     */
+# ifdef CONFIG_KALLSYMS
+    size_t const cchName = strlen(pImage->szName);
+# endif
+    struct module *pMyMod, *pSelfMod, *pTestMod, *pTestModByName;
+    IPRT_LINUX_SAVE_EFL_AC();
+
+    pImage->pLnxModHack    = NULL;
+    pImage->pLnxFTraceHack = NULL;
+
+# ifdef CONFIG_MODULES_TREE_LOOKUP
+    /*
+     * This is pretty naive, but works for 4.2 on arch linux.  I don't think we
+     * can count on finding __mod_tree_remove in all kernel builds as it's not
+     * marked noinline like __mod_tree_insert.
+     */
+    if (!g_fLookedForModTreeFunctions)
+    {
+        unsigned long ulInsert = kallsyms_lookup_name("__mod_tree_insert");
+        unsigned long ulRemove = kallsyms_lookup_name("__mod_tree_remove");
+        if (!ulInsert || !ulRemove)
+        {
+            g_fLookedForModTreeFunctions = true;
+            printk(KERN_ERR "vboxdrv: failed to locate __mod_tree_insert and __mod_tree_remove.\n");
+            IPRT_LINUX_RESTORE_EFL_AC();
+            return;
+        }
+        *(unsigned long *)&g_pfnModTreeInsert = ulInsert;
+        *(unsigned long *)&g_pfnModTreeRemove = ulRemove;
+        ASMCompilerBarrier();
+        g_fLookedForModTreeFunctions = true;
+    }
+    else if (!g_pfnModTreeInsert || !g_pfnModTreeRemove)
+        return;
+#endif
+
+    /*
+     * Make sure we've found our own module, otherwise we cannot access the linked list.
+     */
+    mutex_lock(&module_mutex);
+    pSelfMod = find_module("vboxdrv");
+    mutex_unlock(&module_mutex);
+    if (!pSelfMod)
+    {
+        IPRT_LINUX_RESTORE_EFL_AC();
+        return;
+    }
+
+    /*
+     * Cook up a module structure for the image.
+     * We allocate symbol and string tables in the allocation and the module to keep things simple.
+     */
+# ifdef CONFIG_KALLSYMS
+    pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod)
+                                          + sizeof(Elf_Sym) * 3
+                                          + 1 + cchName * 2 + sizeof("_start") + sizeof("_end") + 4 );
+# else
+    pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod));
+# endif
+    if (pMyMod)
+    {
+        int rc = VINF_SUCCESS;
+        //size_t cch;
+# ifdef CONFIG_KALLSYMS
+        Elf_Sym *paSymbols = (Elf_Sym *)(pMyMod + 1);
+        char    *pchStrTab = (char *)(paSymbols + 3);
+# endif
+
+        pMyMod->state = MODULE_STATE_LIVE;
+        INIT_LIST_HEAD(&pMyMod->list);  /* just in case */
+
+        /* Come up with a good name that perf can translate with minimum help... */
+#  if 0
+        cch = strlen(pszFilename);
+        if (cch < sizeof(pMyMod->name))
+            memcpy(pMyMod->name, pszFilename, cch + 1);
+        else
+        {
+            const char *pszTmp = pszFilename;
+            for (;;)
+            {
+                /* skip one path component. */
+                while (*pszTmp == '/')
+                    pszTmp++, cch--;
+                while (*pszTmp != '/' && *pszTmp != '\0')
+                    pszTmp++, cch--;
+
+                /* If we've skipped past the final component, hack something up based on the module name. */
+                if (*pszTmp != '/')
+                {
+                    RTStrPrintf(pMyMod->name, sizeof(pMyMod->name), "/opt/VirtualBox/%s", pImage->szName);
+                    break;
+                }
+                /* When we've got space for two dots and the remaining path, we're done. */
+                if (cch + 2 < sizeof(pMyMod->name))
+                {
+                    pMyMod->name[0] = '.';
+                    pMyMod->name[1] = '.';
+                    memcpy(&pMyMod->name[2], pszTmp, cch + 1);
+                    break;
+                }
+            }
+        }
+#  else
+        /* Perf only matches up files with a .ko extension (maybe .ko.gz),
+           so in order for this crap to work smoothly, we append .ko to the
+           module name and require the user to create symbolic links in
+           /lib/modules/`uname -r`:
+                for i in VMMR0.r0 VBoxDDR0.r0 VBoxDD2R0.r0; do
+                    sudo ln -s /mnt/scratch/vbox/svn/trunk/out/linux.amd64/debug/bin/$i /lib/modules/`uname -r`/$i.ko;
+                done  */
+        RTStrPrintf(pMyMod->name, sizeof(pMyMod->name), "%s", pImage->szName);
+#  endif
+
+        /* sysfs bits. */
+        INIT_LIST_HEAD(&pMyMod->mkobj.kobj.entry); /* rest of kobj is already zeroed, hopefully never accessed... */
+        pMyMod->mkobj.mod           = pMyMod;
+        pMyMod->mkobj.drivers_dir   = NULL;
+        pMyMod->mkobj.mp            = NULL;
+        pMyMod->mkobj.kobj_completion = NULL;
+
+        pMyMod->modinfo_attrs       = NULL; /* hopefully not accessed after setup. */
+        pMyMod->holders_dir         = NULL; /* hopefully not accessed. */
+        pMyMod->version             = "N/A";
+        pMyMod->srcversion          = "N/A";
+
+        /* We export no symbols. */
+        pMyMod->num_syms            = 0;
+        pMyMod->syms                = NULL;
+        pMyMod->crcs                = NULL;
+
+        pMyMod->num_gpl_syms        = 0;
+        pMyMod->gpl_syms            = NULL;
+        pMyMod->gpl_crcs            = NULL;
+
+        pMyMod->num_gpl_future_syms = 0;
+        pMyMod->gpl_future_syms     = NULL;
+        pMyMod->gpl_future_crcs     = NULL;
+
+# if CONFIG_UNUSED_SYMBOLS
+        pMyMod->num_unused_syms     = 0;
+        pMyMod->unused_syms         = NULL;
+        pMyMod->unused_crcs         = NULL;
+
+        pMyMod->num_unused_gpl_syms = 0;
+        pMyMod->unused_gpl_syms     = NULL;
+        pMyMod->unused_gpl_crcs     = NULL;
+# endif
+        /* No kernel parameters either. */
+        pMyMod->kp                  = NULL;
+        pMyMod->num_kp              = 0;
+
+# ifdef CONFIG_MODULE_SIG
+        /* Pretend ok signature. */
+        pMyMod->sig_ok              = true;
+# endif
+        /* No exception table. */
+        pMyMod->num_exentries       = 0;
+        pMyMod->extable             = NULL;
+
+        /* No init function */
+        pMyMod->init                = NULL;
+        pMyMod->module_init         = NULL;
+        pMyMod->init_size           = 0;
+        pMyMod->init_ro_size        = 0;
+        pMyMod->init_text_size      = 0;
+
+        /* The module address and size. It's all text. */
+        pMyMod->module_core         = pImage->pvImage;
+        pMyMod->core_size           = pImage->cbImageBits;
+        pMyMod->core_text_size      = pImage->cbImageBits;
+        pMyMod->core_ro_size        = pImage->cbImageBits;
+
+#ifdef CONFIG_MODULES_TREE_LOOKUP
+        /* Fill in the self pointers for the tree nodes. */
+        pMyMod->mtn_core.mod        = pMyMod;
+        pMyMod->mtn_init.mod        = pMyMod;
+#endif
+        /* They invented the tained bit for us, didn't they? */
+        pMyMod->taints              = 1;
+
+# ifdef CONFIG_GENERIC_BUGS
+        /* No BUGs in our modules. */
+        pMyMod->num_bugs            = 0;
+        INIT_LIST_HEAD(&pMyMod->bug_list);
+        pMyMod->bug_table           = NULL;
+# endif
+
+# ifdef CONFIG_KALLSYMS
+        /* The core stuff is documented as only used when loading. So just zero them. */
+        pMyMod->core_num_syms       = 0;
+        pMyMod->core_symtab         = NULL;
+        pMyMod->core_strtab         = NULL;
+
+        /* Construct a symbol table with start and end symbols.
+           Note! We don't have our own symbol table at this point, image bit
+                 are not uploaded yet! */
+        pMyMod->num_symtab          = 3;
+        pMyMod->symtab              = paSymbols;
+        pMyMod->strtab              = pchStrTab;
+        RT_ZERO(paSymbols[0]);
+        pchStrTab[0] = '\0';
+        paSymbols[1].st_name        = 1;
+        paSymbols[2].st_name        = 2 + RTStrPrintf(&pchStrTab[paSymbols[1].st_name], cchName + sizeof("_start"),
+                                                      "%s_start", pImage->szName);
+        RTStrPrintf(&pchStrTab[paSymbols[2].st_name], cchName + sizeof("_end"), "%s_end", pImage->szName);
+        paSymbols[1].st_info = 't';
+        paSymbols[2].st_info = 'b';
+        paSymbols[1].st_other = 0;
+        paSymbols[2].st_other = 0;
+        paSymbols[1].st_shndx = 0;
+        paSymbols[2].st_shndx = 0;
+        paSymbols[1].st_value = (uintptr_t)pImage->pvImage;
+        paSymbols[2].st_value = (uintptr_t)pImage->pvImage + pImage->cbImageBits - 1;
+        paSymbols[1].st_size  = pImage->cbImageBits - 1;
+        paSymbols[2].st_size  = 1;
+# endif
+        /* No arguments, but seems its always non-NULL so put empty string there. */
+        pMyMod->args                = "";
+
+# ifdef CONFIG_SMP
+        /* No per CPU data. */
+        pMyMod->percpu              = NULL;
+        pMyMod->percpu_size         = 0;
+# endif
+# ifdef CONFIG_TRACEPOINTS
+        /* No tracepoints we like to share. */
+        pMyMod->num_tracepoints     = 0;
+        pMyMod->tracepoints_ptrs    = NULL;
+#endif
+# ifdef HAVE_JUMP_LABEL
+        /* No jump lable stuff either. */
+        pMyMod->jump_entries        = NULL;
+        pMyMod->num_jump_entries    = 0;
+# endif
+# ifdef CONFIG_TRACING
+        pMyMod->num_trace_bprintk_fmt   = 0;
+        pMyMod->trace_bprintk_fmt_start = NULL;
+# endif
+# ifdef CONFIG_EVENT_TRACING
+        pMyMod->trace_events        = NULL;
+        pMyMod->num_trace_events    = 0;
+# endif
+# ifdef CONFIG_FTRACE_MCOUNT_RECORD
+        pMyMod->num_ftrace_callsites = 0;
+        pMyMod->ftrace_callsites    = NULL;
+# endif
+# ifdef CONFIG_MODULE_UNLOAD
+        /* Dependency lists, not worth sharing */
+        INIT_LIST_HEAD(&pMyMod->source_list);
+        INIT_LIST_HEAD(&pMyMod->target_list);
+
+        /* Nobody waiting and no exit function. */
+#  if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
+        pMyMod->waiter              = NULL;
+#  endif
+        pMyMod->exit                = NULL;
+
+        /* References, very important as we must not allow the module
+           to be unloaded using rmmod. */
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
+        atomic_set(&pMyMod->refcnt, 42);
+#  else
+        pMyMod->refptr              = alloc_percpu(struct module_ref);
+        if (pMyMod->refptr)
+        {
+            int iCpu;
+            for_each_possible_cpu(iCpu)
+            {
+                per_cpu_ptr(pMyMod->refptr, iCpu)->decs = 0;
+                per_cpu_ptr(pMyMod->refptr, iCpu)->incs = 1;
+            }
+        }
+        else
+            rc = VERR_NO_MEMORY;
+#  endif
+# endif
+# ifdef CONFIG_CONSTRUCTORS
+        /* No constructors. */
+        pMyMod->ctors               = NULL;
+        pMyMod->num_ctors           = 0;
+# endif
+        if (RT_SUCCESS(rc))
+        {
+            bool fIsModText;
+
+            /*
+             * Add the module to the list.
+             */
+            mutex_lock(&module_mutex);
+            list_add_rcu(&pMyMod->list, &pSelfMod->list);
+            pImage->pLnxModHack = pMyMod;
+# ifdef CONFIG_MODULES_TREE_LOOKUP
+            g_pfnModTreeInsert(&pMyMod->mtn_core); /* __mod_tree_insert */
+# endif
+            mutex_unlock(&module_mutex);
+
+#if 0 /* Horrible, non-working hack.  Debug when __mod_tree_remove can't be found on a box we care about.  */
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_MODULES_TREE_LOOKUP)
+#  if defined(CONFIG_DYNAMIC_FTRACE)
+            /*
+             * Starting with 4.2 there's the module tree lookup which thwarts
+             * the above module hack.  So, we must install an additional hack
+             * to get the job done.  This relies on dynmaic ftrace trampolines
+             * and is just as ugly as the above.  Only for debugging!!
+             */
+            uint32_t i = 0;
+            while (i < RT_ELEMENTS(g_aFTraceOps)
+                   && ASMAtomicXchgBool(&g_aFTraceOps[i].fUsed, true) == true)
+                i++;
+            if (i < RT_ELEMENTS(g_aFTraceOps))
+            {
+                struct supdrv_ftrace_ops *pOps = &g_aFTraceOps[i];
+                pOps->Core.func              = supdrvLnxFTraceStub;
+                pOps->Core.flags             = /*FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB |*/ FTRACE_OPS_FL_DYNAMIC;
+                pOps->Core.trampoline        = (uintptr_t)pImage->pvImage;
+                pOps->Core.trampoline_size   = (uintptr_t)pImage->cbImageBits;
+
+                rc = register_ftrace_function(&pOps->Core);
+                if (rc == 0)
+                    pImage->pLnxFTraceHack = pOps;
+                else
+                    printk(KERN_ERR "vboxdrv: register_ftrace_function failed: %d\n", rc);
+            }
+#  else
+#   error "Sorry, without CONFIG_DYNAMIC_FTRACE currently not possible to get proper stack traces"
+#  endif
+# endif
+#endif
+            /*
+             * Test it.
+             */
+            mutex_lock(&module_mutex);
+            pTestModByName = find_module(pMyMod->name);
+            pTestMod = __module_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 4);
+            fIsModText = __module_text_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 2);
+            mutex_unlock(&module_mutex);
+            if (   pTestMod == pMyMod
+                && pTestModByName == pMyMod
+                && fIsModText)
+                printk(KERN_ERR "vboxdrv: fake module works for '%s' (%#lx to %#lx)\n",
+                       pMyMod->name, (unsigned long)paSymbols[1].st_value, (unsigned long)paSymbols[2].st_value);
+            else
+                printk(KERN_ERR "vboxdrv: failed to find fake module (pTestMod=%p, pTestModByName=%p, pMyMod=%p, fIsModText=%d)\n",
+                       pTestMod, pTestModByName, pMyMod, fIsModText);
+        }
+        else
+            RTMemFree(pMyMod);
+    }
+
+    IPRT_LINUX_RESTORE_EFL_AC();
+#else
+    pImage->pLnxModHack    = NULL;
+    pImage->pLnxFTraceHack = NULL;
+#endif
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */
+    struct module *pMyMod = pImage->pLnxModHack;
+    pImage->pLnxModHack = NULL;
+    if (pMyMod)
+    {
+        /*
+         * Remove the fake module list entry and free it.
+         */
+        IPRT_LINUX_SAVE_EFL_AC();
+        mutex_lock(&module_mutex);
+        list_del_rcu(&pMyMod->list);
+# ifdef CONFIG_MODULES_TREE_LOOKUP
+        g_pfnModTreeRemove(&pMyMod->mtn_core);
+# endif
+        synchronize_sched();
+        mutex_unlock(&module_mutex);
+
+# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
+        free_percpu(pMyMod->refptr);
+# endif
+        RTMemFree(pMyMod);
+        IPRT_LINUX_RESTORE_EFL_AC();
+    }
+
+#if 0 /* Butt-ugly and ain't working yet. */
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_MODULES_TREE_LOOKUP)
+#  if defined(CONFIG_DYNAMIC_FTRACE)
+    {
+        /*
+         * Undo the ftrace hack.
+         */
+        struct supdrv_ftrace_ops *pOps = pImage->pLnxFTraceHack;
+        pImage->pLnxFTraceHack = NULL;
+        if (pOps)
+        {
+            IPRT_LINUX_SAVE_EFL_AC();
+            int rc = unregister_ftrace_function(&pOps->Core);
+            if (rc == 0)
+                ASMAtomicWriteBool(&pOps->fUsed, false);
+            else
+                printk(KERN_ERR "vboxdrv: unregister_ftrace_function failed: %d\n", rc);
+            IPRT_LINUX_RESTORE_EFL_AC();
+        }
+    }
+#  else
+#   error "Sorry, without CONFIG_DYNAMIC_FTRACE currently not possible to get proper stack traces"
+#  endif
+# endif
+#endif
+
+#else
+    Assert(pImage->pLnxModHack == NULL);
+#endif
     NOREF(pDevExt); NOREF(pImage);
 }
Index: /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 58872)
@@ -428,10 +428,4 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
-}
-
-
 int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
 {
@@ -449,4 +443,16 @@
 
 void VBOXCALL   supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+    NOREF(pDevExt); NOREF(pImage);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
     NOREF(pDevExt); NOREF(pImage);
Index: /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 58872)
@@ -1062,10 +1062,4 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
-}
-
-
 int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
 {
@@ -1212,10 +1206,4 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
-}
-
-
 int  VBOXCALL   supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
 {
@@ -1238,4 +1226,16 @@
 
 #endif /* !VBOX_WITH_NATIVE_SOLARIS_LOADING */
+
+
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
+}
+
+
+void VBOXCALL   supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
+{
+    NOREF(pDevExt); NOREF(pImage);
+}
 
 
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 58871)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 58872)
@@ -1829,7 +1829,7 @@
 
 
-void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
-{
-    NOREF(pDevExt); NOREF(pImage);
+void VBOXCALL   supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
+{
+    NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
 }
 
