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

Cache object: 4cc3632245b5063a745df807a2dddc91


[ 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.