Fix module loading for vkernel.
[dragonfly.git] / sys / kern / kern_linker.c
index d8a33a1..c1159f3 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_linker.c,v 1.41.2.3 2001/11/21 17:50:35 luigi Exp $
- * $DragonFly: src/sys/kern/kern_linker.c,v 1.33 2007/01/15 20:51:14 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_linker.c,v 1.38 2007/06/07 22:58:11 corecode Exp $
  */
 
 #include "opt_ddb.h"
 
 #include <vm/vm_zone.h>
 
+#ifdef _KERNEL_VIRTUAL
+#include <dlfcn.h>
+#endif
+
 #ifdef KLD_DEBUG
 int kld_debug = 0;
 #endif
@@ -71,7 +75,7 @@ linker_init(void* arg)
     TAILQ_INIT(&linker_files);
 }
 
-SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
+SYSINIT(linker, SI_BOOT2_KLD, SI_ORDER_FIRST, linker_init, 0);
 
 int
 linker_add_class(const char* desc, void* priv,
@@ -146,7 +150,7 @@ linker_file_sysinit(linker_file_t lf)
      * Perform each task, and continue on to the next task.
      */
     for (sipp = start; sipp < stop; sipp++) {
-       if ((*sipp)->subsystem == SI_SUB_DUMMY)
+       if ((*sipp)->subsystem == SI_SPECIAL_DUMMY)
            continue;   /* skip dummy task(s)*/
 
        /* Call function */
@@ -194,7 +198,7 @@ linker_file_sysuninit(linker_file_t lf)
      * Perform each task, and continue on to the next task.
      */
     for (sipp = start; sipp < stop; sipp++) {
-       if ((*sipp)->subsystem == SI_SUB_DUMMY)
+       if ((*sipp)->subsystem == SI_SPECIAL_DUMMY)
            continue;   /* skip dummy task(s)*/
 
        /* Call function */
@@ -622,6 +626,14 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_
        return 0;
     }
 
+#ifdef _KERNEL_VIRTUAL
+    *raddr = dlsym(RTLD_NEXT, name);
+    if (*raddr != NULL) {
+       KLD_DPF(SYM, ("linker_file_lookup_symbol: found dlsym=%x\n", *raddr));
+       return 0;
+    }
+#endif
+
     KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
     return ENOENT;
 }
@@ -1062,7 +1074,7 @@ linker_preload(void* arg)
     }
 }
 
-SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
+SYSINIT(preload, SI_BOOT2_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
 
 /*
  * Search for a not-loaded module by name.
@@ -1079,10 +1091,11 @@ SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
  * character as a separator to be consistent with the bootloader.
  */
 
-static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/";
+static char linker_path[MAXPATHLEN] = "/;/boot;/modules";
 
 SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
              sizeof(linker_path), "module load search path");
+TUNABLE_STR("module_path", linker_path, sizeof(linker_path));
 
 static char *
 linker_strdup(const char *str)
@@ -1099,6 +1112,8 @@ linker_search_path(const char *name)
 {
     struct nlookupdata nd;
     char               *cp, *ep, *result;
+    size_t             name_len, prefix_len;
+    int                        sep;
     int                        error;
     enum vtype         type;
 
@@ -1108,17 +1123,28 @@ linker_search_path(const char *name)
 
     /* traverse the linker path */
     cp = linker_path;
+    name_len = strlen(name);
     for (;;) {
 
        /* find the end of this component */
        for (ep = cp; (*ep != 0) && (*ep != ';'); ep++)
            ;
-       result = kmalloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK);
-       if (result == NULL)     /* actually ENOMEM */
-           return(NULL);
+       prefix_len = ep - cp;
+       /* if this component doesn't end with a slash, add one */
+       if (ep == cp || *(ep - 1) != '/')
+           sep = 1;
+       else
+           sep = 0;
+
+       /*
+        * +2 : possible separator, plus terminator.
+        */
+       result = kmalloc(prefix_len + name_len + 2, M_LINKER, M_WAITOK);
 
-       strncpy(result, cp, ep - cp);
-       strcpy(result + (ep - cp), name);
+       strncpy(result, cp, prefix_len);
+       if (sep)
+           result[prefix_len++] = '/';
+       strcpy(result + prefix_len, name);
 
        /*
         * Attempt to open the file, and return the path if we succeed and it's