125537Sdfr/*-
259603Sdfr * Copyright (c) 1997-2000 Doug Rabson
325537Sdfr * All rights reserved.
425537Sdfr *
525537Sdfr * Redistribution and use in source and binary forms, with or without
625537Sdfr * modification, are permitted provided that the following conditions
725537Sdfr * are met:
825537Sdfr * 1. Redistributions of source code must retain the above copyright
925537Sdfr *    notice, this list of conditions and the following disclaimer.
1025537Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1125537Sdfr *    notice, this list of conditions and the following disclaimer in the
1225537Sdfr *    documentation and/or other materials provided with the distribution.
1325537Sdfr *
1425537Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1525537Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1625537Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1725537Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1825537Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1925537Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2025537Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2125537Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2225537Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2325537Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2425537Sdfr * SUCH DAMAGE.
2525537Sdfr */
2625537Sdfr
27116182Sobrien#include <sys/cdefs.h>
28116182Sobrien__FBSDID("$FreeBSD$");
29116182Sobrien
3040159Speter#include "opt_ddb.h"
31227151Sfjoe#include "opt_kld.h"
32157144Sjkoshy#include "opt_hwpmc_hooks.h"
3340159Speter
3425537Sdfr#include <sys/param.h>
3525537Sdfr#include <sys/kernel.h>
3625537Sdfr#include <sys/systm.h>
3725537Sdfr#include <sys/malloc.h>
3825537Sdfr#include <sys/sysproto.h>
3925537Sdfr#include <sys/sysent.h>
40164033Srwatson#include <sys/priv.h>
4125537Sdfr#include <sys/proc.h>
4225537Sdfr#include <sys/lock.h>
4382749Sdillon#include <sys/mutex.h>
4492547Sarr#include <sys/sx.h>
4525537Sdfr#include <sys/module.h>
46159808Sjhb#include <sys/mount.h>
4725537Sdfr#include <sys/linker.h>
48254266Smarkj#include <sys/eventhandler.h>
4940159Speter#include <sys/fcntl.h>
50192895Sjamie#include <sys/jail.h>
5140159Speter#include <sys/libkern.h>
5240159Speter#include <sys/namei.h>
5340159Speter#include <sys/vnode.h>
54159588Sjhb#include <sys/syscallsubr.h>
5540159Speter#include <sys/sysctl.h>
5625537Sdfr
57196019Srwatson#include <net/vnet.h>
58196019Srwatson
59163606Srwatson#include <security/mac/mac_framework.h>
60163606Srwatson
6159603Sdfr#include "linker_if.h"
6259603Sdfr
63157144Sjkoshy#ifdef HWPMC_HOOKS
64157144Sjkoshy#include <sys/pmckern.h>
65157144Sjkoshy#endif
66157144Sjkoshy
6740961Speter#ifdef KLD_DEBUG
6840961Speterint kld_debug = 0;
69232999SaeSYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW | CTLFLAG_TUN,
70232999Sae    &kld_debug, 0, "Set various levels of KLD debug");
71232997SaeTUNABLE_INT("debug.kld_debug", &kld_debug);
7240961Speter#endif
7340961Speter
7491040Sarr/*
7591040Sarr * static char *linker_search_path(const char *name, struct mod_depend
7691040Sarr * *verinfo);
7791040Sarr */
7891040Sarrstatic const char 	*linker_basename(const char *path);
7959751Speter
80159800Sjhb/*
81159800Sjhb * Find a currently loaded file given its filename.
82159800Sjhb */
83159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
84159800Sjhb
85159800Sjhb/*
86159800Sjhb * Find a currently loaded file given its file id.
87159800Sjhb */
88159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
89159800Sjhb
9078161Speter/* Metadata from the static kernel */
9178161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
9278161Speter
9359751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
9459751Speter
9540906Speterlinker_file_t linker_kernel_file;
9631324Sbde
97159845Sjhbstatic struct sx kld_sx;	/* kernel linker lock */
9898452Sarr
99172862Sjb/*
100172862Sjb * Load counter used by clients to determine if a linker file has been
101172862Sjb * re-loaded. This counter is incremented for each file load.
102172862Sjb */
103172862Sjbstatic int loadcnt;
104172862Sjb
10525537Sdfrstatic linker_class_list_t classes;
10650068Sgrogstatic linker_file_list_t linker_files;
10725537Sdfrstatic int next_file_id = 1;
10898452Sarrstatic int linker_no_more_classes = 0;
10925537Sdfr
11086553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
11191040Sarr	linker_file_t lftmp;						\
11286553Sarr									\
113254810Smarkj	if (!cold)							\
114254810Smarkj		sx_assert(&kld_sx, SA_XLOCKED);				\
11586553Sarrretry:									\
11691040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
11791040Sarr		if (next_file_id == lftmp->id) {			\
11891040Sarr			next_file_id++;					\
11991040Sarr			goto retry;					\
12091040Sarr		}							\
12191040Sarr	}								\
12291040Sarr	(a) = next_file_id;						\
12386553Sarr} while(0)
12486553Sarr
12586553Sarr
12659751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
12760938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
12859751Speterstruct modlist {
12991040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
13091040Sarr	linker_file_t   container;
13191040Sarr	const char 	*name;
13291040Sarr	int             version;
13359751Speter};
13491040Sarrtypedef struct modlist *modlist_t;
13591040Sarrstatic modlisthead_t found_modules;
13659751Speter
137159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
138159796Sjhb		    linker_file_t dep);
139159845Sjhbstatic caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
140159845Sjhb		    const char* name, int deps);
141159796Sjhbstatic int	linker_load_module(const char *kldname,
142159796Sjhb		    const char *modname, struct linker_file *parent,
143159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
144159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
14594321Sbrian
14625537Sdfrstatic void
14791040Sarrlinker_init(void *arg)
14825537Sdfr{
14991040Sarr
150159845Sjhb	sx_init(&kld_sx, "kernel linker");
15191040Sarr	TAILQ_INIT(&classes);
15291040Sarr	TAILQ_INIT(&linker_files);
15325537Sdfr}
15425537Sdfr
155177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
15625537Sdfr
15798452Sarrstatic void
15898452Sarrlinker_stop_class_add(void *arg)
15998452Sarr{
16098452Sarr
16198452Sarr	linker_no_more_classes = 1;
16298452Sarr}
16398452Sarr
164177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL);
16598452Sarr
16625537Sdfrint
16759603Sdfrlinker_add_class(linker_class_t lc)
16825537Sdfr{
16991040Sarr
17098452Sarr	/*
171144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
172144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
173144443Sjhb	 * ops from being freed.
17498452Sarr	 */
17598452Sarr	if (linker_no_more_classes == 1)
17698452Sarr		return (EPERM);
17791040Sarr	kobj_class_compile((kobj_class_t) lc);
178144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
17991040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
18091040Sarr	return (0);
18125537Sdfr}
18225537Sdfr
18325537Sdfrstatic void
18425537Sdfrlinker_file_sysinit(linker_file_t lf)
18525537Sdfr{
18691040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
18725537Sdfr
18891040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
18991040Sarr	    lf->filename));
19025537Sdfr
191254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
192254811Smarkj
19391040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
19491040Sarr		return;
19591040Sarr	/*
19691040Sarr	 * Perform a bubble sort of the system initialization objects by
19791040Sarr	 * their subsystem (primary key) and order (secondary key).
198159840Sjhb	 *
19991040Sarr	 * Since some things care about execution order, this is the operation
20091040Sarr	 * which ensures continued function.
20191040Sarr	 */
20291040Sarr	for (sipp = start; sipp < stop; sipp++) {
20391040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
20491040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
20591040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
20691040Sarr			    (*sipp)->order <= (*xipp)->order))
20791040Sarr				continue;	/* skip */
20891040Sarr			save = *sipp;
20991040Sarr			*sipp = *xipp;
21091040Sarr			*xipp = save;
21191040Sarr		}
21225537Sdfr	}
21325537Sdfr
21491040Sarr	/*
21591040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
21691040Sarr	 * Perform each task, and continue on to the next task.
21791040Sarr	 */
218254811Smarkj	sx_xunlock(&kld_sx);
219160142Sjhb	mtx_lock(&Giant);
22091040Sarr	for (sipp = start; sipp < stop; sipp++) {
22191040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
22291040Sarr			continue;	/* skip dummy task(s) */
22325537Sdfr
22491040Sarr		/* Call function */
22591040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
22691040Sarr	}
227160142Sjhb	mtx_unlock(&Giant);
228254811Smarkj	sx_xlock(&kld_sx);
22925537Sdfr}
23025537Sdfr
23141055Speterstatic void
23241055Speterlinker_file_sysuninit(linker_file_t lf)
23341055Speter{
23491040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
23541055Speter
23691040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
23791040Sarr	    lf->filename));
23841055Speter
239254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
240254811Smarkj
24191068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
24291040Sarr	    NULL) != 0)
24391040Sarr		return;
24441055Speter
24591040Sarr	/*
24691040Sarr	 * Perform a reverse bubble sort of the system initialization objects
24791040Sarr	 * by their subsystem (primary key) and order (secondary key).
248159840Sjhb	 *
24991040Sarr	 * Since some things care about execution order, this is the operation
25091040Sarr	 * which ensures continued function.
25191040Sarr	 */
25291040Sarr	for (sipp = start; sipp < stop; sipp++) {
25391040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
25491040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
25591040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
25691040Sarr			    (*sipp)->order >= (*xipp)->order))
25791040Sarr				continue;	/* skip */
25891040Sarr			save = *sipp;
25991040Sarr			*sipp = *xipp;
26091040Sarr			*xipp = save;
26191040Sarr		}
26241055Speter	}
26341055Speter
26491040Sarr	/*
26591040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
26691040Sarr	 * Perform each task, and continue on to the next task.
26791040Sarr	 */
268254811Smarkj	sx_xunlock(&kld_sx);
269160142Sjhb	mtx_lock(&Giant);
27091040Sarr	for (sipp = start; sipp < stop; sipp++) {
27191040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
27291040Sarr			continue;	/* skip dummy task(s) */
27341055Speter
27491040Sarr		/* Call function */
27591040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
27691040Sarr	}
277160142Sjhb	mtx_unlock(&Giant);
278254811Smarkj	sx_xlock(&kld_sx);
27941055Speter}
28041055Speter
28144078Sdfrstatic void
28244078Sdfrlinker_file_register_sysctls(linker_file_t lf)
28344078Sdfr{
28491040Sarr	struct sysctl_oid **start, **stop, **oidp;
28544078Sdfr
28691040Sarr	KLD_DPF(FILE,
28791040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
28891040Sarr	    lf->filename));
28944078Sdfr
290254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
291254811Smarkj
29291040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
29391040Sarr		return;
29444078Sdfr
295254811Smarkj	sx_xunlock(&kld_sx);
296188232Sjhb	sysctl_lock();
29791040Sarr	for (oidp = start; oidp < stop; oidp++)
29891040Sarr		sysctl_register_oid(*oidp);
299188232Sjhb	sysctl_unlock();
300254811Smarkj	sx_xlock(&kld_sx);
30144078Sdfr}
30244078Sdfr
30344078Sdfrstatic void
30444078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
30544078Sdfr{
30691040Sarr	struct sysctl_oid **start, **stop, **oidp;
30744078Sdfr
308233295Sae	KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs"
30991040Sarr	    " for %s\n", lf->filename));
31044078Sdfr
311254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
312254811Smarkj
31391040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
31491040Sarr		return;
31544078Sdfr
316254811Smarkj	sx_xunlock(&kld_sx);
317188232Sjhb	sysctl_lock();
31891040Sarr	for (oidp = start; oidp < stop; oidp++)
31991040Sarr		sysctl_unregister_oid(*oidp);
320188232Sjhb	sysctl_unlock();
321254811Smarkj	sx_xlock(&kld_sx);
32244078Sdfr}
32344078Sdfr
32459751Speterstatic int
32559751Speterlinker_file_register_modules(linker_file_t lf)
32659751Speter{
32791040Sarr	struct mod_metadata **start, **stop, **mdp;
32891040Sarr	const moduledata_t *moddata;
329146733Spjd	int first_error, error;
33059751Speter
33191040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
33291040Sarr	    " in %s\n", lf->filename));
33359751Speter
334254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
335254811Smarkj
33691068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
337159841Sjhb	    &stop, NULL) != 0) {
33891040Sarr		/*
33991040Sarr		 * This fallback should be unnecessary, but if we get booted
34091040Sarr		 * from boot2 instead of loader and we are missing our
34191040Sarr		 * metadata then we have to try the best we can.
34291040Sarr		 */
34391040Sarr		if (lf == linker_kernel_file) {
34491040Sarr			start = SET_BEGIN(modmetadata_set);
34591040Sarr			stop = SET_LIMIT(modmetadata_set);
34691040Sarr		} else
34791040Sarr			return (0);
34878161Speter	}
349146733Spjd	first_error = 0;
35091040Sarr	for (mdp = start; mdp < stop; mdp++) {
35191040Sarr		if ((*mdp)->md_type != MDT_MODULE)
35291040Sarr			continue;
35391040Sarr		moddata = (*mdp)->md_data;
35491040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
35591040Sarr		    moddata->name, lf->filename));
35691040Sarr		error = module_register(moddata, lf);
357146730Spjd		if (error) {
35891068Sarr			printf("Module %s failed to register: %d\n",
35991040Sarr			    moddata->name, error);
360146733Spjd			if (first_error == 0)
361146733Spjd				first_error = error;
362146730Spjd		}
36359751Speter	}
364146733Spjd	return (first_error);
36559751Speter}
36659751Speter
36759751Speterstatic void
36859751Speterlinker_init_kernel_modules(void)
36959751Speter{
37091040Sarr
371254810Smarkj	sx_xlock(&kld_sx);
37291040Sarr	linker_file_register_modules(linker_kernel_file);
373254810Smarkj	sx_xunlock(&kld_sx);
37459751Speter}
37559751Speter
376177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules,
377177253Srwatson    0);
37859751Speter
379101241Smuxstatic int
38091040Sarrlinker_load_file(const char *filename, linker_file_t *result)
38125537Sdfr{
38291040Sarr	linker_class_t lc;
38391040Sarr	linker_file_t lf;
384234186Sjhb	int foundfile, error, modules;
38525537Sdfr
38691040Sarr	/* Refuse to load modules if securelevel raised */
387192895Sjamie	if (prison0.pr_securelevel > 0)
38891040Sarr		return (EPERM);
38962261Sarchie
390254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
39191040Sarr	lf = linker_find_file_by_name(filename);
39291040Sarr	if (lf) {
39391040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
39491040Sarr		    " incrementing refs\n", filename));
39591040Sarr		*result = lf;
39691040Sarr		lf->refs++;
397159585Sjhb		return (0);
39891040Sarr	}
39991040Sarr	foundfile = 0;
400159585Sjhb	error = 0;
40198452Sarr
40298452Sarr	/*
40398452Sarr	 * We do not need to protect (lock) classes here because there is
40498452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
40598452Sarr	 * and there is no class deregistration mechanism at this time.
40698452Sarr	 */
40791040Sarr	TAILQ_FOREACH(lc, &classes, link) {
40891040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
40991040Sarr		    filename));
41091040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
41191040Sarr		/*
41291040Sarr		 * If we got something other than ENOENT, then it exists but
41391040Sarr		 * we cannot load it for some other reason.
41491040Sarr		 */
41591040Sarr		if (error != ENOENT)
41691040Sarr			foundfile = 1;
41791040Sarr		if (lf) {
418146730Spjd			error = linker_file_register_modules(lf);
419146730Spjd			if (error == EEXIST) {
420146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
421159585Sjhb				return (error);
422146730Spjd			}
423234186Sjhb			modules = !TAILQ_EMPTY(&lf->modules);
42491040Sarr			linker_file_register_sysctls(lf);
42591040Sarr			linker_file_sysinit(lf);
42691040Sarr			lf->flags |= LINKER_FILE_LINKED;
427234186Sjhb
428234186Sjhb			/*
429234186Sjhb			 * If all of the modules in this file failed
430234186Sjhb			 * to load, unload the file and return an
431234186Sjhb			 * error of ENOEXEC.
432234186Sjhb			 */
433234186Sjhb			if (modules && TAILQ_EMPTY(&lf->modules)) {
434234186Sjhb				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
435234186Sjhb				return (ENOEXEC);
436234186Sjhb			}
437262039Savg			EVENTHANDLER_INVOKE(kld_load, lf);
43891040Sarr			*result = lf;
439159585Sjhb			return (0);
44091040Sarr		}
44191040Sarr	}
44242755Speter	/*
44391040Sarr	 * Less than ideal, but tells the user whether it failed to load or
44491040Sarr	 * the module was not found.
44542755Speter	 */
446105337Ssam	if (foundfile) {
447188440Sattilio
448105337Ssam		/*
449188440Sattilio		 * If the file type has not been recognized by the last try
450188440Sattilio		 * printout a message before to fail.
451188440Sattilio		 */
452188440Sattilio		if (error == ENOSYS)
453188440Sattilio			printf("linker_load_file: Unsupported file type\n");
454188440Sattilio
455188440Sattilio		/*
456105337Ssam		 * Format not recognized or otherwise unloadable.
457105337Ssam		 * When loading a module that is statically built into
458105337Ssam		 * the kernel EEXIST percolates back up as the return
459105337Ssam		 * value.  Preserve this so that apps like sysinstall
460105337Ssam		 * can recognize this special case and not post bogus
461105337Ssam		 * dialog boxes.
462105337Ssam		 */
463105337Ssam		if (error != EEXIST)
464105337Ssam			error = ENOEXEC;
465105337Ssam	} else
46691068Sarr		error = ENOENT;		/* Nothing found */
46791040Sarr	return (error);
46825537Sdfr}
46925537Sdfr
47078413Sbrianint
47194321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
47294321Sbrian    linker_file_t *result)
47378413Sbrian{
47494321Sbrian	modlist_t mod;
475159804Sjhb	int error;
47694321Sbrian
477254810Smarkj	sx_xlock(&kld_sx);
47894321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
47994321Sbrian		*result = mod->container;
48094321Sbrian		(*result)->refs++;
481254810Smarkj		sx_xunlock(&kld_sx);
48294321Sbrian		return (0);
48394321Sbrian	}
48494321Sbrian
485159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
486254810Smarkj	sx_xunlock(&kld_sx);
487159804Sjhb	return (error);
48878413Sbrian}
48978413Sbrian
490159804Sjhbint
491159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
492159804Sjhb    linker_file_t lf)
493159804Sjhb{
494159804Sjhb	modlist_t mod;
495159804Sjhb	int error;
496159804Sjhb
497254810Smarkj	sx_xlock(&kld_sx);
498159804Sjhb	if (lf == NULL) {
499159804Sjhb		KASSERT(modname != NULL,
500159804Sjhb		    ("linker_release_module: no file or name"));
501159804Sjhb		mod = modlist_lookup2(modname, verinfo);
502159804Sjhb		if (mod == NULL) {
503254810Smarkj			sx_xunlock(&kld_sx);
504159804Sjhb			return (ESRCH);
505159804Sjhb		}
506159804Sjhb		lf = mod->container;
507159804Sjhb	} else
508159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
509159804Sjhb		    ("linker_release_module: both file and name"));
510159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
511254810Smarkj	sx_xunlock(&kld_sx);
512159804Sjhb	return (error);
513159804Sjhb}
514159804Sjhb
515159800Sjhbstatic linker_file_t
51691040Sarrlinker_find_file_by_name(const char *filename)
51725537Sdfr{
518159585Sjhb	linker_file_t lf;
51991040Sarr	char *koname;
52025537Sdfr
521111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
52291040Sarr	sprintf(koname, "%s.ko", filename);
52340861Speter
524254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
52591040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
52692032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
52791040Sarr			break;
52892032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
52991040Sarr			break;
53091040Sarr	}
531159585Sjhb	free(koname, M_LINKER);
53291040Sarr	return (lf);
53325537Sdfr}
53425537Sdfr
535159800Sjhbstatic linker_file_t
53625537Sdfrlinker_find_file_by_id(int fileid)
53725537Sdfr{
538159585Sjhb	linker_file_t lf;
539159845Sjhb
540254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
54191040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
542166921Sjhb		if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
54391040Sarr			break;
54491040Sarr	return (lf);
54525537Sdfr}
54625537Sdfr
547159797Sjhbint
548159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
549159797Sjhb{
550159797Sjhb	linker_file_t lf;
551159797Sjhb	int retval = 0;
552159797Sjhb
553254810Smarkj	sx_xlock(&kld_sx);
554159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
555159797Sjhb		retval = predicate(lf, context);
556159797Sjhb		if (retval != 0)
557159797Sjhb			break;
558159797Sjhb	}
559254810Smarkj	sx_xunlock(&kld_sx);
560159797Sjhb	return (retval);
561159797Sjhb}
562159797Sjhb
56325537Sdfrlinker_file_t
56491040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
56525537Sdfr{
56691040Sarr	linker_file_t lf;
56791040Sarr	const char *filename;
56825537Sdfr
569254810Smarkj	if (!cold)
570254810Smarkj		sx_assert(&kld_sx, SA_XLOCKED);
57191040Sarr	filename = linker_basename(pathname);
57240159Speter
573172862Sjb	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
574111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
57591040Sarr	if (lf == NULL)
576159585Sjhb		return (NULL);
57791040Sarr	lf->refs = 1;
57891040Sarr	lf->userrefs = 0;
57991040Sarr	lf->flags = 0;
580254396Smarkj	lf->filename = strdup(filename, M_LINKER);
581254396Smarkj	lf->pathname = strdup(pathname, M_LINKER);
58291040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
58391040Sarr	lf->ndeps = 0;
58491040Sarr	lf->deps = NULL;
585172862Sjb	lf->loadcnt = ++loadcnt;
58691040Sarr	STAILQ_INIT(&lf->common);
58791040Sarr	TAILQ_INIT(&lf->modules);
58891040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
58991040Sarr	return (lf);
59025537Sdfr}
59125537Sdfr
59225537Sdfrint
593132117Sphklinker_file_unload(linker_file_t file, int flags)
59425537Sdfr{
59591040Sarr	module_t mod, next;
59691040Sarr	modlist_t ml, nextml;
59791040Sarr	struct common_symbol *cp;
59891040Sarr	int error, i;
59925537Sdfr
60091040Sarr	/* Refuse to unload modules if securelevel raised. */
601192895Sjamie	if (prison0.pr_securelevel > 0)
60291040Sarr		return (EPERM);
60325537Sdfr
604254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
60591040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
60691040Sarr
607159584Sjhb	/* Easy case of just dropping a reference. */
608159584Sjhb	if (file->refs > 1) {
609159584Sjhb		file->refs--;
610159584Sjhb		return (0);
611159584Sjhb	}
612159584Sjhb
613262039Savg	/* Give eventhandlers a chance to prevent the unload. */
614262039Savg	error = 0;
615262039Savg	EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
616262039Savg	if (error != 0)
617262039Savg		return (EBUSY);
618262039Savg
619159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
620159584Sjhb	    " informing modules\n"));
621159584Sjhb
622159584Sjhb	/*
623185635Sjhb	 * Quiesce all the modules to give them a chance to veto the unload.
624159584Sjhb	 */
625185635Sjhb	MOD_SLOCK;
626185635Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod;
627185635Sjhb	     mod = module_getfnext(mod)) {
628185635Sjhb
629185635Sjhb		error = module_quiesce(mod);
630185635Sjhb		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
631185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
632185635Sjhb			    " vetoed unload\n", module_getname(mod)));
633185635Sjhb			/*
634185635Sjhb			 * XXX: Do we need to tell all the quiesced modules
635185635Sjhb			 * that they can resume work now via a new module
636185635Sjhb			 * event?
637185635Sjhb			 */
638185635Sjhb			MOD_SUNLOCK;
639185635Sjhb			return (error);
640185635Sjhb		}
641185635Sjhb	}
642185635Sjhb	MOD_SUNLOCK;
643185635Sjhb
644185635Sjhb	/*
645185635Sjhb	 * Inform any modules associated with this file that they are
646234186Sjhb	 * being unloaded.
647185635Sjhb	 */
648159584Sjhb	MOD_XLOCK;
649159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
650159584Sjhb		next = module_getfnext(mod);
651159584Sjhb		MOD_XUNLOCK;
652159584Sjhb
65391040Sarr		/*
654159584Sjhb		 * Give the module a chance to veto the unload.
65591040Sarr		 */
656185635Sjhb		if ((error = module_unload(mod)) != 0) {
657233276Sae#ifdef KLD_DEBUG
658233276Sae			MOD_SLOCK;
659185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
660199457Sgonzo			    " failed unload\n", module_getname(mod)));
661233276Sae			MOD_SUNLOCK;
662233276Sae#endif
663159584Sjhb			return (error);
664159584Sjhb		}
66592547Sarr		MOD_XLOCK;
666159584Sjhb		module_release(mod);
667159584Sjhb	}
668159584Sjhb	MOD_XUNLOCK;
66991040Sarr
670159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
671128057Speadar		if (ml->container == file) {
67291040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
673128057Speadar			free(ml, M_LINKER);
674128057Speadar		}
67591040Sarr	}
67625537Sdfr
677159840Sjhb	/*
678159840Sjhb	 * Don't try to run SYSUNINITs if we are unloaded due to a
67991040Sarr	 * link error.
68091040Sarr	 */
68191040Sarr	if (file->flags & LINKER_FILE_LINKED) {
682188209Sjhb		file->flags &= ~LINKER_FILE_LINKED;
68391040Sarr		linker_file_sysuninit(file);
68491040Sarr		linker_file_unregister_sysctls(file);
68525537Sdfr	}
68691040Sarr	TAILQ_REMOVE(&linker_files, file, link);
68725537Sdfr
68891040Sarr	if (file->deps) {
68991040Sarr		for (i = 0; i < file->ndeps; i++)
690132117Sphk			linker_file_unload(file->deps[i], flags);
69191040Sarr		free(file->deps, M_LINKER);
69291040Sarr		file->deps = NULL;
69359751Speter	}
694160245Sjhb	while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
695160245Sjhb		STAILQ_REMOVE_HEAD(&file->common, link);
69691040Sarr		free(cp, M_LINKER);
69791040Sarr	}
69859751Speter
69991040Sarr	LINKER_UNLOAD(file);
700262039Savg
701262039Savg	EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
702262039Savg	    file->size);
703262039Savg
70491040Sarr	if (file->filename) {
70591040Sarr		free(file->filename, M_LINKER);
70691040Sarr		file->filename = NULL;
70791040Sarr	}
708172862Sjb	if (file->pathname) {
709172862Sjb		free(file->pathname, M_LINKER);
710172862Sjb		file->pathname = NULL;
711172862Sjb	}
71291040Sarr	kobj_delete((kobj_t) file, M_LINKER);
713159584Sjhb	return (0);
71425537Sdfr}
71525537Sdfr
716179238Sjbint
717179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc)
718179238Sjb{
719179238Sjb	return (LINKER_CTF_GET(file, lc));
720179238Sjb}
721179238Sjb
722159796Sjhbstatic int
72386469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
72425537Sdfr{
72591040Sarr	linker_file_t *newdeps;
72625537Sdfr
727254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
728264370Skib	file->deps = realloc(file->deps, (file->ndeps + 1) * sizeof(*newdeps),
729264370Skib	    M_LINKER, M_WAITOK | M_ZERO);
73091040Sarr	file->deps[file->ndeps] = dep;
73191040Sarr	file->ndeps++;
732199457Sgonzo	KLD_DPF(FILE, ("linker_file_add_dependency:"
733199457Sgonzo	    " adding %s as dependency for %s\n",
734199457Sgonzo	    dep->filename, file->filename));
73591040Sarr	return (0);
73625537Sdfr}
73725537Sdfr
73878161Speter/*
73991040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
740159841Sjhb * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
741159841Sjhb * This function is used in this file so we can avoid having lots of (void **)
742159841Sjhb * casts.
74378161Speter */
74478161Speterint
74578161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
74691040Sarr    void *firstp, void *lastp, int *countp)
74778161Speter{
74878161Speter
749254811Smarkj	sx_assert(&kld_sx, SA_LOCKED);
750254811Smarkj	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
75178161Speter}
75278161Speter
753173714Sjb/*
754173714Sjb * List all functions in a file.
755173714Sjb */
756173714Sjbint
757173714Sjblinker_file_function_listall(linker_file_t lf,
758179238Sjb    linker_function_nameval_callback_t callback_func, void *arg)
759173714Sjb{
760173714Sjb	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
761173714Sjb}
762173714Sjb
76325537Sdfrcaddr_t
76491040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
76525537Sdfr{
766159845Sjhb	caddr_t sym;
767159845Sjhb	int locked;
768159845Sjhb
769254810Smarkj	locked = sx_xlocked(&kld_sx);
770159845Sjhb	if (!locked)
771254810Smarkj		sx_xlock(&kld_sx);
772159845Sjhb	sym = linker_file_lookup_symbol_internal(file, name, deps);
773159845Sjhb	if (!locked)
774254810Smarkj		sx_xunlock(&kld_sx);
775159845Sjhb	return (sym);
776159845Sjhb}
777159845Sjhb
778159845Sjhbstatic caddr_t
779159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name,
780159845Sjhb    int deps)
781159845Sjhb{
78291040Sarr	c_linker_sym_t sym;
78391040Sarr	linker_symval_t symval;
78491040Sarr	caddr_t address;
78591040Sarr	size_t common_size = 0;
78692032Sdwmalone	int i;
78725537Sdfr
788254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
789109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
79091040Sarr	    file, name, deps));
79125537Sdfr
79291040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
79391040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
79491040Sarr		if (symval.value == 0)
79591040Sarr			/*
79691040Sarr			 * For commons, first look them up in the
79791040Sarr			 * dependencies and only allocate space if not found
79891040Sarr			 * there.
79991040Sarr			 */
80091040Sarr			common_size = symval.size;
80191040Sarr		else {
80291040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
803109605Sjake			    ".value=%p\n", symval.value));
80491040Sarr			return (symval.value);
80591040Sarr		}
80640159Speter	}
80791040Sarr	if (deps) {
80891040Sarr		for (i = 0; i < file->ndeps; i++) {
809159845Sjhb			address = linker_file_lookup_symbol_internal(
810159845Sjhb			    file->deps[i], name, 0);
81191040Sarr			if (address) {
81291040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
813109605Sjake				    " deps value=%p\n", address));
81491040Sarr				return (address);
81591040Sarr			}
81691040Sarr		}
81725537Sdfr	}
81891040Sarr	if (common_size > 0) {
81991040Sarr		/*
82091040Sarr		 * This is a common symbol which was not found in the
82191040Sarr		 * dependencies.  We maintain a simple common symbol table in
82291040Sarr		 * the file object.
82391040Sarr		 */
82491040Sarr		struct common_symbol *cp;
82542849Speter
82691040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
82792032Sdwmalone			if (strcmp(cp->name, name) == 0) {
82891040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
829109605Sjake				    " old common value=%p\n", cp->address));
83091040Sarr				return (cp->address);
83191040Sarr			}
83291040Sarr		}
83391040Sarr		/*
83491040Sarr		 * Round the symbol size up to align.
83591040Sarr		 */
83691040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
83791040Sarr		cp = malloc(sizeof(struct common_symbol)
83891040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
839111119Simp		    M_WAITOK | M_ZERO);
84091040Sarr		cp->address = (caddr_t)(cp + 1);
84191040Sarr		cp->name = cp->address + common_size;
84291040Sarr		strcpy(cp->name, name);
84391040Sarr		bzero(cp->address, common_size);
84491040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
84525537Sdfr
84691040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
847109605Sjake		    " value=%p\n", cp->address));
84891040Sarr		return (cp->address);
84940159Speter	}
85091040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
85191040Sarr	return (0);
85225537Sdfr}
85325537Sdfr
85425537Sdfr/*
855174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and
856174132Srwatson * backward lookup of symbols.  However, DDB and sometimes stack(9) need to
857174132Srwatson * do this in a lockfree manner.  We provide a set of internal helper
858174132Srwatson * routines to perform these operations without locks, and then wrappers that
859174132Srwatson * optionally lock.
860159840Sjhb *
861174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
86240159Speter */
863174132Srwatson#ifdef DDB
864174132Srwatsonstatic int
865174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
86640159Speter{
86791040Sarr	linker_file_t lf;
86840159Speter
86991040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
87091040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
87191040Sarr			return (0);
87291040Sarr	}
87391040Sarr	return (ENOENT);
87440159Speter}
875174132Srwatson#endif
87640159Speter
877174132Srwatsonstatic int
878174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
87940159Speter{
88091040Sarr	linker_file_t lf;
88191040Sarr	c_linker_sym_t best, es;
88291040Sarr	u_long diff, bestdiff, off;
88340159Speter
88491040Sarr	best = 0;
88591040Sarr	off = (uintptr_t)value;
88691040Sarr	bestdiff = off;
88791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
88891040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
88991040Sarr			continue;
89091040Sarr		if (es != 0 && diff < bestdiff) {
89191040Sarr			best = es;
89291040Sarr			bestdiff = diff;
89391040Sarr		}
89491040Sarr		if (bestdiff == 0)
89591040Sarr			break;
89640159Speter	}
89791040Sarr	if (best) {
89891040Sarr		*sym = best;
89991040Sarr		*diffp = bestdiff;
90091040Sarr		return (0);
90191040Sarr	} else {
90291040Sarr		*sym = 0;
90391040Sarr		*diffp = off;
90491040Sarr		return (ENOENT);
90591040Sarr	}
90640159Speter}
90740159Speter
908174132Srwatsonstatic int
909174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
91040159Speter{
91191040Sarr	linker_file_t lf;
91240159Speter
91391040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
91491040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
91591040Sarr			return (0);
91691040Sarr	}
91791040Sarr	return (ENOENT);
91840159Speter}
919174132Srwatson
920174132Srwatsonstatic int
921174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
922174132Srwatson    long *offset)
923174132Srwatson{
924174132Srwatson	linker_symval_t symval;
925174132Srwatson	c_linker_sym_t sym;
926174132Srwatson	int error;
927174132Srwatson
928174132Srwatson	*offset = 0;
929174132Srwatson	error = linker_debug_search_symbol(value, &sym, offset);
930174132Srwatson	if (error)
931174132Srwatson		return (error);
932174132Srwatson	error = linker_debug_symbol_values(sym, &symval);
933174132Srwatson	if (error)
934174132Srwatson		return (error);
935174132Srwatson	strlcpy(buf, symval.name, buflen);
936174132Srwatson	return (0);
937174132Srwatson}
938174132Srwatson
939174132Srwatson/*
940174132Srwatson * DDB Helpers.  DDB has to look across multiple files with their own symbol
941174132Srwatson * tables and string tables.
942174132Srwatson *
943174132Srwatson * Note that we do not obey list locking protocols here.  We really don't need
944174132Srwatson * DDB to hang because somebody's got the lock held.  We'll take the chance
945174132Srwatson * that the files list is inconsistant instead.
946174132Srwatson */
947212994Savg#ifdef DDB
948174132Srwatsonint
949174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
950174132Srwatson{
951174132Srwatson
952174132Srwatson	return (linker_debug_lookup(symstr, sym));
953174132Srwatson}
954212994Savg#endif
955174132Srwatson
956174132Srwatsonint
957174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
958174132Srwatson{
959174132Srwatson
960174132Srwatson	return (linker_debug_search_symbol(value, sym, diffp));
961174132Srwatson}
962174132Srwatson
963174132Srwatsonint
964174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
965174132Srwatson{
966174132Srwatson
967174132Srwatson	return (linker_debug_symbol_values(sym, symval));
968174132Srwatson}
969174132Srwatson
970174132Srwatsonint
971174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
972174132Srwatson    long *offset)
973174132Srwatson{
974174132Srwatson
975174132Srwatson	return (linker_debug_search_symbol_name(value, buf, buflen, offset));
976174132Srwatson}
97740159Speter
97840159Speter/*
979174132Srwatson * stack(9) helper for non-debugging environemnts.  Unlike DDB helpers, we do
980174132Srwatson * obey locking protocols, and offer a significantly less complex interface.
981174132Srwatson */
982174132Srwatsonint
983174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
984174132Srwatson    long *offset)
985174132Srwatson{
986178380Spjd	int error;
987174132Srwatson
988254810Smarkj	sx_xlock(&kld_sx);
989174132Srwatson	error = linker_debug_search_symbol_name(value, buf, buflen, offset);
990254810Smarkj	sx_xunlock(&kld_sx);
991174132Srwatson	return (error);
992174132Srwatson}
993174132Srwatson
994174132Srwatson/*
99525537Sdfr * Syscalls.
99625537Sdfr */
99725537Sdfrint
998159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
99925537Sdfr{
1000159588Sjhb	const char *kldname, *modname;
100191040Sarr	linker_file_t lf;
1002159588Sjhb	int error;
100325537Sdfr
100493159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1005159588Sjhb		return (error);
100693159Sarr
1007164033Srwatson	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
1008159588Sjhb		return (error);
100925537Sdfr
101091040Sarr	/*
1011191917Szec	 * It is possible that kldloaded module will attach a new ifnet,
1012191816Szec	 * so vnet context must be set when this ocurs.
1013191816Szec	 */
1014191816Szec	CURVNET_SET(TD_TO_VNET(td));
1015191816Szec
1016191816Szec	/*
1017159841Sjhb	 * If file does not contain a qualified name or any dot in it
1018159841Sjhb	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
101991040Sarr	 * name.
102091040Sarr	 */
1021229272Sed	if (strchr(file, '/') || strchr(file, '.')) {
1022159588Sjhb		kldname = file;
102391040Sarr		modname = NULL;
102491040Sarr	} else {
102591040Sarr		kldname = NULL;
1026159588Sjhb		modname = file;
102791040Sarr	}
1028159588Sjhb
1029254810Smarkj	sx_xlock(&kld_sx);
103091040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
1031224156Srstone	if (error) {
1032254810Smarkj		sx_xunlock(&kld_sx);
1033224156Srstone		goto done;
1034224156Srstone	}
1035224156Srstone	lf->userrefs++;
1036224156Srstone	if (fileid != NULL)
1037224156Srstone		*fileid = lf->id;
1038262039Savg	sx_xunlock(&kld_sx);
1039254266Smarkj
1040224156Srstonedone:
1041191816Szec	CURVNET_RESTORE();
104291040Sarr	return (error);
104325537Sdfr}
104425537Sdfr
1045159588Sjhbint
1046225617Skmacysys_kldload(struct thread *td, struct kldload_args *uap)
1047159588Sjhb{
1048159588Sjhb	char *pathname = NULL;
1049159596Smarcel	int error, fileid;
1050159588Sjhb
1051159588Sjhb	td->td_retval[0] = -1;
1052159588Sjhb
1053159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1054159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1055159596Smarcel	if (error == 0) {
1056159596Smarcel		error = kern_kldload(td, pathname, &fileid);
1057159596Smarcel		if (error == 0)
1058159596Smarcel			td->td_retval[0] = fileid;
1059159596Smarcel	}
1060159588Sjhb	free(pathname, M_TEMP);
1061159588Sjhb	return (error);
1062159588Sjhb}
1063159588Sjhb
1064159588Sjhbint
1065132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
106625537Sdfr{
106791040Sarr	linker_file_t lf;
106891040Sarr	int error = 0;
106925537Sdfr
107093159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1071159588Sjhb		return (error);
107293159Sarr
1073164033Srwatson	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1074159588Sjhb		return (error);
107525537Sdfr
1076191816Szec	CURVNET_SET(TD_TO_VNET(td));
1077254810Smarkj	sx_xlock(&kld_sx);
1078132117Sphk	lf = linker_find_file_by_id(fileid);
107991040Sarr	if (lf) {
108091040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
1081172862Sjb
1082262039Savg		if (lf->userrefs == 0) {
1083132117Sphk			/*
1084132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
1085132117Sphk			 */
108691040Sarr			printf("kldunload: attempt to unload file that was"
108791040Sarr			    " loaded by the kernel\n");
1088159840Sjhb			error = EBUSY;
1089159588Sjhb		} else {
1090159588Sjhb			lf->userrefs--;
1091159588Sjhb			error = linker_file_unload(lf, flags);
1092159588Sjhb			if (error)
1093159588Sjhb				lf->userrefs++;
1094159588Sjhb		}
109591040Sarr	} else
109691040Sarr		error = ENOENT;
1097262039Savg	sx_xunlock(&kld_sx);
1098157144Sjkoshy
1099191816Szec	CURVNET_RESTORE();
110091068Sarr	return (error);
110125537Sdfr}
110225537Sdfr
110325537Sdfrint
1104225617Skmacysys_kldunload(struct thread *td, struct kldunload_args *uap)
1105132117Sphk{
1106132117Sphk
1107132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
1108132117Sphk}
1109132117Sphk
1110132117Sphkint
1111225617Skmacysys_kldunloadf(struct thread *td, struct kldunloadf_args *uap)
1112132117Sphk{
1113132117Sphk
1114132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
1115132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
1116132117Sphk		return (EINVAL);
1117132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
1118132117Sphk}
1119132117Sphk
1120132117Sphkint
1121225617Skmacysys_kldfind(struct thread *td, struct kldfind_args *uap)
112225537Sdfr{
112391040Sarr	char *pathname;
112491040Sarr	const char *filename;
112591040Sarr	linker_file_t lf;
1126159791Sjhb	int error;
112725537Sdfr
1128107089Srwatson#ifdef MAC
1129172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1130107089Srwatson	if (error)
1131107089Srwatson		return (error);
1132107089Srwatson#endif
1133107089Srwatson
113491040Sarr	td->td_retval[0] = -1;
113582749Sdillon
1136111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1137107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
113891040Sarr		goto out;
113925537Sdfr
114091040Sarr	filename = linker_basename(pathname);
1141254810Smarkj	sx_xlock(&kld_sx);
114291040Sarr	lf = linker_find_file_by_name(filename);
114391040Sarr	if (lf)
114491040Sarr		td->td_retval[0] = lf->id;
114591040Sarr	else
114691040Sarr		error = ENOENT;
1147254810Smarkj	sx_xunlock(&kld_sx);
114825537Sdfrout:
1149159791Sjhb	free(pathname, M_TEMP);
115091040Sarr	return (error);
115125537Sdfr}
115225537Sdfr
115325537Sdfrint
1154225617Skmacysys_kldnext(struct thread *td, struct kldnext_args *uap)
115525537Sdfr{
115691040Sarr	linker_file_t lf;
115791040Sarr	int error = 0;
115825537Sdfr
1159107089Srwatson#ifdef MAC
1160172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1161107089Srwatson	if (error)
1162107089Srwatson		return (error);
1163107089Srwatson#endif
1164107089Srwatson
1165254810Smarkj	sx_xlock(&kld_sx);
1166166921Sjhb	if (uap->fileid == 0)
1167166921Sjhb		lf = TAILQ_FIRST(&linker_files);
1168166921Sjhb	else {
1169166921Sjhb		lf = linker_find_file_by_id(uap->fileid);
1170166921Sjhb		if (lf == NULL) {
1171166921Sjhb			error = ENOENT;
1172166921Sjhb			goto out;
1173166921Sjhb		}
1174166921Sjhb		lf = TAILQ_NEXT(lf, link);
117591040Sarr	}
1176166921Sjhb
1177166921Sjhb	/* Skip partially loaded files. */
1178166921Sjhb	while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1179166921Sjhb		lf = TAILQ_NEXT(lf, link);
1180166921Sjhb
1181166921Sjhb	if (lf)
1182166921Sjhb		td->td_retval[0] = lf->id;
1183166921Sjhb	else
1184166921Sjhb		td->td_retval[0] = 0;
118582749Sdillonout:
1186254810Smarkj	sx_xunlock(&kld_sx);
118791040Sarr	return (error);
118825537Sdfr}
118925537Sdfr
119025537Sdfrint
1191225617Skmacysys_kldstat(struct thread *td, struct kldstat_args *uap)
119225537Sdfr{
1193159587Sjhb	struct kld_file_stat stat;
1194220158Skib	int error, version;
119525537Sdfr
1196159587Sjhb	/*
1197159587Sjhb	 * Check the version of the user's structure.
1198159587Sjhb	 */
1199220158Skib	if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
1200220158Skib	    != 0)
1201159587Sjhb		return (error);
1202220158Skib	if (version != sizeof(struct kld_file_stat_1) &&
1203220158Skib	    version != sizeof(struct kld_file_stat))
1204159587Sjhb		return (EINVAL);
1205159587Sjhb
1206220158Skib	error = kern_kldstat(td, uap->fileid, &stat);
1207220158Skib	if (error != 0)
1208220158Skib		return (error);
1209220158Skib	return (copyout(&stat, uap->stat, version));
1210220158Skib}
1211220158Skib
1212220158Skibint
1213220158Skibkern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
1214220158Skib{
1215220158Skib	linker_file_t lf;
1216220158Skib	int namelen;
1217107089Srwatson#ifdef MAC
1218220158Skib	int error;
1219220158Skib
1220172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1221107089Srwatson	if (error)
1222107089Srwatson		return (error);
1223107089Srwatson#endif
1224107089Srwatson
1225254810Smarkj	sx_xlock(&kld_sx);
1226220158Skib	lf = linker_find_file_by_id(fileid);
122791040Sarr	if (lf == NULL) {
1228254810Smarkj		sx_xunlock(&kld_sx);
1229159587Sjhb		return (ENOENT);
123091040Sarr	}
123125537Sdfr
1232172862Sjb	/* Version 1 fields: */
123391040Sarr	namelen = strlen(lf->filename) + 1;
123491040Sarr	if (namelen > MAXPATHLEN)
123591040Sarr		namelen = MAXPATHLEN;
1236220158Skib	bcopy(lf->filename, &stat->name[0], namelen);
1237220158Skib	stat->refs = lf->refs;
1238220158Skib	stat->id = lf->id;
1239220158Skib	stat->address = lf->address;
1240220158Skib	stat->size = lf->size;
1241220158Skib	/* Version 2 fields: */
1242220158Skib	namelen = strlen(lf->pathname) + 1;
1243220158Skib	if (namelen > MAXPATHLEN)
1244220158Skib		namelen = MAXPATHLEN;
1245220158Skib	bcopy(lf->pathname, &stat->pathname[0], namelen);
1246254810Smarkj	sx_xunlock(&kld_sx);
124725537Sdfr
124891040Sarr	td->td_retval[0] = 0;
1249220158Skib	return (0);
125025537Sdfr}
125125537Sdfr
125225537Sdfrint
1253225617Skmacysys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
125425537Sdfr{
125591040Sarr	linker_file_t lf;
125691040Sarr	module_t mp;
125791040Sarr	int error = 0;
125825537Sdfr
1259107089Srwatson#ifdef MAC
1260172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1261107089Srwatson	if (error)
1262107089Srwatson		return (error);
1263107089Srwatson#endif
1264107089Srwatson
1265254810Smarkj	sx_xlock(&kld_sx);
1266107849Salfred	lf = linker_find_file_by_id(uap->fileid);
126791040Sarr	if (lf) {
126892547Sarr		MOD_SLOCK;
126991040Sarr		mp = TAILQ_FIRST(&lf->modules);
127091040Sarr		if (mp != NULL)
127191040Sarr			td->td_retval[0] = module_getid(mp);
127291040Sarr		else
127391040Sarr			td->td_retval[0] = 0;
127492547Sarr		MOD_SUNLOCK;
127591040Sarr	} else
127691040Sarr		error = ENOENT;
1277254810Smarkj	sx_xunlock(&kld_sx);
127891040Sarr	return (error);
127925537Sdfr}
128040159Speter
128141090Speterint
1282225617Skmacysys_kldsym(struct thread *td, struct kldsym_args *uap)
128341090Speter{
128491040Sarr	char *symstr = NULL;
128591040Sarr	c_linker_sym_t sym;
128691040Sarr	linker_symval_t symval;
128791040Sarr	linker_file_t lf;
128891040Sarr	struct kld_sym_lookup lookup;
128991040Sarr	int error = 0;
129041090Speter
1291107089Srwatson#ifdef MAC
1292172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1293107089Srwatson	if (error)
1294107089Srwatson		return (error);
1295107089Srwatson#endif
1296107089Srwatson
1297107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1298159843Sjhb		return (error);
129991068Sarr	if (lookup.version != sizeof(lookup) ||
1300159843Sjhb	    uap->cmd != KLDSYM_LOOKUP)
1301159843Sjhb		return (EINVAL);
1302111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
130391040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
130491040Sarr		goto out;
1305254810Smarkj	sx_xlock(&kld_sx);
1306107849Salfred	if (uap->fileid != 0) {
1307107849Salfred		lf = linker_find_file_by_id(uap->fileid);
1308159843Sjhb		if (lf == NULL)
130991040Sarr			error = ENOENT;
1310159843Sjhb		else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
131191040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
131291040Sarr			lookup.symvalue = (uintptr_t) symval.value;
131391040Sarr			lookup.symsize = symval.size;
1314107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
131591040Sarr		} else
131691040Sarr			error = ENOENT;
131791040Sarr	} else {
131891040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
131991040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
132091040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
132191040Sarr				lookup.symvalue = (uintptr_t)symval.value;
132291040Sarr				lookup.symsize = symval.size;
1323107849Salfred				error = copyout(&lookup, uap->data,
132491040Sarr				    sizeof(lookup));
132591068Sarr				break;
132691040Sarr			}
132791040Sarr		}
132891040Sarr		if (lf == NULL)
132991040Sarr			error = ENOENT;
133041090Speter	}
1331254810Smarkj	sx_xunlock(&kld_sx);
133241090Speterout:
1333159843Sjhb	free(symstr, M_TEMP);
133491040Sarr	return (error);
133541090Speter}
133641090Speter
133740159Speter/*
133840159Speter * Preloaded module support
133940159Speter */
134040159Speter
134159751Speterstatic modlist_t
134274642Sbpmodlist_lookup(const char *name, int ver)
134359751Speter{
134491040Sarr	modlist_t mod;
134559751Speter
134691040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
134792032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
134892032Sdwmalone		    (ver == 0 || mod->version == ver))
134991040Sarr			return (mod);
135091040Sarr	}
135191040Sarr	return (NULL);
135259751Speter}
135359751Speter
135474642Sbpstatic modlist_t
135583321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
135683321Speter{
135791040Sarr	modlist_t mod, bestmod;
135892032Sdwmalone	int ver;
135983321Speter
136091040Sarr	if (verinfo == NULL)
136191040Sarr		return (modlist_lookup(name, 0));
136291040Sarr	bestmod = NULL;
1363159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
136492032Sdwmalone		if (strcmp(mod->name, name) != 0)
136591040Sarr			continue;
136691040Sarr		ver = mod->version;
136791040Sarr		if (ver == verinfo->md_ver_preferred)
136891040Sarr			return (mod);
136991040Sarr		if (ver >= verinfo->md_ver_minimum &&
137091068Sarr		    ver <= verinfo->md_ver_maximum &&
1371120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
137291040Sarr			bestmod = mod;
137391040Sarr	}
137491040Sarr	return (bestmod);
137583321Speter}
137683321Speter
137783321Speterstatic modlist_t
137878501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
137974642Sbp{
138091040Sarr	modlist_t mod;
138174642Sbp
138292705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
138391040Sarr	if (mod == NULL)
138491040Sarr		panic("no memory for module list");
138591040Sarr	mod->container = container;
138691040Sarr	mod->name = modname;
138791040Sarr	mod->version = version;
138891040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
138991040Sarr	return (mod);
139074642Sbp}
139174642Sbp
139240159Speterstatic void
139378161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
139491040Sarr    struct mod_metadata **stop, int preload)
139574642Sbp{
139691040Sarr	struct mod_metadata *mp, **mdp;
139791040Sarr	const char *modname;
139891040Sarr	int ver;
139974642Sbp
140091040Sarr	for (mdp = start; mdp < stop; mdp++) {
1401109605Sjake		mp = *mdp;
140291040Sarr		if (mp->md_type != MDT_VERSION)
140391040Sarr			continue;
1404109605Sjake		modname = mp->md_cval;
1405109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
140691040Sarr		if (modlist_lookup(modname, ver) != NULL) {
140791040Sarr			printf("module %s already present!\n", modname);
140891040Sarr			/* XXX what can we do? this is a build error. :-( */
140991040Sarr			continue;
141091040Sarr		}
141191040Sarr		modlist_newmodule(modname, ver, lf);
141274642Sbp	}
141374642Sbp}
141474642Sbp
141574642Sbpstatic void
141691040Sarrlinker_preload(void *arg)
141740159Speter{
141891040Sarr	caddr_t modptr;
141991040Sarr	const char *modname, *nmodname;
142091040Sarr	char *modtype;
1421160244Sjhb	linker_file_t lf, nlf;
142291040Sarr	linker_class_t lc;
142392032Sdwmalone	int error;
142491040Sarr	linker_file_list_t loaded_files;
142591040Sarr	linker_file_list_t depended_files;
142691040Sarr	struct mod_metadata *mp, *nmp;
142791040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
142891040Sarr	struct mod_depend *verinfo;
142991040Sarr	int nver;
143091040Sarr	int resolves;
143191040Sarr	modlist_t mod;
143291040Sarr	struct sysinit **si_start, **si_stop;
143340159Speter
143491040Sarr	TAILQ_INIT(&loaded_files);
143591040Sarr	TAILQ_INIT(&depended_files);
143691040Sarr	TAILQ_INIT(&found_modules);
143791040Sarr	error = 0;
143859751Speter
143991040Sarr	modptr = NULL;
1440254810Smarkj	sx_xlock(&kld_sx);
144191040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
144291040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
144391040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
144491040Sarr		if (modname == NULL) {
144591040Sarr			printf("Preloaded module at %p does not have a"
144691040Sarr			    " name!\n", modptr);
144791040Sarr			continue;
144891040Sarr		}
144991040Sarr		if (modtype == NULL) {
145091040Sarr			printf("Preloaded module at %p does not have a type!\n",
145191040Sarr			    modptr);
145291040Sarr			continue;
145391040Sarr		}
1454131398Sjhb		if (bootverbose)
1455131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1456131398Sjhb			    modptr);
145740159Speter		lf = NULL;
145891040Sarr		TAILQ_FOREACH(lc, &classes, link) {
145991040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1460134364Siedowse			if (!error)
146191040Sarr				break;
1462134364Siedowse			lf = NULL;
146391040Sarr		}
146491040Sarr		if (lf)
146591040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
146640159Speter	}
146740159Speter
146891040Sarr	/*
146991040Sarr	 * First get a list of stuff in the kernel.
147091040Sarr	 */
147191040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
147291040Sarr	    &stop, NULL) == 0)
147391040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
147459751Speter
147559751Speter	/*
1476167019Sjhb	 * This is a once-off kinky bubble sort to resolve relocation
1477167019Sjhb	 * dependency requirements.
147859751Speter	 */
147991040Sarrrestart:
148091040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
148191040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
148291040Sarr		    &stop, NULL);
148391040Sarr		/*
148491040Sarr		 * First, look to see if we would successfully link with this
148591040Sarr		 * stuff.
148691040Sarr		 */
148791040Sarr		resolves = 1;	/* unless we know otherwise */
148891040Sarr		if (!error) {
148991040Sarr			for (mdp = start; mdp < stop; mdp++) {
1490109605Sjake				mp = *mdp;
149191040Sarr				if (mp->md_type != MDT_DEPEND)
149291040Sarr					continue;
1493109605Sjake				modname = mp->md_cval;
1494109605Sjake				verinfo = mp->md_data;
149591040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1496109605Sjake					nmp = *nmdp;
149791040Sarr					if (nmp->md_type != MDT_VERSION)
149891040Sarr						continue;
1499109605Sjake					nmodname = nmp->md_cval;
150092032Sdwmalone					if (strcmp(modname, nmodname) == 0)
150191040Sarr						break;
150291040Sarr				}
150391040Sarr				if (nmdp < stop)   /* it's a self reference */
150491040Sarr					continue;
1505159840Sjhb
150691040Sarr				/*
150791040Sarr				 * ok, the module isn't here yet, we
150891040Sarr				 * are not finished
150991040Sarr				 */
151091068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
151191040Sarr					resolves = 0;
151291040Sarr			}
151364143Speter		}
151491040Sarr		/*
151591040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
151691040Sarr		 * the modules inside and add it to the end of the link order
151791040Sarr		 * list.
151891040Sarr		 */
151991040Sarr		if (resolves) {
152091040Sarr			if (!error) {
152191040Sarr				for (mdp = start; mdp < stop; mdp++) {
1522109605Sjake					mp = *mdp;
152391040Sarr					if (mp->md_type != MDT_VERSION)
152491040Sarr						continue;
1525109605Sjake					modname = mp->md_cval;
1526109605Sjake					nver = ((struct mod_version *)
1527109605Sjake					    mp->md_data)->mv_version;
152891040Sarr					if (modlist_lookup(modname,
152991040Sarr					    nver) != NULL) {
153091040Sarr						printf("module %s already"
153191040Sarr						    " present!\n", modname);
1532160244Sjhb						TAILQ_REMOVE(&loaded_files,
1533160244Sjhb						    lf, loaded);
1534132117Sphk						linker_file_unload(lf,
1535132117Sphk						    LINKER_UNLOAD_FORCE);
153691040Sarr						/* we changed tailq next ptr */
153791068Sarr						goto restart;
153891040Sarr					}
153991040Sarr					modlist_newmodule(modname, nver, lf);
154091040Sarr				}
154191040Sarr			}
154291040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
154391040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
154491040Sarr			/*
154591040Sarr			 * Since we provided modules, we need to restart the
154691040Sarr			 * sort so that the previous files that depend on us
154791040Sarr			 * have a chance. Also, we've busted the tailq next
154891040Sarr			 * pointer with the REMOVE.
154991040Sarr			 */
155091040Sarr			goto restart;
155159751Speter		}
155259751Speter	}
155391040Sarr
155459751Speter	/*
155591040Sarr	 * At this point, we check to see what could not be resolved..
155659751Speter	 */
1557160242Sjhb	while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1558160242Sjhb		TAILQ_REMOVE(&loaded_files, lf, loaded);
155991040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1560132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
156140159Speter	}
156259751Speter
156378161Speter	/*
156491040Sarr	 * We made it. Finish off the linking in the order we determined.
156578161Speter	 */
1566160244Sjhb	TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
156791040Sarr		if (linker_kernel_file) {
156891040Sarr			linker_kernel_file->refs++;
156991040Sarr			error = linker_file_add_dependency(lf,
157091040Sarr			    linker_kernel_file);
157191040Sarr			if (error)
157291040Sarr				panic("cannot add dependency");
157391040Sarr		}
157491040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
157591040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
157691040Sarr		    &stop, NULL);
157791040Sarr		if (!error) {
157891040Sarr			for (mdp = start; mdp < stop; mdp++) {
1579109605Sjake				mp = *mdp;
158091040Sarr				if (mp->md_type != MDT_DEPEND)
158191040Sarr					continue;
1582109605Sjake				modname = mp->md_cval;
1583109605Sjake				verinfo = mp->md_data;
158491040Sarr				mod = modlist_lookup2(modname, verinfo);
1585216988Strasz				if (mod == NULL) {
1586216988Strasz					printf("KLD file %s - cannot find "
1587216988Strasz					    "dependency \"%s\"\n",
1588216988Strasz					    lf->filename, modname);
1589216988Strasz					goto fail;
1590216988Strasz				}
1591151484Sjdp				/* Don't count self-dependencies */
1592151484Sjdp				if (lf == mod->container)
1593151484Sjdp					continue;
159491040Sarr				mod->container->refs++;
159591040Sarr				error = linker_file_add_dependency(lf,
159691040Sarr				    mod->container);
159791040Sarr				if (error)
159891040Sarr					panic("cannot add dependency");
159991040Sarr			}
160091040Sarr		}
160191040Sarr		/*
160291040Sarr		 * Now do relocation etc using the symbol search paths
160391040Sarr		 * established by the dependencies
160491040Sarr		 */
160591040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
160691040Sarr		if (error) {
160791040Sarr			printf("KLD file %s - could not finalize loading\n",
160891040Sarr			    lf->filename);
1609216988Strasz			goto fail;
161091040Sarr		}
161191040Sarr		linker_file_register_modules(lf);
161291040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
161391040Sarr		    &si_stop, NULL) == 0)
161491040Sarr			sysinit_add(si_start, si_stop);
161591040Sarr		linker_file_register_sysctls(lf);
161691040Sarr		lf->flags |= LINKER_FILE_LINKED;
1617216988Strasz		continue;
1618216988Straszfail:
1619216988Strasz		TAILQ_REMOVE(&depended_files, lf, loaded);
1620216988Strasz		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
162159751Speter	}
1622254810Smarkj	sx_xunlock(&kld_sx);
162391040Sarr	/* woohoo! we made it! */
162440159Speter}
162540159Speter
1626177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
162740159Speter
162840159Speter/*
162940159Speter * Search for a not-loaded module by name.
1630159840Sjhb *
163140159Speter * Modules may be found in the following locations:
1632159840Sjhb *
163391040Sarr * - preloaded (result is just the module name) - on disk (result is full path
163491040Sarr * to module)
1635159840Sjhb *
163691040Sarr * If the module name is qualified in any way (contains path, etc.) the we
163791040Sarr * simply return a copy of it.
1638159840Sjhb *
163940159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
164040159Speter * character as a separator to be consistent with the bootloader.
164140159Speter */
164240159Speter
164383321Speterstatic char linker_hintfile[] = "linker.hints";
1644111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
164540159Speter
164640159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
164791040Sarr    sizeof(linker_path), "module load search path");
164840159Speter
164977843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
165070417Speter
165159751Speterstatic char *linker_ext_list[] = {
165283321Speter	"",
165359751Speter	".ko",
165459751Speter	NULL
165559751Speter};
165659751Speter
165783321Speter/*
165891040Sarr * Check if file actually exists either with or without extension listed in
165991040Sarr * the linker_ext_list. (probably should be generic for the rest of the
166091040Sarr * kernel)
166183321Speter */
166259751Speterstatic char *
166391040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
166491040Sarr    int namelen, struct vattr *vap)
166540159Speter{
166691040Sarr	struct nameidata nd;
166791040Sarr	struct thread *td = curthread;	/* XXX */
166891040Sarr	char *result, **cpp, *sep;
1669241896Skib	int error, len, extlen, reclen, flags;
167091040Sarr	enum vtype type;
167140159Speter
167291040Sarr	extlen = 0;
167391040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
167491040Sarr		len = strlen(*cpp);
167591040Sarr		if (len > extlen)
167691040Sarr			extlen = len;
167791040Sarr	}
167891040Sarr	extlen++;		/* trailing '\0' */
167991040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
168083321Speter
168191040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1682111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
168391040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
168491040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
168591040Sarr		    namelen, name, *cpp);
168691040Sarr		/*
168791040Sarr		 * Attempt to open the file, and return the path if
168891040Sarr		 * we succeed and it's a regular file.
168991040Sarr		 */
1690241896Skib		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
169191040Sarr		flags = FREAD;
1692170152Skib		error = vn_open(&nd, &flags, 0, NULL);
169391040Sarr		if (error == 0) {
169491040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
169591040Sarr			type = nd.ni_vp->v_type;
169691040Sarr			if (vap)
1697182371Sattilio				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1698175294Sattilio			VOP_UNLOCK(nd.ni_vp, 0);
169991406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
170091040Sarr			if (type == VREG)
170191040Sarr				return (result);
170291040Sarr		}
170383321Speter	}
170491040Sarr	free(result, M_LINKER);
170591040Sarr	return (NULL);
170683321Speter}
170783321Speter
170891040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
170983321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
171083321Speter
171183321Speter/*
171291040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
171391040Sarr * version specification is available, then try to find the best KLD.
171483321Speter * Otherwise just find the latest one.
171583321Speter */
171683321Speterstatic char *
171791040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
171891040Sarr    int modnamelen, struct mod_depend *verinfo)
171983321Speter{
172091040Sarr	struct thread *td = curthread;	/* XXX */
172191406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
172291040Sarr	struct nameidata nd;
172391040Sarr	struct vattr vattr, mattr;
172491040Sarr	u_char *hints = NULL;
172591040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
1726231949Skib	int error, ival, bestver, *intp, found, flags, clen, blen;
1727231949Skib	ssize_t reclen;
172883321Speter
172991040Sarr	result = NULL;
173091040Sarr	bestver = found = 0;
173183321Speter
173291040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
173391040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
173491040Sarr	    strlen(sep) + 1;
1735111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
173691040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
173791040Sarr	    linker_hintfile);
173883321Speter
1739241896Skib	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
174091040Sarr	flags = FREAD;
1741170152Skib	error = vn_open(&nd, &flags, 0, NULL);
174291040Sarr	if (error)
174391040Sarr		goto bad;
174491040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
174591040Sarr	if (nd.ni_vp->v_type != VREG)
174691040Sarr		goto bad;
174791040Sarr	best = cp = NULL;
1748182371Sattilio	error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
174991040Sarr	if (error)
175091040Sarr		goto bad;
175191040Sarr	/*
175291040Sarr	 * XXX: we need to limit this number to some reasonable value
175391040Sarr	 */
175491040Sarr	if (vattr.va_size > 100 * 1024) {
175591040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
175691040Sarr		goto bad;
175791040Sarr	}
1758111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
175991040Sarr	if (hints == NULL)
176091040Sarr		goto bad;
176191068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1762101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
176391040Sarr	if (error)
176491040Sarr		goto bad;
1765175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
176691040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
176791040Sarr	nd.ni_vp = NULL;
176891040Sarr	if (reclen != 0) {
1769231949Skib		printf("can't read %zd\n", reclen);
177091040Sarr		goto bad;
177191040Sarr	}
177291040Sarr	intp = (int *)hints;
177383321Speter	ival = *intp++;
177491040Sarr	if (ival != LINKER_HINTS_VERSION) {
177591040Sarr		printf("hints file version mismatch %d\n", ival);
177691040Sarr		goto bad;
177783321Speter	}
177891040Sarr	bufend = hints + vattr.va_size;
177991040Sarr	recptr = (u_char *)intp;
178091040Sarr	clen = blen = 0;
178191040Sarr	while (recptr < bufend && !found) {
178291040Sarr		intp = (int *)recptr;
178391040Sarr		reclen = *intp++;
178491040Sarr		ival = *intp++;
178591040Sarr		cp = (char *)intp;
178691040Sarr		switch (ival) {
178791040Sarr		case MDT_VERSION:
178891040Sarr			clen = *cp++;
178991040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
179091040Sarr				break;
179191040Sarr			cp += clen;
179291040Sarr			INT_ALIGN(hints, cp);
179391040Sarr			ival = *(int *)cp;
179491040Sarr			cp += sizeof(int);
179591040Sarr			clen = *cp++;
179691040Sarr			if (verinfo == NULL ||
179791040Sarr			    ival == verinfo->md_ver_preferred) {
179891040Sarr				found = 1;
179991040Sarr				break;
180091040Sarr			}
180191040Sarr			if (ival >= verinfo->md_ver_minimum &&
180291040Sarr			    ival <= verinfo->md_ver_maximum &&
180391040Sarr			    ival > bestver) {
180491040Sarr				bestver = ival;
180591040Sarr				best = cp;
180691040Sarr				blen = clen;
180791040Sarr			}
180891040Sarr			break;
180991040Sarr		default:
181091040Sarr			break;
181191040Sarr		}
181291040Sarr		recptr += reclen + sizeof(int);
181391040Sarr	}
181483321Speter	/*
181591040Sarr	 * Finally check if KLD is in the place
181683321Speter	 */
181791040Sarr	if (found)
181891040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
181991040Sarr	else if (best)
182091040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
182191040Sarr
182291040Sarr	/*
182391040Sarr	 * KLD is newer than hints file. What we should do now?
182491040Sarr	 */
182591040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
182691040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
182791040Sarr		    " file\n", result);
182883321Speterbad:
1829105167Sphk	free(pathbuf, M_LINKER);
183091040Sarr	if (hints)
183191040Sarr		free(hints, M_TEMP);
183299553Sjeff	if (nd.ni_vp != NULL) {
1833175294Sattilio		VOP_UNLOCK(nd.ni_vp, 0);
183491040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
183599553Sjeff	}
183691040Sarr	/*
183791040Sarr	 * If nothing found or hints is absent - fallback to the old
183891040Sarr	 * way by using "kldname[.ko]" as module name.
183991040Sarr	 */
184091040Sarr	if (!found && !bestver && result == NULL)
184191040Sarr		result = linker_lookup_file(path, pathlen, modname,
184291040Sarr		    modnamelen, NULL);
184391040Sarr	return (result);
184483321Speter}
184583321Speter
184683321Speter/*
184783321Speter * Lookup KLD which contains requested module in the all directories.
184883321Speter */
184983321Speterstatic char *
185083321Speterlinker_search_module(const char *modname, int modnamelen,
185191040Sarr    struct mod_depend *verinfo)
185283321Speter{
185391040Sarr	char *cp, *ep, *result;
185483321Speter
185591040Sarr	/*
185691040Sarr	 * traverse the linker path
185791040Sarr	 */
185891040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
185991040Sarr		/* find the end of this component */
186091040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
186191068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
186291068Sarr		    modnamelen, verinfo);
186391040Sarr		if (result != NULL)
186491040Sarr			return (result);
186591040Sarr		if (*ep == 0)
186691040Sarr			break;
186791040Sarr	}
186891040Sarr	return (NULL);
186983321Speter}
187083321Speter
187183321Speter/*
187283321Speter * Search for module in all directories listed in the linker_path.
187383321Speter */
187483321Speterstatic char *
187583321Speterlinker_search_kld(const char *name)
187683321Speter{
1877158972Sdelphij	char *cp, *ep, *result;
1878158972Sdelphij	int len;
187983321Speter
188091040Sarr	/* qualified at all? */
1881229272Sed	if (strchr(name, '/'))
1882254396Smarkj		return (strdup(name, M_LINKER));
188340159Speter
188491040Sarr	/* traverse the linker path */
188591040Sarr	len = strlen(name);
188691040Sarr	for (ep = linker_path; *ep; ep++) {
188791040Sarr		cp = ep;
188891040Sarr		/* find the end of this component */
188991040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
189091040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
189191040Sarr		if (result != NULL)
189291040Sarr			return (result);
189391040Sarr	}
189491040Sarr	return (NULL);
189540159Speter}
189659751Speter
189759751Speterstatic const char *
189891040Sarrlinker_basename(const char *path)
189959751Speter{
190091040Sarr	const char *filename;
190159751Speter
1902229272Sed	filename = strrchr(path, '/');
190391040Sarr	if (filename == NULL)
190491040Sarr		return path;
190591040Sarr	if (filename[1])
190691040Sarr		filename++;
190791040Sarr	return (filename);
190859751Speter}
190959751Speter
1910157144Sjkoshy#ifdef HWPMC_HOOKS
191159751Speter/*
1912157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1913157144Sjkoshy */
1914157144Sjkoshyvoid *
1915157144Sjkoshylinker_hwpmc_list_objects(void)
1916157144Sjkoshy{
1917195159Sattilio	linker_file_t lf;
1918195159Sattilio	struct pmckern_map_in *kobase;
1919195159Sattilio	int i, nmappings;
1920157144Sjkoshy
1921195159Sattilio	nmappings = 0;
1922254810Smarkj	sx_slock(&kld_sx);
1923195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link)
1924195159Sattilio		nmappings++;
1925157144Sjkoshy
1926195159Sattilio	/* Allocate nmappings + 1 entries. */
1927195159Sattilio	kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in),
1928184214Sdes	    M_LINKER, M_WAITOK | M_ZERO);
1929195159Sattilio	i = 0;
1930195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link) {
1931157144Sjkoshy
1932195159Sattilio		/* Save the info for this linker file. */
1933195159Sattilio		kobase[i].pm_file = lf->filename;
1934195159Sattilio		kobase[i].pm_address = (uintptr_t)lf->address;
1935195159Sattilio		i++;
1936157144Sjkoshy	}
1937254810Smarkj	sx_sunlock(&kld_sx);
1938157144Sjkoshy
1939195159Sattilio	KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
1940157144Sjkoshy
1941157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1942195159Sattilio	KASSERT(kobase[i].pm_file == NULL,
1943157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1944157144Sjkoshy
1945195159Sattilio	return ((void *)kobase);
1946157144Sjkoshy}
1947157144Sjkoshy#endif
1948157144Sjkoshy
1949157144Sjkoshy/*
195091040Sarr * Find a file which contains given module and load it, if "parent" is not
195191040Sarr * NULL, register a reference to it.
195259751Speter */
1953159796Sjhbstatic int
195483321Speterlinker_load_module(const char *kldname, const char *modname,
195591040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
195691040Sarr    struct linker_file **lfpp)
195759751Speter{
195891040Sarr	linker_file_t lfdep;
195991040Sarr	const char *filename;
196091040Sarr	char *pathname;
196191040Sarr	int error;
196259751Speter
1963254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
196491040Sarr	if (modname == NULL) {
196591040Sarr		/*
196691040Sarr 		 * We have to load KLD
196791040Sarr 		 */
196891068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
196991068Sarr		    " is not NULL"));
197091040Sarr		pathname = linker_search_kld(kldname);
197191040Sarr	} else {
197291040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
197391040Sarr			return (EEXIST);
197494322Sbrian		if (kldname != NULL)
1975254396Smarkj			pathname = strdup(kldname, M_LINKER);
197695488Sbrian		else if (rootvnode == NULL)
197794322Sbrian			pathname = NULL;
197894322Sbrian		else
197991040Sarr			/*
198091040Sarr			 * Need to find a KLD with required module
198191040Sarr			 */
198291040Sarr			pathname = linker_search_module(modname,
198391040Sarr			    strlen(modname), verinfo);
198491040Sarr	}
198591040Sarr	if (pathname == NULL)
198691040Sarr		return (ENOENT);
198791040Sarr
198883321Speter	/*
198991040Sarr	 * Can't load more than one file with the same basename XXX:
199091040Sarr	 * Actually it should be possible to have multiple KLDs with
199191040Sarr	 * the same basename but different path because they can
199291040Sarr	 * provide different versions of the same modules.
199383321Speter	 */
199491040Sarr	filename = linker_basename(pathname);
1995159792Sjhb	if (linker_find_file_by_name(filename))
199691040Sarr		error = EEXIST;
1997159792Sjhb	else do {
199891040Sarr		error = linker_load_file(pathname, &lfdep);
199991040Sarr		if (error)
200091040Sarr			break;
200191040Sarr		if (modname && verinfo &&
200291040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
2003132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
200491040Sarr			error = ENOENT;
200591040Sarr			break;
200691040Sarr		}
200791040Sarr		if (parent) {
200891040Sarr			error = linker_file_add_dependency(parent, lfdep);
200991040Sarr			if (error)
201091040Sarr				break;
201191040Sarr		}
201291040Sarr		if (lfpp)
201391040Sarr			*lfpp = lfdep;
201491040Sarr	} while (0);
2015159791Sjhb	free(pathname, M_LINKER);
201691040Sarr	return (error);
201759751Speter}
201859751Speter
201959751Speter/*
202091040Sarr * This routine is responsible for finding dependencies of userland initiated
202191040Sarr * kldload(2)'s of files.
202259751Speter */
202359751Speterint
202486469Siedowselinker_load_dependencies(linker_file_t lf)
202559751Speter{
202691040Sarr	linker_file_t lfdep;
202791040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
202891040Sarr	struct mod_metadata *mp, *nmp;
202991040Sarr	struct mod_depend *verinfo;
203091040Sarr	modlist_t mod;
203191040Sarr	const char *modname, *nmodname;
203292032Sdwmalone	int ver, error = 0, count;
203359751Speter
203491040Sarr	/*
203591040Sarr	 * All files are dependant on /kernel.
203691040Sarr	 */
2037254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
203891040Sarr	if (linker_kernel_file) {
203991040Sarr		linker_kernel_file->refs++;
204091040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
204191040Sarr		if (error)
204291040Sarr			return (error);
204359751Speter	}
204491040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
204591040Sarr	    &count) != 0)
204691040Sarr		return (0);
204791040Sarr	for (mdp = start; mdp < stop; mdp++) {
2048109605Sjake		mp = *mdp;
204991040Sarr		if (mp->md_type != MDT_VERSION)
205091040Sarr			continue;
2051109605Sjake		modname = mp->md_cval;
2052109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
205391040Sarr		mod = modlist_lookup(modname, ver);
205491040Sarr		if (mod != NULL) {
205591040Sarr			printf("interface %s.%d already present in the KLD"
205691040Sarr			    " '%s'!\n", modname, ver,
205791040Sarr			    mod->container->filename);
205891040Sarr			return (EEXIST);
205991040Sarr		}
206091040Sarr	}
206174642Sbp
206291040Sarr	for (mdp = start; mdp < stop; mdp++) {
2063109605Sjake		mp = *mdp;
206491040Sarr		if (mp->md_type != MDT_DEPEND)
206591040Sarr			continue;
2066109605Sjake		modname = mp->md_cval;
2067109605Sjake		verinfo = mp->md_data;
206891040Sarr		nmodname = NULL;
206991040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
2070109605Sjake			nmp = *nmdp;
207191040Sarr			if (nmp->md_type != MDT_VERSION)
207291040Sarr				continue;
2073109605Sjake			nmodname = nmp->md_cval;
207492032Sdwmalone			if (strcmp(modname, nmodname) == 0)
207591040Sarr				break;
207691040Sarr		}
207791040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
207891040Sarr			continue;
207991040Sarr		mod = modlist_lookup2(modname, verinfo);
208091040Sarr		if (mod) {	/* woohoo, it's loaded already */
208191040Sarr			lfdep = mod->container;
208291040Sarr			lfdep->refs++;
208391040Sarr			error = linker_file_add_dependency(lf, lfdep);
208491040Sarr			if (error)
208591040Sarr				break;
208691040Sarr			continue;
208791040Sarr		}
208891040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
208991040Sarr		if (error) {
2090231931Sdelphij			printf("KLD %s: depends on %s - not available or"
2091195803Srpaulo			    " version mismatch\n", lf->filename, modname);
209291040Sarr			break;
209391040Sarr		}
209459751Speter	}
209559751Speter
209691040Sarr	if (error)
209791040Sarr		return (error);
209891040Sarr	linker_addmodules(lf, start, stop, 0);
209991040Sarr	return (error);
210059751Speter}
210185736Sgreen
210285736Sgreenstatic int
210385736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
210485736Sgreen{
210585736Sgreen	struct sysctl_req *req;
210685736Sgreen
210785736Sgreen	req = opaque;
210885736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
210985736Sgreen}
211085736Sgreen
211185736Sgreen/*
211285736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
211385736Sgreen * in the kernel.
211485736Sgreen */
211585736Sgreenstatic int
211685736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
211785736Sgreen{
211885736Sgreen	linker_file_t lf;
211985736Sgreen	int error;
212085736Sgreen
2121107089Srwatson#ifdef MAC
2122172930Srwatson	error = mac_kld_check_stat(req->td->td_ucred);
2123107089Srwatson	if (error)
2124107089Srwatson		return (error);
2125107089Srwatson#endif
2126126253Struckman	error = sysctl_wire_old_buffer(req, 0);
2127126253Struckman	if (error != 0)
2128126253Struckman		return (error);
2129254810Smarkj	sx_xlock(&kld_sx);
213085736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
213185736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
213285736Sgreen		    sysctl_kern_function_list_iterate, req);
213398452Sarr		if (error) {
2134254810Smarkj			sx_xunlock(&kld_sx);
213585736Sgreen			return (error);
213698452Sarr		}
213785736Sgreen	}
2138254810Smarkj	sx_xunlock(&kld_sx);
213985736Sgreen	return (SYSCTL_OUT(req, "", 1));
214085736Sgreen}
214185736Sgreen
2142217555SmdfSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLTYPE_OPAQUE | CTLFLAG_RD,
214391040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2144