The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_linker.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1997 Doug Rabson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 #include "opt_ddb.h"
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/systm.h>
   34 #include <sys/malloc.h>
   35 #include <sys/sysproto.h>
   36 #include <sys/sysent.h>
   37 #include <sys/proc.h>
   38 #include <sys/lock.h>
   39 #include <sys/module.h>
   40 #include <sys/linker.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/libkern.h>
   43 #include <sys/namei.h>
   44 #include <sys/vnode.h>
   45 #include <sys/sysctl.h>
   46 
   47 #include <vm/vm_zone.h>
   48 
   49 #ifdef KLD_DEBUG
   50 int kld_debug = 0;
   51 #endif
   52 
   53 MALLOC_DEFINE(M_LINKER, "kld", "kernel linker");
   54 linker_file_t linker_current_file;
   55 linker_file_t linker_kernel_file;
   56 
   57 static struct lock lock;        /* lock for the file list */
   58 static linker_class_list_t classes;
   59 static linker_file_list_t linker_files;
   60 static int next_file_id = 1;
   61 
   62 static void
   63 linker_init(void* arg)
   64 {
   65     lockinit(&lock, PVM, "klink", 0, 0);
   66     TAILQ_INIT(&classes);
   67     TAILQ_INIT(&linker_files);
   68 }
   69 
   70 SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
   71 
   72 int
   73 linker_add_class(const char* desc, void* priv,
   74                  struct linker_class_ops* ops)
   75 {
   76     linker_class_t lc;
   77 
   78     lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT);
   79     if (!lc)
   80         return ENOMEM;
   81     bzero(lc, sizeof(*lc));
   82 
   83     lc->desc = desc;
   84     lc->priv = priv;
   85     lc->ops = ops;
   86     TAILQ_INSERT_HEAD(&classes, lc, link);
   87 
   88     return 0;
   89 }
   90 
   91 static int
   92 linker_file_sysinit(linker_file_t lf)
   93 {
   94     struct linker_set* sysinits;
   95     struct sysinit** sipp;
   96     struct sysinit** xipp;
   97     struct sysinit* save;
   98     const moduledata_t *moddata;
   99     int error;
  100 
  101     KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
  102                    lf->filename));
  103 
  104     sysinits = (struct linker_set*)
  105         linker_file_lookup_symbol(lf, "sysinit_set", 0);
  106 
  107     KLD_DPF(FILE, ("linker_file_sysinit: SYSINITs %p\n", sysinits));
  108     if (!sysinits)
  109         return 0; /* XXX is this correct ? No sysinit ? */
  110 
  111     /* HACK ALERT! */
  112     for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
  113         if ((*sipp)->func == module_register_init) {
  114             moddata = (*sipp)->udata;
  115             error = module_register(moddata, lf);
  116             if (error) {
  117                 printf("linker_file_sysinit \"%s\" failed to register! %d\n",
  118                     lf->filename, error);
  119                 return error;
  120             }
  121         }
  122     }
  123             
  124     /*
  125      * Perform a bubble sort of the system initialization objects by
  126      * their subsystem (primary key) and order (secondary key).
  127      *
  128      * Since some things care about execution order, this is the
  129      * operation which ensures continued function.
  130      */
  131     for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
  132         for (xipp = sipp + 1; *xipp; xipp++) {
  133             if ((*sipp)->subsystem < (*xipp)->subsystem ||
  134                  ((*sipp)->subsystem == (*xipp)->subsystem &&
  135                   (*sipp)->order <= (*xipp)->order))
  136                 continue;       /* skip*/
  137             save = *sipp;
  138             *sipp = *xipp;
  139             *xipp = save;
  140         }
  141     }
  142 
  143 
  144     /*
  145      * Traverse the (now) ordered list of system initialization tasks.
  146      * Perform each task, and continue on to the next task.
  147      */
  148     for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
  149         if ((*sipp)->subsystem == SI_SUB_DUMMY)
  150             continue;   /* skip dummy task(s)*/
  151 
  152         /* Call function */
  153         (*((*sipp)->func))((*sipp)->udata);
  154     }
  155     return 0; /* no errors */
  156 }
  157 
  158 static void
  159 linker_file_sysuninit(linker_file_t lf)
  160 {
  161     struct linker_set* sysuninits;
  162     struct sysinit** sipp;
  163     struct sysinit** xipp;
  164     struct sysinit* save;
  165 
  166     KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
  167                    lf->filename));
  168 
  169     sysuninits = (struct linker_set*)
  170         linker_file_lookup_symbol(lf, "sysuninit_set", 0);
  171 
  172     KLD_DPF(FILE, ("linker_file_sysuninit: SYSUNINITs %p\n", sysuninits));
  173     if (!sysuninits)
  174         return;
  175 
  176     /*
  177      * Perform a reverse bubble sort of the system initialization objects
  178      * by their subsystem (primary key) and order (secondary key).
  179      *
  180      * Since some things care about execution order, this is the
  181      * operation which ensures continued function.
  182      */
  183     for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) {
  184         for (xipp = sipp + 1; *xipp; xipp++) {
  185             if ((*sipp)->subsystem > (*xipp)->subsystem ||
  186                  ((*sipp)->subsystem == (*xipp)->subsystem &&
  187                   (*sipp)->order >= (*xipp)->order))
  188                 continue;       /* skip*/
  189             save = *sipp;
  190             *sipp = *xipp;
  191             *xipp = save;
  192         }
  193     }
  194 
  195 
  196     /*
  197      * Traverse the (now) ordered list of system initialization tasks.
  198      * Perform each task, and continue on to the next task.
  199      */
  200     for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) {
  201         if ((*sipp)->subsystem == SI_SUB_DUMMY)
  202             continue;   /* skip dummy task(s)*/
  203 
  204         /* Call function */
  205         (*((*sipp)->func))((*sipp)->udata);
  206     }
  207 }
  208 
  209 static void
  210 linker_file_register_sysctls(linker_file_t lf)
  211 {
  212     struct linker_set* sysctls;
  213 
  214     KLD_DPF(FILE, ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
  215                    lf->filename));
  216 
  217     sysctls = (struct linker_set*)
  218         linker_file_lookup_symbol(lf, "sysctl_set", 0);
  219 
  220     KLD_DPF(FILE, ("linker_file_register_sysctls: SYSCTLs %p\n", sysctls));
  221     if (!sysctls)
  222         return;
  223 
  224     sysctl_register_set(sysctls);
  225 }
  226 
  227 static void
  228 linker_file_unregister_sysctls(linker_file_t lf)
  229 {
  230     struct linker_set* sysctls;
  231 
  232     KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs for %s\n",
  233                    lf->filename));
  234 
  235     sysctls = (struct linker_set*)
  236         linker_file_lookup_symbol(lf, "sysctl_set", 0);
  237 
  238     KLD_DPF(FILE, ("linker_file_unregister_sysctls: SYSCTLs %p\n", sysctls));
  239     if (!sysctls)
  240         return;
  241 
  242     sysctl_unregister_set(sysctls);
  243 }
  244 
  245 int
  246 linker_load_file(const char* filename, linker_file_t* result)
  247 {
  248     linker_class_t lc;
  249     linker_file_t lf;
  250     int foundfile, error = 0;
  251     char *koname = NULL;
  252 
  253     /* Refuse to load modules if securelevel raised */
  254     if (securelevel > 0)
  255         return EPERM; 
  256 
  257     lf = linker_find_file_by_name(filename);
  258     if (lf) {
  259         KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename));
  260         *result = lf;
  261         lf->refs++;
  262         goto out;
  263     }
  264 
  265     koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
  266     if (koname == NULL) {
  267         error = ENOMEM;
  268         goto out;
  269     }
  270     sprintf(koname, "%s.ko", filename);
  271     lf = NULL;
  272     foundfile = 0;
  273     for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) {
  274         KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n",
  275                        filename, lc->desc));
  276 
  277         error = lc->ops->load_file(koname, &lf);        /* First with .ko */
  278         if (lf == NULL && error == ENOENT)
  279             error = lc->ops->load_file(filename, &lf);  /* Then try without */
  280         /*
  281          * If we got something other than ENOENT, then it exists but we cannot
  282          * load it for some other reason.
  283          */
  284         if (error != ENOENT)
  285             foundfile = 1;
  286         if (lf) {
  287             linker_file_register_sysctls(lf);
  288             error = linker_file_sysinit(lf);
  289 
  290             *result = lf;
  291             goto out;
  292         }
  293     }
  294     /*
  295      * Less than ideal, but tells the user whether it failed to load or
  296      * the module was not found.
  297      */
  298     if (foundfile)
  299         error = ENOEXEC;        /* Format not recognised (or unloadable) */
  300     else
  301         error = ENOENT;         /* Nothing found */
  302 
  303 out:
  304     if (koname)
  305         free(koname, M_LINKER);
  306     return error;
  307 }
  308 
  309 linker_file_t
  310 linker_find_file_by_name(const char* filename)
  311 {
  312     linker_file_t lf = 0;
  313     char *koname;
  314 
  315     koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
  316     if (koname == NULL)
  317         goto out;
  318     sprintf(koname, "%s.ko", filename);
  319 
  320     lockmgr(&lock, LK_SHARED, 0, curproc);
  321     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  322         if (!strcmp(lf->filename, koname))
  323             break;
  324         if (!strcmp(lf->filename, filename))
  325             break;
  326     }
  327     lockmgr(&lock, LK_RELEASE, 0, curproc);
  328 
  329 out:
  330     if (koname)
  331         free(koname, M_LINKER);
  332     return lf;
  333 }
  334 
  335 linker_file_t
  336 linker_find_file_by_id(int fileid)
  337 {
  338     linker_file_t lf = 0;
  339 
  340     lockmgr(&lock, LK_SHARED, 0, curproc);
  341     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link))
  342         if (lf->id == fileid)
  343             break;
  344     lockmgr(&lock, LK_RELEASE, 0, curproc);
  345 
  346     return lf;
  347 }
  348 
  349 linker_file_t
  350 linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops)
  351 {
  352     linker_file_t lf = 0;
  353     int namelen;
  354     const char *filename;
  355 
  356     filename = rindex(pathname, '/');
  357     if (filename && filename[1])
  358         filename++;
  359     else
  360         filename = pathname;
  361 
  362     KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
  363     lockmgr(&lock, LK_EXCLUSIVE, 0, curproc);
  364     namelen = strlen(filename) + 1;
  365     lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK);
  366     if (!lf)
  367         goto out;
  368     bzero(lf, sizeof(*lf));
  369 
  370     lf->refs = 1;
  371     lf->userrefs = 0;
  372     lf->flags = 0;
  373     lf->filename = (char*) (lf + 1);
  374     strcpy(lf->filename, filename);
  375     lf->id = next_file_id++;
  376     lf->ndeps = 0;
  377     lf->deps = NULL;
  378     STAILQ_INIT(&lf->common);
  379     TAILQ_INIT(&lf->modules);
  380 
  381     lf->priv = priv;
  382     lf->ops = ops;
  383     TAILQ_INSERT_TAIL(&linker_files, lf, link);
  384 
  385 out:
  386     lockmgr(&lock, LK_RELEASE, 0, curproc);
  387     return lf;
  388 }
  389 
  390 int
  391 linker_file_unload(linker_file_t file)
  392 {
  393     module_t mod, next;
  394     struct common_symbol* cp;
  395     int error = 0;
  396     int i;
  397 
  398     /* Refuse to unload modules if securelevel raised */
  399     if (securelevel > 0)
  400         return EPERM; 
  401 
  402     KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
  403     lockmgr(&lock, LK_EXCLUSIVE, 0, curproc);
  404     if (file->refs == 1) {
  405         KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
  406         /*
  407          * Inform any modules associated with this file.
  408          */
  409         for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
  410             next = module_getfnext(mod);
  411 
  412             /*
  413              * Give the module a chance to veto the unload.
  414              */
  415             if ((error = module_unload(mod)) != 0) {
  416                 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
  417                                mod));
  418                 lockmgr(&lock, LK_RELEASE, 0, curproc);
  419                 goto out;
  420             }
  421 
  422             module_release(mod);
  423         }
  424     }
  425 
  426     file->refs--;
  427     if (file->refs > 0) {
  428         lockmgr(&lock, LK_RELEASE, 0, curproc);
  429         goto out;
  430     }
  431 
  432     /* Don't try to run SYSUNINITs if we are unloaded due to a link error */
  433     if (file->flags & LINKER_FILE_LINKED) {
  434         linker_file_sysuninit(file);
  435         linker_file_unregister_sysctls(file);
  436     }
  437 
  438     TAILQ_REMOVE(&linker_files, file, link);
  439     lockmgr(&lock, LK_RELEASE, 0, curproc);
  440 
  441     for (i = 0; i < file->ndeps; i++)
  442         linker_file_unload(file->deps[i]);
  443     free(file->deps, M_LINKER);
  444 
  445     for (cp = STAILQ_FIRST(&file->common); cp;
  446          cp = STAILQ_FIRST(&file->common)) {
  447         STAILQ_REMOVE(&file->common, cp, common_symbol, link);
  448         free(cp, M_LINKER);
  449     }
  450 
  451     file->ops->unload(file);
  452     free(file, M_LINKER);
  453 
  454 out:
  455     return error;
  456 }
  457 
  458 int
  459 linker_file_add_dependancy(linker_file_t file, linker_file_t dep)
  460 {
  461     linker_file_t* newdeps;
  462 
  463     newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*),
  464                      M_LINKER, M_WAITOK);
  465     if (newdeps == NULL)
  466         return ENOMEM;
  467     bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*));
  468 
  469     if (file->deps) {
  470         bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*));
  471         free(file->deps, M_LINKER);
  472     }
  473     file->deps = newdeps;
  474     file->deps[file->ndeps] = dep;
  475     file->ndeps++;
  476 
  477     return 0;
  478 }
  479 
  480 caddr_t
  481 linker_file_lookup_symbol(linker_file_t file, const char* name, int deps)
  482 {
  483     c_linker_sym_t sym;
  484     linker_symval_t symval;
  485     linker_file_t lf;
  486     caddr_t address;
  487     size_t common_size = 0;
  488     int i;
  489 
  490     KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n",
  491                   file, name, deps));
  492 
  493     if (file->ops->lookup_symbol(file, name, &sym) == 0) {
  494         file->ops->symbol_values(file, sym, &symval);
  495         if (symval.value == 0)
  496             /*
  497              * For commons, first look them up in the dependancies and
  498              * only allocate space if not found there.
  499              */
  500             common_size = symval.size;
  501         else {
  502             KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value));
  503             return symval.value;
  504         }
  505     }
  506 
  507     if (deps) {
  508         for (i = 0; i < file->ndeps; i++) {
  509             address = linker_file_lookup_symbol(file->deps[i], name, 0);
  510             if (address) {
  511                 KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address));
  512                 return address;
  513             }
  514         }
  515 
  516         /* If we have not found it in the dependencies, search globally */
  517         for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  518             /* But skip the current file if it's on the list */
  519             if (lf == file)
  520                 continue;
  521             /* And skip the files we searched above */
  522             for (i = 0; i < file->ndeps; i++)
  523                 if (lf == file->deps[i])
  524                     break;
  525             if (i < file->ndeps)
  526                 continue;
  527             address = linker_file_lookup_symbol(lf, name, 0);
  528             if (address) {
  529                 KLD_DPF(SYM, ("linker_file_lookup_symbol: global value=%x\n", address));
  530                 return address;
  531             }
  532         }
  533     }
  534 
  535     if (common_size > 0) {
  536         /*
  537          * This is a common symbol which was not found in the
  538          * dependancies.  We maintain a simple common symbol table in
  539          * the file object.
  540          */
  541         struct common_symbol* cp;
  542 
  543         for (cp = STAILQ_FIRST(&file->common); cp;
  544              cp = STAILQ_NEXT(cp, link))
  545             if (!strcmp(cp->name, name)) {
  546                 KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address));
  547                 return cp->address;
  548             }
  549 
  550         /*
  551          * Round the symbol size up to align.
  552          */
  553         common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
  554         cp = malloc(sizeof(struct common_symbol)
  555                     + common_size
  556                     + strlen(name) + 1,
  557                     M_LINKER, M_WAITOK);
  558         if (!cp) {
  559             KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
  560             return 0;
  561         }
  562         bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1);
  563 
  564         cp->address = (caddr_t) (cp + 1);
  565         cp->name = cp->address + common_size;
  566         strcpy(cp->name, name);
  567         bzero(cp->address, common_size);
  568         STAILQ_INSERT_TAIL(&file->common, cp, link);
  569 
  570         KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address));
  571         return cp->address;
  572     }
  573 
  574     KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
  575     return 0;
  576 }
  577 
  578 #ifdef DDB
  579 /*
  580  * DDB Helpers.  DDB has to look across multiple files with their own
  581  * symbol tables and string tables.
  582  *
  583  * Note that we do not obey list locking protocols here.  We really don't
  584  * need DDB to hang because somebody's got the lock held.  We'll take the
  585  * chance that the files list is inconsistant instead.
  586  */
  587 
  588 int
  589 linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
  590 {
  591     linker_file_t lf;
  592 
  593     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  594         if (lf->ops->lookup_symbol(lf, symstr, sym) == 0)
  595             return 0;
  596     }
  597     return ENOENT;
  598 }
  599 
  600 int
  601 linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
  602 {
  603     linker_file_t lf;
  604     u_long off = (uintptr_t)value;
  605     u_long diff, bestdiff;
  606     c_linker_sym_t best;
  607     c_linker_sym_t es;
  608 
  609     best = 0;
  610     bestdiff = off;
  611     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  612         if (lf->ops->search_symbol(lf, value, &es, &diff) != 0)
  613             continue;
  614         if (es != 0 && diff < bestdiff) {
  615             best = es;
  616             bestdiff = diff;
  617         }
  618         if (bestdiff == 0)
  619             break;
  620     }
  621     if (best) {
  622         *sym = best;
  623         *diffp = bestdiff;
  624         return 0;
  625     } else {
  626         *sym = 0;
  627         *diffp = off;
  628         return ENOENT;
  629     }
  630 }
  631 
  632 int
  633 linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
  634 {
  635     linker_file_t lf;
  636 
  637     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  638         if (lf->ops->symbol_values(lf, sym, symval) == 0)
  639             return 0;
  640     }
  641     return ENOENT;
  642 }
  643 
  644 #endif
  645 
  646 /*
  647  * Syscalls.
  648  */
  649 
  650 int
  651 kldload(struct proc* p, struct kldload_args* uap)
  652 {
  653     char* filename = NULL, *modulename;
  654     linker_file_t lf;
  655     int error = 0;
  656 
  657     p->p_retval[0] = -1;
  658 
  659     if (securelevel > 0)        /* redundant, but that's OK */
  660         return EPERM;
  661 
  662     if ((error = suser(p)) != 0)
  663         return error;
  664 
  665     filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  666     if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0)
  667         goto out;
  668 
  669     /* Can't load more than one module with the same name */
  670     modulename = rindex(filename, '/');
  671     if (modulename == NULL)
  672         modulename = filename;
  673     else
  674         modulename++;
  675     if (linker_find_file_by_name(modulename)) {
  676         error = EEXIST;
  677         goto out;
  678     }
  679 
  680     if ((error = linker_load_file(filename, &lf)) != 0)
  681         goto out;
  682 
  683     lf->userrefs++;
  684     p->p_retval[0] = lf->id;
  685 
  686 out:
  687     if (filename)
  688         free(filename, M_TEMP);
  689     return error;
  690 }
  691 
  692 int
  693 kldunload(struct proc* p, struct kldunload_args* uap)
  694 {
  695     linker_file_t lf;
  696     int error = 0;
  697 
  698     if (securelevel > 0)        /* redundant, but that's OK */
  699         return EPERM;
  700 
  701     if ((error = suser(p)) != 0)
  702         return error;
  703 
  704     lf = linker_find_file_by_id(SCARG(uap, fileid));
  705     if (lf) {
  706         KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
  707         if (lf->userrefs == 0) {
  708             printf("linkerunload: attempt to unload file that was loaded by the kernel\n");
  709             error = EBUSY;
  710             goto out;
  711         }
  712         lf->userrefs--;
  713         error = linker_file_unload(lf);
  714         if (error)
  715             lf->userrefs++;
  716     } else
  717         error = ENOENT;
  718 
  719 out:
  720     return error;
  721 }
  722 
  723 int
  724 kldfind(struct proc* p, struct kldfind_args* uap)
  725 {
  726     char* filename = NULL, *modulename;
  727     linker_file_t lf;
  728     int error = 0;
  729 
  730     p->p_retval[0] = -1;
  731 
  732     filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  733     if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0)
  734         goto out;
  735 
  736     modulename = rindex(filename, '/');
  737     if (modulename == NULL)
  738         modulename = filename;
  739 
  740     lf = linker_find_file_by_name(modulename);
  741     if (lf)
  742         p->p_retval[0] = lf->id;
  743     else
  744         error = ENOENT;
  745 
  746 out:
  747     if (filename)
  748         free(filename, M_TEMP);
  749     return error;
  750 }
  751 
  752 int
  753 kldnext(struct proc* p, struct kldnext_args* uap)
  754 {
  755     linker_file_t lf;
  756     int error = 0;
  757 
  758     if (SCARG(uap, fileid) == 0) {
  759         if (TAILQ_FIRST(&linker_files))
  760             p->p_retval[0] = TAILQ_FIRST(&linker_files)->id;
  761         else
  762             p->p_retval[0] = 0;
  763         return 0;
  764     }
  765 
  766     lf = linker_find_file_by_id(SCARG(uap, fileid));
  767     if (lf) {
  768         if (TAILQ_NEXT(lf, link))
  769             p->p_retval[0] = TAILQ_NEXT(lf, link)->id;
  770         else
  771             p->p_retval[0] = 0;
  772     } else
  773         error = ENOENT;
  774 
  775     return error;
  776 }
  777 
  778 int
  779 kldstat(struct proc* p, struct kldstat_args* uap)
  780 {
  781     linker_file_t lf;
  782     int error = 0;
  783     int version;
  784     struct kld_file_stat* stat;
  785     int namelen;
  786 
  787     lf = linker_find_file_by_id(SCARG(uap, fileid));
  788     if (!lf) {
  789         error = ENOENT;
  790         goto out;
  791     }
  792 
  793     stat = SCARG(uap, stat);
  794 
  795     /*
  796      * Check the version of the user's structure.
  797      */
  798     if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
  799         goto out;
  800     if (version != sizeof(struct kld_file_stat)) {
  801         error = EINVAL;
  802         goto out;
  803     }
  804 
  805     namelen = strlen(lf->filename) + 1;
  806     if (namelen > MAXPATHLEN)
  807         namelen = MAXPATHLEN;
  808     if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0)
  809         goto out;
  810     if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0)
  811         goto out;
  812     if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0)
  813         goto out;
  814     if ((error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) != 0)
  815         goto out;
  816     if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0)
  817         goto out;
  818 
  819     p->p_retval[0] = 0;
  820 
  821 out:
  822     return error;
  823 }
  824 
  825 int
  826 kldfirstmod(struct proc* p, struct kldfirstmod_args* uap)
  827 {
  828     linker_file_t lf;
  829     int error = 0;
  830 
  831     lf = linker_find_file_by_id(SCARG(uap, fileid));
  832     if (lf) {
  833         if (TAILQ_FIRST(&lf->modules))
  834             p->p_retval[0] = module_getid(TAILQ_FIRST(&lf->modules));
  835         else
  836             p->p_retval[0] = 0;
  837     } else
  838         error = ENOENT;
  839 
  840     return error;
  841 }
  842 
  843 int
  844 kldsym(struct proc *p, struct kldsym_args *uap)
  845 {
  846     char *symstr = NULL;
  847     c_linker_sym_t sym;
  848     linker_symval_t symval;
  849     linker_file_t lf;
  850     struct kld_sym_lookup lookup;
  851     int error = 0;
  852 
  853     if ((error = copyin(SCARG(uap, data), &lookup, sizeof(lookup))) != 0)
  854         goto out;
  855     if (lookup.version != sizeof(lookup) || SCARG(uap, cmd) != KLDSYM_LOOKUP) {
  856         error = EINVAL;
  857         goto out;
  858     }
  859 
  860     symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  861     if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
  862         goto out;
  863 
  864     if (SCARG(uap, fileid) != 0) {
  865         lf = linker_find_file_by_id(SCARG(uap, fileid));
  866         if (lf == NULL) {
  867             error = ENOENT;
  868             goto out;
  869         }
  870         if (lf->ops->lookup_symbol(lf, symstr, &sym) == 0 &&
  871             lf->ops->symbol_values(lf, sym, &symval) == 0) {
  872             lookup.symvalue = (uintptr_t)symval.value;
  873             lookup.symsize = symval.size;
  874             error = copyout(&lookup, SCARG(uap, data), sizeof(lookup));
  875         } else
  876             error = ENOENT;
  877     } else {
  878         for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
  879             if (lf->ops->lookup_symbol(lf, symstr, &sym) == 0 &&
  880                 lf->ops->symbol_values(lf, sym, &symval) == 0) {
  881                 lookup.symvalue = (uintptr_t)symval.value;
  882                 lookup.symsize = symval.size;
  883                 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup));
  884                 break;
  885             }
  886         }
  887         if (!lf)
  888             error = ENOENT;
  889     }
  890 out:
  891     if (symstr)
  892         free(symstr, M_TEMP);
  893     return error;
  894 }
  895 
  896 /*
  897  * Preloaded module support
  898  */
  899 
  900 static void
  901 linker_preload(void* arg)
  902 {
  903     caddr_t             modptr;
  904     char                *modname;
  905     char                *modtype;
  906     linker_file_t       lf;
  907     linker_class_t      lc;
  908     int                 error;
  909     struct linker_set   *sysinits;
  910     struct sysinit      **sipp;
  911     const moduledata_t  *moddata;
  912 
  913     modptr = NULL;
  914     while ((modptr = preload_search_next_name(modptr)) != NULL) {
  915         modname = (char *)preload_search_info(modptr, MODINFO_NAME);
  916         modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
  917         if (modname == NULL) {
  918             printf("Preloaded module at %p does not have a name!\n", modptr);
  919             continue;
  920         }
  921         if (modtype == NULL) {
  922             printf("Preloaded module at %p does not have a type!\n", modptr);
  923             continue;
  924         }
  925         printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr);
  926         lf = linker_find_file_by_name(modname);
  927         if (lf) {
  928             lf->userrefs++;
  929             continue;
  930         }
  931         lf = NULL;
  932         for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) {
  933             error = lc->ops->load_file(modname, &lf);
  934             if (error) {
  935                 lf = NULL;
  936                 break;
  937             }
  938         }
  939         if (lf) {
  940             lf->userrefs++;
  941 
  942             sysinits = (struct linker_set*)
  943                 linker_file_lookup_symbol(lf, "sysinit_set", 0);
  944             if (sysinits) {
  945                 /* HACK ALERT!
  946                  * This is to set the sysinit moduledata so that the module
  947                  * can attach itself to the correct containing file.
  948                  * The sysinit could be run at *any* time.
  949                  */
  950                 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
  951                     if ((*sipp)->func == module_register_init) {
  952                         moddata = (*sipp)->udata;
  953                         error = module_register(moddata, lf);
  954                         if (error)
  955                             printf("Preloaded %s \"%s\" failed to register: %d\n",
  956                                 modtype, modname, error);
  957                     }
  958                 }
  959                 sysinit_add((struct sysinit **)sysinits->ls_items);
  960             }
  961             linker_file_register_sysctls(lf);
  962         }
  963     }
  964 }
  965 
  966 SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
  967 
  968 /*
  969  * Search for a not-loaded module by name.
  970  *
  971  * Modules may be found in the following locations:
  972  *
  973  * - preloaded (result is just the module name)
  974  * - on disk (result is full path to module)
  975  *
  976  * If the module name is qualified in any way (contains path, etc.)
  977  * the we simply return a copy of it.
  978  *
  979  * The search path can be manipulated via sysctl.  Note that we use the ';'
  980  * character as a separator to be consistent with the bootloader.
  981  */
  982 
  983 static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/";
  984 
  985 SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
  986               sizeof(linker_path), "module load search path");
  987 
  988 static char *
  989 linker_strdup(const char *str)
  990 {
  991     char        *result;
  992 
  993     if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
  994         strcpy(result, str);
  995     return(result);
  996 }
  997 
  998 char *
  999 linker_search_path(const char *name)
 1000 {
 1001     struct nameidata    nd;
 1002     struct proc         *p = curproc;   /* XXX */
 1003     char                *cp, *ep, *result;
 1004     int                 error;
 1005     enum vtype          type;
 1006 
 1007     /* qualified at all? */
 1008     if (index(name, '/'))
 1009         return(linker_strdup(name));
 1010 
 1011     /* traverse the linker path */
 1012     cp = linker_path;
 1013     for (;;) {
 1014 
 1015         /* find the end of this component */
 1016         for (ep = cp; (*ep != 0) && (*ep != ';'); ep++)
 1017             ;
 1018         result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK);
 1019         if (result == NULL)     /* actually ENOMEM */
 1020             return(NULL);
 1021 
 1022         strncpy(result, cp, ep - cp);
 1023         strcpy(result + (ep - cp), name);
 1024 
 1025         /*
 1026          * Attempt to open the file, and return the path if we succeed and it's
 1027          * a regular file.
 1028          */
 1029         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p);
 1030         error = vn_open(&nd, FREAD, 0);
 1031         if (error == 0) {
 1032             NDFREE(&nd, NDF_ONLY_PNBUF);
 1033             type = nd.ni_vp->v_type;
 1034             VOP_UNLOCK(nd.ni_vp, 0, p);
 1035             vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
 1036             if (type == VREG)
 1037                 return(result);
 1038         }
 1039         free(result, M_LINKER);
 1040 
 1041         if (*ep == 0)
 1042             break;
 1043         cp = ep + 1;
 1044     }
 1045     return(NULL);
 1046 }

Cache object: db2c2735e9bdbd160886ac9476922a1d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.