kern_linker.c revision 196019
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: head/sys/kern/kern_linker.c 196019 2009-08-01 19:26:27Z rwatson $");
29116182Sobrien
3040159Speter#include "opt_ddb.h"
31157144Sjkoshy#include "opt_hwpmc_hooks.h"
3240159Speter
3325537Sdfr#include <sys/param.h>
3425537Sdfr#include <sys/kernel.h>
3525537Sdfr#include <sys/systm.h>
3625537Sdfr#include <sys/malloc.h>
3725537Sdfr#include <sys/sysproto.h>
3825537Sdfr#include <sys/sysent.h>
39164033Srwatson#include <sys/priv.h>
4025537Sdfr#include <sys/proc.h>
4125537Sdfr#include <sys/lock.h>
4282749Sdillon#include <sys/mutex.h>
4392547Sarr#include <sys/sx.h>
4425537Sdfr#include <sys/module.h>
45159808Sjhb#include <sys/mount.h>
4625537Sdfr#include <sys/linker.h>
4740159Speter#include <sys/fcntl.h>
48192895Sjamie#include <sys/jail.h>
4940159Speter#include <sys/libkern.h>
5040159Speter#include <sys/namei.h>
5140159Speter#include <sys/vnode.h>
52159588Sjhb#include <sys/syscallsubr.h>
5340159Speter#include <sys/sysctl.h>
5425537Sdfr
55196019Srwatson#include <net/vnet.h>
56196019Srwatson
57163606Srwatson#include <security/mac/mac_framework.h>
58163606Srwatson
5959603Sdfr#include "linker_if.h"
6059603Sdfr
61157144Sjkoshy#ifdef HWPMC_HOOKS
62157144Sjkoshy#include <sys/pmckern.h>
63157144Sjkoshy#endif
64157144Sjkoshy
6540961Speter#ifdef KLD_DEBUG
6640961Speterint kld_debug = 0;
6740961Speter#endif
6840961Speter
69160142Sjhb#define	KLD_LOCK()		sx_xlock(&kld_sx)
70160142Sjhb#define	KLD_UNLOCK()		sx_xunlock(&kld_sx)
71159845Sjhb#define	KLD_LOCKED()		sx_xlocked(&kld_sx)
72160142Sjhb#define	KLD_LOCK_ASSERT() do {						\
73160142Sjhb	if (!cold)							\
74160142Sjhb		sx_assert(&kld_sx, SX_XLOCKED);				\
75160142Sjhb} while (0)
76159845Sjhb
7791040Sarr/*
7891040Sarr * static char *linker_search_path(const char *name, struct mod_depend
7991040Sarr * *verinfo);
8091040Sarr */
8191040Sarrstatic const char 	*linker_basename(const char *path);
8259751Speter
83159800Sjhb/*
84159800Sjhb * Find a currently loaded file given its filename.
85159800Sjhb */
86159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
87159800Sjhb
88159800Sjhb/*
89159800Sjhb * Find a currently loaded file given its file id.
90159800Sjhb */
91159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
92159800Sjhb
9378161Speter/* Metadata from the static kernel */
9478161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
9578161Speter
9659751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
9759751Speter
9840906Speterlinker_file_t linker_kernel_file;
9931324Sbde
100159845Sjhbstatic struct sx kld_sx;	/* kernel linker lock */
10198452Sarr
102172862Sjb/*
103172862Sjb * Load counter used by clients to determine if a linker file has been
104172862Sjb * re-loaded. This counter is incremented for each file load.
105172862Sjb */
106172862Sjbstatic int loadcnt;
107172862Sjb
10825537Sdfrstatic linker_class_list_t classes;
10950068Sgrogstatic linker_file_list_t linker_files;
11025537Sdfrstatic int next_file_id = 1;
11198452Sarrstatic int linker_no_more_classes = 0;
11225537Sdfr
11386553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
11491040Sarr	linker_file_t lftmp;						\
11586553Sarr									\
116159845Sjhb	KLD_LOCK_ASSERT();						\
11786553Sarrretry:									\
11891040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
11991040Sarr		if (next_file_id == lftmp->id) {			\
12091040Sarr			next_file_id++;					\
12191040Sarr			goto retry;					\
12291040Sarr		}							\
12391040Sarr	}								\
12491040Sarr	(a) = next_file_id;						\
12586553Sarr} while(0)
12686553Sarr
12786553Sarr
12859751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
12960938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
13059751Speterstruct modlist {
13191040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
13291040Sarr	linker_file_t   container;
13391040Sarr	const char 	*name;
13491040Sarr	int             version;
13559751Speter};
13691040Sarrtypedef struct modlist *modlist_t;
13791040Sarrstatic modlisthead_t found_modules;
13859751Speter
139159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
140159796Sjhb		    linker_file_t dep);
141159845Sjhbstatic caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
142159845Sjhb		    const char* name, int deps);
143159796Sjhbstatic int	linker_load_module(const char *kldname,
144159796Sjhb		    const char *modname, struct linker_file *parent,
145159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
146159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
14794321Sbrian
14859603Sdfrstatic char *
14959603Sdfrlinker_strdup(const char *str)
15059603Sdfr{
15191040Sarr	char *result;
15259603Sdfr
153111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
15491040Sarr		strcpy(result, str);
15591040Sarr	return (result);
15659603Sdfr}
15759603Sdfr
15825537Sdfrstatic void
15991040Sarrlinker_init(void *arg)
16025537Sdfr{
16191040Sarr
162159845Sjhb	sx_init(&kld_sx, "kernel linker");
16391040Sarr	TAILQ_INIT(&classes);
16491040Sarr	TAILQ_INIT(&linker_files);
16525537Sdfr}
16625537Sdfr
167177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
16825537Sdfr
16998452Sarrstatic void
17098452Sarrlinker_stop_class_add(void *arg)
17198452Sarr{
17298452Sarr
17398452Sarr	linker_no_more_classes = 1;
17498452Sarr}
17598452Sarr
176177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL);
17798452Sarr
17825537Sdfrint
17959603Sdfrlinker_add_class(linker_class_t lc)
18025537Sdfr{
18191040Sarr
18298452Sarr	/*
183144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
184144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
185144443Sjhb	 * ops from being freed.
18698452Sarr	 */
18798452Sarr	if (linker_no_more_classes == 1)
18898452Sarr		return (EPERM);
18991040Sarr	kobj_class_compile((kobj_class_t) lc);
190144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
19191040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
19291040Sarr	return (0);
19325537Sdfr}
19425537Sdfr
19525537Sdfrstatic void
19625537Sdfrlinker_file_sysinit(linker_file_t lf)
19725537Sdfr{
19891040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
19925537Sdfr
20091040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
20191040Sarr	    lf->filename));
20225537Sdfr
20391040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
20491040Sarr		return;
20591040Sarr	/*
20691040Sarr	 * Perform a bubble sort of the system initialization objects by
20791040Sarr	 * their subsystem (primary key) and order (secondary key).
208159840Sjhb	 *
20991040Sarr	 * Since some things care about execution order, this is the operation
21091040Sarr	 * which ensures continued function.
21191040Sarr	 */
21291040Sarr	for (sipp = start; sipp < stop; sipp++) {
21391040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
21491040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
21591040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
21691040Sarr			    (*sipp)->order <= (*xipp)->order))
21791040Sarr				continue;	/* skip */
21891040Sarr			save = *sipp;
21991040Sarr			*sipp = *xipp;
22091040Sarr			*xipp = save;
22191040Sarr		}
22225537Sdfr	}
22325537Sdfr
22491040Sarr	/*
22591040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
22691040Sarr	 * Perform each task, and continue on to the next task.
22791040Sarr	 */
228160142Sjhb	mtx_lock(&Giant);
22991040Sarr	for (sipp = start; sipp < stop; sipp++) {
23091040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
23191040Sarr			continue;	/* skip dummy task(s) */
23225537Sdfr
23391040Sarr		/* Call function */
23491040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
23591040Sarr	}
236160142Sjhb	mtx_unlock(&Giant);
23725537Sdfr}
23825537Sdfr
23941055Speterstatic void
24041055Speterlinker_file_sysuninit(linker_file_t lf)
24141055Speter{
24291040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
24341055Speter
24491040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
24591040Sarr	    lf->filename));
24641055Speter
24791068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
24891040Sarr	    NULL) != 0)
24991040Sarr		return;
25041055Speter
25191040Sarr	/*
25291040Sarr	 * Perform a reverse bubble sort of the system initialization objects
25391040Sarr	 * by their subsystem (primary key) and order (secondary key).
254159840Sjhb	 *
25591040Sarr	 * Since some things care about execution order, this is the operation
25691040Sarr	 * which ensures continued function.
25791040Sarr	 */
25891040Sarr	for (sipp = start; sipp < stop; sipp++) {
25991040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
26091040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
26191040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
26291040Sarr			    (*sipp)->order >= (*xipp)->order))
26391040Sarr				continue;	/* skip */
26491040Sarr			save = *sipp;
26591040Sarr			*sipp = *xipp;
26691040Sarr			*xipp = save;
26791040Sarr		}
26841055Speter	}
26941055Speter
27091040Sarr	/*
27191040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
27291040Sarr	 * Perform each task, and continue on to the next task.
27391040Sarr	 */
274160142Sjhb	mtx_lock(&Giant);
27591040Sarr	for (sipp = start; sipp < stop; sipp++) {
27691040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
27791040Sarr			continue;	/* skip dummy task(s) */
27841055Speter
27991040Sarr		/* Call function */
28091040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
28191040Sarr	}
282160142Sjhb	mtx_unlock(&Giant);
28341055Speter}
28441055Speter
28544078Sdfrstatic void
28644078Sdfrlinker_file_register_sysctls(linker_file_t lf)
28744078Sdfr{
28891040Sarr	struct sysctl_oid **start, **stop, **oidp;
28944078Sdfr
29091040Sarr	KLD_DPF(FILE,
29191040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
29291040Sarr	    lf->filename));
29344078Sdfr
29491040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
29591040Sarr		return;
29644078Sdfr
297188232Sjhb	sysctl_lock();
29891040Sarr	for (oidp = start; oidp < stop; oidp++)
29991040Sarr		sysctl_register_oid(*oidp);
300188232Sjhb	sysctl_unlock();
30144078Sdfr}
30244078Sdfr
30344078Sdfrstatic void
30444078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
30544078Sdfr{
30691040Sarr	struct sysctl_oid **start, **stop, **oidp;
30744078Sdfr
30891040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
30991040Sarr	    " for %s\n", lf->filename));
31044078Sdfr
31191040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
31291040Sarr		return;
31344078Sdfr
314188232Sjhb	sysctl_lock();
31591040Sarr	for (oidp = start; oidp < stop; oidp++)
31691040Sarr		sysctl_unregister_oid(*oidp);
317188232Sjhb	sysctl_unlock();
31844078Sdfr}
31944078Sdfr
32059751Speterstatic int
32159751Speterlinker_file_register_modules(linker_file_t lf)
32259751Speter{
32391040Sarr	struct mod_metadata **start, **stop, **mdp;
32491040Sarr	const moduledata_t *moddata;
325146733Spjd	int first_error, error;
32659751Speter
32791040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
32891040Sarr	    " in %s\n", lf->filename));
32959751Speter
33091068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
331159841Sjhb	    &stop, NULL) != 0) {
33291040Sarr		/*
33391040Sarr		 * This fallback should be unnecessary, but if we get booted
33491040Sarr		 * from boot2 instead of loader and we are missing our
33591040Sarr		 * metadata then we have to try the best we can.
33691040Sarr		 */
33791040Sarr		if (lf == linker_kernel_file) {
33891040Sarr			start = SET_BEGIN(modmetadata_set);
33991040Sarr			stop = SET_LIMIT(modmetadata_set);
34091040Sarr		} else
34191040Sarr			return (0);
34278161Speter	}
343146733Spjd	first_error = 0;
34491040Sarr	for (mdp = start; mdp < stop; mdp++) {
34591040Sarr		if ((*mdp)->md_type != MDT_MODULE)
34691040Sarr			continue;
34791040Sarr		moddata = (*mdp)->md_data;
34891040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
34991040Sarr		    moddata->name, lf->filename));
35091040Sarr		error = module_register(moddata, lf);
351146730Spjd		if (error) {
35291068Sarr			printf("Module %s failed to register: %d\n",
35391040Sarr			    moddata->name, error);
354146733Spjd			if (first_error == 0)
355146733Spjd				first_error = error;
356146730Spjd		}
35759751Speter	}
358146733Spjd	return (first_error);
35959751Speter}
36059751Speter
36159751Speterstatic void
36259751Speterlinker_init_kernel_modules(void)
36359751Speter{
36491040Sarr
36591040Sarr	linker_file_register_modules(linker_kernel_file);
36659751Speter}
36759751Speter
368177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules,
369177253Srwatson    0);
37059751Speter
371101241Smuxstatic int
37291040Sarrlinker_load_file(const char *filename, linker_file_t *result)
37325537Sdfr{
37491040Sarr	linker_class_t lc;
37591040Sarr	linker_file_t lf;
376159585Sjhb	int foundfile, error;
37725537Sdfr
37891040Sarr	/* Refuse to load modules if securelevel raised */
379192895Sjamie	if (prison0.pr_securelevel > 0)
38091040Sarr		return (EPERM);
38162261Sarchie
382159845Sjhb	KLD_LOCK_ASSERT();
38391040Sarr	lf = linker_find_file_by_name(filename);
38491040Sarr	if (lf) {
38591040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
38691040Sarr		    " incrementing refs\n", filename));
38791040Sarr		*result = lf;
38891040Sarr		lf->refs++;
389159585Sjhb		return (0);
39091040Sarr	}
39191040Sarr	foundfile = 0;
392159585Sjhb	error = 0;
39398452Sarr
39498452Sarr	/*
39598452Sarr	 * We do not need to protect (lock) classes here because there is
39698452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
39798452Sarr	 * and there is no class deregistration mechanism at this time.
39898452Sarr	 */
39991040Sarr	TAILQ_FOREACH(lc, &classes, link) {
40091040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
40191040Sarr		    filename));
40291040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
40391040Sarr		/*
40491040Sarr		 * If we got something other than ENOENT, then it exists but
40591040Sarr		 * we cannot load it for some other reason.
40691040Sarr		 */
40791040Sarr		if (error != ENOENT)
40891040Sarr			foundfile = 1;
40991040Sarr		if (lf) {
410146730Spjd			error = linker_file_register_modules(lf);
411146730Spjd			if (error == EEXIST) {
412146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
413159585Sjhb				return (error);
414146730Spjd			}
415166921Sjhb			KLD_UNLOCK();
41691040Sarr			linker_file_register_sysctls(lf);
41791040Sarr			linker_file_sysinit(lf);
418166921Sjhb			KLD_LOCK();
41991040Sarr			lf->flags |= LINKER_FILE_LINKED;
42091040Sarr			*result = lf;
421159585Sjhb			return (0);
42291040Sarr		}
42391040Sarr	}
42442755Speter	/*
42591040Sarr	 * Less than ideal, but tells the user whether it failed to load or
42691040Sarr	 * the module was not found.
42742755Speter	 */
428105337Ssam	if (foundfile) {
429188440Sattilio
430105337Ssam		/*
431188440Sattilio		 * If the file type has not been recognized by the last try
432188440Sattilio		 * printout a message before to fail.
433188440Sattilio		 */
434188440Sattilio		if (error == ENOSYS)
435188440Sattilio			printf("linker_load_file: Unsupported file type\n");
436188440Sattilio
437188440Sattilio		/*
438105337Ssam		 * Format not recognized or otherwise unloadable.
439105337Ssam		 * When loading a module that is statically built into
440105337Ssam		 * the kernel EEXIST percolates back up as the return
441105337Ssam		 * value.  Preserve this so that apps like sysinstall
442105337Ssam		 * can recognize this special case and not post bogus
443105337Ssam		 * dialog boxes.
444105337Ssam		 */
445105337Ssam		if (error != EEXIST)
446105337Ssam			error = ENOEXEC;
447105337Ssam	} else
44891068Sarr		error = ENOENT;		/* Nothing found */
44991040Sarr	return (error);
45025537Sdfr}
45125537Sdfr
45278413Sbrianint
45394321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
45494321Sbrian    linker_file_t *result)
45578413Sbrian{
45694321Sbrian	modlist_t mod;
457159804Sjhb	int error;
45894321Sbrian
459159845Sjhb	KLD_LOCK();
46094321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
46194321Sbrian		*result = mod->container;
46294321Sbrian		(*result)->refs++;
463159845Sjhb		KLD_UNLOCK();
46494321Sbrian		return (0);
46594321Sbrian	}
46694321Sbrian
467159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
468159845Sjhb	KLD_UNLOCK();
469159804Sjhb	return (error);
47078413Sbrian}
47178413Sbrian
472159804Sjhbint
473159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
474159804Sjhb    linker_file_t lf)
475159804Sjhb{
476159804Sjhb	modlist_t mod;
477159804Sjhb	int error;
478159804Sjhb
479159845Sjhb	KLD_LOCK();
480159804Sjhb	if (lf == NULL) {
481159804Sjhb		KASSERT(modname != NULL,
482159804Sjhb		    ("linker_release_module: no file or name"));
483159804Sjhb		mod = modlist_lookup2(modname, verinfo);
484159804Sjhb		if (mod == NULL) {
485159845Sjhb			KLD_UNLOCK();
486159804Sjhb			return (ESRCH);
487159804Sjhb		}
488159804Sjhb		lf = mod->container;
489159804Sjhb	} else
490159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
491159804Sjhb		    ("linker_release_module: both file and name"));
492159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
493159845Sjhb	KLD_UNLOCK();
494159804Sjhb	return (error);
495159804Sjhb}
496159804Sjhb
497159800Sjhbstatic linker_file_t
49891040Sarrlinker_find_file_by_name(const char *filename)
49925537Sdfr{
500159585Sjhb	linker_file_t lf;
50191040Sarr	char *koname;
50225537Sdfr
503111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
50491040Sarr	sprintf(koname, "%s.ko", filename);
50540861Speter
506159845Sjhb	KLD_LOCK_ASSERT();
50791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
50892032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
50991040Sarr			break;
51092032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
51191040Sarr			break;
51291040Sarr	}
513159585Sjhb	free(koname, M_LINKER);
51491040Sarr	return (lf);
51525537Sdfr}
51625537Sdfr
517159800Sjhbstatic linker_file_t
51825537Sdfrlinker_find_file_by_id(int fileid)
51925537Sdfr{
520159585Sjhb	linker_file_t lf;
521159845Sjhb
522159845Sjhb	KLD_LOCK_ASSERT();
52391040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
524166921Sjhb		if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
52591040Sarr			break;
52691040Sarr	return (lf);
52725537Sdfr}
52825537Sdfr
529159797Sjhbint
530159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
531159797Sjhb{
532159797Sjhb	linker_file_t lf;
533159797Sjhb	int retval = 0;
534159797Sjhb
535159845Sjhb	KLD_LOCK();
536159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
537159797Sjhb		retval = predicate(lf, context);
538159797Sjhb		if (retval != 0)
539159797Sjhb			break;
540159797Sjhb	}
541159845Sjhb	KLD_UNLOCK();
542159797Sjhb	return (retval);
543159797Sjhb}
544159797Sjhb
54525537Sdfrlinker_file_t
54691040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
54725537Sdfr{
54891040Sarr	linker_file_t lf;
54991040Sarr	const char *filename;
55025537Sdfr
551159845Sjhb	KLD_LOCK_ASSERT();
55291040Sarr	filename = linker_basename(pathname);
55340159Speter
554172862Sjb	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
555111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
55691040Sarr	if (lf == NULL)
557159585Sjhb		return (NULL);
55891040Sarr	lf->refs = 1;
55991040Sarr	lf->userrefs = 0;
56091040Sarr	lf->flags = 0;
56191040Sarr	lf->filename = linker_strdup(filename);
562172862Sjb	lf->pathname = linker_strdup(pathname);
56391040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
56491040Sarr	lf->ndeps = 0;
56591040Sarr	lf->deps = NULL;
566172862Sjb	lf->loadcnt = ++loadcnt;
567172862Sjb	lf->sdt_probes = NULL;
568172862Sjb	lf->sdt_nprobes = 0;
56991040Sarr	STAILQ_INIT(&lf->common);
57091040Sarr	TAILQ_INIT(&lf->modules);
57191040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
57291040Sarr	return (lf);
57325537Sdfr}
57425537Sdfr
57525537Sdfrint
576132117Sphklinker_file_unload(linker_file_t file, int flags)
57725537Sdfr{
57891040Sarr	module_t mod, next;
57991040Sarr	modlist_t ml, nextml;
58091040Sarr	struct common_symbol *cp;
58191040Sarr	int error, i;
58225537Sdfr
58391040Sarr	/* Refuse to unload modules if securelevel raised. */
584192895Sjamie	if (prison0.pr_securelevel > 0)
58591040Sarr		return (EPERM);
58625537Sdfr
587159845Sjhb	KLD_LOCK_ASSERT();
58891040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
58991040Sarr
590159584Sjhb	/* Easy case of just dropping a reference. */
591159584Sjhb	if (file->refs > 1) {
592159584Sjhb		file->refs--;
593159584Sjhb		return (0);
594159584Sjhb	}
595159584Sjhb
596159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
597159584Sjhb	    " informing modules\n"));
598159584Sjhb
599159584Sjhb	/*
600185635Sjhb	 * Quiesce all the modules to give them a chance to veto the unload.
601159584Sjhb	 */
602185635Sjhb	MOD_SLOCK;
603185635Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod;
604185635Sjhb	     mod = module_getfnext(mod)) {
605185635Sjhb
606185635Sjhb		error = module_quiesce(mod);
607185635Sjhb		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
608185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
609185635Sjhb			    " vetoed unload\n", module_getname(mod)));
610185635Sjhb			/*
611185635Sjhb			 * XXX: Do we need to tell all the quiesced modules
612185635Sjhb			 * that they can resume work now via a new module
613185635Sjhb			 * event?
614185635Sjhb			 */
615185635Sjhb			MOD_SUNLOCK;
616185635Sjhb			return (error);
617185635Sjhb		}
618185635Sjhb	}
619185635Sjhb	MOD_SUNLOCK;
620185635Sjhb
621185635Sjhb	/*
622185635Sjhb	 * Inform any modules associated with this file that they are
623185635Sjhb	 * being be unloaded.
624185635Sjhb	 */
625159584Sjhb	MOD_XLOCK;
626159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
627159584Sjhb		next = module_getfnext(mod);
628159584Sjhb		MOD_XUNLOCK;
629159584Sjhb
63091040Sarr		/*
631159584Sjhb		 * Give the module a chance to veto the unload.
63291040Sarr		 */
633185635Sjhb		if ((error = module_unload(mod)) != 0) {
634185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
635185635Sjhb			    " failed unload\n", mod));
636159584Sjhb			return (error);
637159584Sjhb		}
63892547Sarr		MOD_XLOCK;
639159584Sjhb		module_release(mod);
640159584Sjhb	}
641159584Sjhb	MOD_XUNLOCK;
64291040Sarr
643159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
644128057Speadar		if (ml->container == file) {
64591040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
646128057Speadar			free(ml, M_LINKER);
647128057Speadar		}
64891040Sarr	}
64925537Sdfr
650159840Sjhb	/*
651159840Sjhb	 * Don't try to run SYSUNINITs if we are unloaded due to a
65291040Sarr	 * link error.
65391040Sarr	 */
65491040Sarr	if (file->flags & LINKER_FILE_LINKED) {
655188209Sjhb		file->flags &= ~LINKER_FILE_LINKED;
656188209Sjhb		KLD_UNLOCK();
65791040Sarr		linker_file_sysuninit(file);
65891040Sarr		linker_file_unregister_sysctls(file);
659188209Sjhb		KLD_LOCK();
66025537Sdfr	}
66191040Sarr	TAILQ_REMOVE(&linker_files, file, link);
66225537Sdfr
66391040Sarr	if (file->deps) {
66491040Sarr		for (i = 0; i < file->ndeps; i++)
665132117Sphk			linker_file_unload(file->deps[i], flags);
66691040Sarr		free(file->deps, M_LINKER);
66791040Sarr		file->deps = NULL;
66859751Speter	}
669160245Sjhb	while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
670160245Sjhb		STAILQ_REMOVE_HEAD(&file->common, link);
67191040Sarr		free(cp, M_LINKER);
67291040Sarr	}
67359751Speter
67491040Sarr	LINKER_UNLOAD(file);
67591040Sarr	if (file->filename) {
67691040Sarr		free(file->filename, M_LINKER);
67791040Sarr		file->filename = NULL;
67891040Sarr	}
679172862Sjb	if (file->pathname) {
680172862Sjb		free(file->pathname, M_LINKER);
681172862Sjb		file->pathname = NULL;
682172862Sjb	}
68391040Sarr	kobj_delete((kobj_t) file, M_LINKER);
684159584Sjhb	return (0);
68525537Sdfr}
68625537Sdfr
687179238Sjbint
688179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc)
689179238Sjb{
690179238Sjb	return (LINKER_CTF_GET(file, lc));
691179238Sjb}
692179238Sjb
693159796Sjhbstatic int
69486469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
69525537Sdfr{
69691040Sarr	linker_file_t *newdeps;
69725537Sdfr
698159845Sjhb	KLD_LOCK_ASSERT();
69991040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
700111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
70191040Sarr	if (newdeps == NULL)
70291040Sarr		return (ENOMEM);
70325537Sdfr
70491040Sarr	if (file->deps) {
70591040Sarr		bcopy(file->deps, newdeps,
70691040Sarr		    file->ndeps * sizeof(linker_file_t *));
70791040Sarr		free(file->deps, M_LINKER);
70891040Sarr	}
70991040Sarr	file->deps = newdeps;
71091040Sarr	file->deps[file->ndeps] = dep;
71191040Sarr	file->ndeps++;
71291040Sarr	return (0);
71325537Sdfr}
71425537Sdfr
71578161Speter/*
71691040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
717159841Sjhb * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
718159841Sjhb * This function is used in this file so we can avoid having lots of (void **)
719159841Sjhb * casts.
72078161Speter */
72178161Speterint
72278161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
72391040Sarr    void *firstp, void *lastp, int *countp)
72478161Speter{
725159845Sjhb	int error, locked;
72678161Speter
727159845Sjhb	locked = KLD_LOCKED();
728159845Sjhb	if (!locked)
729159845Sjhb		KLD_LOCK();
730159845Sjhb	error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
731159845Sjhb	if (!locked)
732159845Sjhb		KLD_UNLOCK();
733159845Sjhb	return (error);
73478161Speter}
73578161Speter
736173714Sjb/*
737173714Sjb * List all functions in a file.
738173714Sjb */
739173714Sjbint
740173714Sjblinker_file_function_listall(linker_file_t lf,
741179238Sjb    linker_function_nameval_callback_t callback_func, void *arg)
742173714Sjb{
743173714Sjb	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
744173714Sjb}
745173714Sjb
74625537Sdfrcaddr_t
74791040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
74825537Sdfr{
749159845Sjhb	caddr_t sym;
750159845Sjhb	int locked;
751159845Sjhb
752159845Sjhb	locked = KLD_LOCKED();
753159845Sjhb	if (!locked)
754159845Sjhb		KLD_LOCK();
755159845Sjhb	sym = linker_file_lookup_symbol_internal(file, name, deps);
756159845Sjhb	if (!locked)
757159845Sjhb		KLD_UNLOCK();
758159845Sjhb	return (sym);
759159845Sjhb}
760159845Sjhb
761159845Sjhbstatic caddr_t
762159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name,
763159845Sjhb    int deps)
764159845Sjhb{
76591040Sarr	c_linker_sym_t sym;
76691040Sarr	linker_symval_t symval;
76791040Sarr	caddr_t address;
76891040Sarr	size_t common_size = 0;
76992032Sdwmalone	int i;
77025537Sdfr
771159845Sjhb	KLD_LOCK_ASSERT();
772109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
77391040Sarr	    file, name, deps));
77425537Sdfr
77591040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
77691040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
77791040Sarr		if (symval.value == 0)
77891040Sarr			/*
77991040Sarr			 * For commons, first look them up in the
78091040Sarr			 * dependencies and only allocate space if not found
78191040Sarr			 * there.
78291040Sarr			 */
78391040Sarr			common_size = symval.size;
78491040Sarr		else {
78591040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
786109605Sjake			    ".value=%p\n", symval.value));
78791040Sarr			return (symval.value);
78891040Sarr		}
78940159Speter	}
79091040Sarr	if (deps) {
79191040Sarr		for (i = 0; i < file->ndeps; i++) {
792159845Sjhb			address = linker_file_lookup_symbol_internal(
793159845Sjhb			    file->deps[i], name, 0);
79491040Sarr			if (address) {
79591040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
796109605Sjake				    " deps value=%p\n", address));
79791040Sarr				return (address);
79891040Sarr			}
79991040Sarr		}
80025537Sdfr	}
80191040Sarr	if (common_size > 0) {
80291040Sarr		/*
80391040Sarr		 * This is a common symbol which was not found in the
80491040Sarr		 * dependencies.  We maintain a simple common symbol table in
80591040Sarr		 * the file object.
80691040Sarr		 */
80791040Sarr		struct common_symbol *cp;
80842849Speter
80991040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
81092032Sdwmalone			if (strcmp(cp->name, name) == 0) {
81191040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
812109605Sjake				    " old common value=%p\n", cp->address));
81391040Sarr				return (cp->address);
81491040Sarr			}
81591040Sarr		}
81691040Sarr		/*
81791040Sarr		 * Round the symbol size up to align.
81891040Sarr		 */
81991040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
82091040Sarr		cp = malloc(sizeof(struct common_symbol)
82191040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
822111119Simp		    M_WAITOK | M_ZERO);
82391040Sarr		cp->address = (caddr_t)(cp + 1);
82491040Sarr		cp->name = cp->address + common_size;
82591040Sarr		strcpy(cp->name, name);
82691040Sarr		bzero(cp->address, common_size);
82791040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
82825537Sdfr
82991040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
830109605Sjake		    " value=%p\n", cp->address));
83191040Sarr		return (cp->address);
83240159Speter	}
83391040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
83491040Sarr	return (0);
83525537Sdfr}
83625537Sdfr
83725537Sdfr/*
838174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and
839174132Srwatson * backward lookup of symbols.  However, DDB and sometimes stack(9) need to
840174132Srwatson * do this in a lockfree manner.  We provide a set of internal helper
841174132Srwatson * routines to perform these operations without locks, and then wrappers that
842174132Srwatson * optionally lock.
843159840Sjhb *
844174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
84540159Speter */
846174132Srwatson#ifdef DDB
847174132Srwatsonstatic int
848174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
84940159Speter{
85091040Sarr	linker_file_t lf;
85140159Speter
85291040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
85391040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
85491040Sarr			return (0);
85591040Sarr	}
85691040Sarr	return (ENOENT);
85740159Speter}
858174132Srwatson#endif
85940159Speter
860174132Srwatsonstatic int
861174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
86240159Speter{
86391040Sarr	linker_file_t lf;
86491040Sarr	c_linker_sym_t best, es;
86591040Sarr	u_long diff, bestdiff, off;
86640159Speter
86791040Sarr	best = 0;
86891040Sarr	off = (uintptr_t)value;
86991040Sarr	bestdiff = off;
87091040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
87191040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
87291040Sarr			continue;
87391040Sarr		if (es != 0 && diff < bestdiff) {
87491040Sarr			best = es;
87591040Sarr			bestdiff = diff;
87691040Sarr		}
87791040Sarr		if (bestdiff == 0)
87891040Sarr			break;
87940159Speter	}
88091040Sarr	if (best) {
88191040Sarr		*sym = best;
88291040Sarr		*diffp = bestdiff;
88391040Sarr		return (0);
88491040Sarr	} else {
88591040Sarr		*sym = 0;
88691040Sarr		*diffp = off;
88791040Sarr		return (ENOENT);
88891040Sarr	}
88940159Speter}
89040159Speter
891174132Srwatsonstatic int
892174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
89340159Speter{
89491040Sarr	linker_file_t lf;
89540159Speter
89691040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
89791040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
89891040Sarr			return (0);
89991040Sarr	}
90091040Sarr	return (ENOENT);
90140159Speter}
902174132Srwatson
903174132Srwatsonstatic int
904174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
905174132Srwatson    long *offset)
906174132Srwatson{
907174132Srwatson	linker_symval_t symval;
908174132Srwatson	c_linker_sym_t sym;
909174132Srwatson	int error;
910174132Srwatson
911174132Srwatson	*offset = 0;
912174132Srwatson	error = linker_debug_search_symbol(value, &sym, offset);
913174132Srwatson	if (error)
914174132Srwatson		return (error);
915174132Srwatson	error = linker_debug_symbol_values(sym, &symval);
916174132Srwatson	if (error)
917174132Srwatson		return (error);
918174132Srwatson	strlcpy(buf, symval.name, buflen);
919174132Srwatson	return (0);
920174132Srwatson}
921174132Srwatson
922174132Srwatson#ifdef DDB
923174132Srwatson/*
924174132Srwatson * DDB Helpers.  DDB has to look across multiple files with their own symbol
925174132Srwatson * tables and string tables.
926174132Srwatson *
927174132Srwatson * Note that we do not obey list locking protocols here.  We really don't need
928174132Srwatson * DDB to hang because somebody's got the lock held.  We'll take the chance
929174132Srwatson * that the files list is inconsistant instead.
930174132Srwatson */
931174132Srwatsonint
932174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
933174132Srwatson{
934174132Srwatson
935174132Srwatson	return (linker_debug_lookup(symstr, sym));
936174132Srwatson}
937174132Srwatson
938174132Srwatsonint
939174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
940174132Srwatson{
941174132Srwatson
942174132Srwatson	return (linker_debug_search_symbol(value, sym, diffp));
943174132Srwatson}
944174132Srwatson
945174132Srwatsonint
946174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
947174132Srwatson{
948174132Srwatson
949174132Srwatson	return (linker_debug_symbol_values(sym, symval));
950174132Srwatson}
951174132Srwatson
952174132Srwatsonint
953174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
954174132Srwatson    long *offset)
955174132Srwatson{
956174132Srwatson
957174132Srwatson	return (linker_debug_search_symbol_name(value, buf, buflen, offset));
958174132Srwatson}
95940159Speter#endif
96040159Speter
96140159Speter/*
962174132Srwatson * stack(9) helper for non-debugging environemnts.  Unlike DDB helpers, we do
963174132Srwatson * obey locking protocols, and offer a significantly less complex interface.
964174132Srwatson */
965174132Srwatsonint
966174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
967174132Srwatson    long *offset)
968174132Srwatson{
969178380Spjd	int error;
970174132Srwatson
971178380Spjd	KLD_LOCK();
972174132Srwatson	error = linker_debug_search_symbol_name(value, buf, buflen, offset);
973178380Spjd	KLD_UNLOCK();
974174132Srwatson	return (error);
975174132Srwatson}
976174132Srwatson
977174132Srwatson/*
97825537Sdfr * Syscalls.
97925537Sdfr */
98025537Sdfrint
981159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
98225537Sdfr{
983157144Sjkoshy#ifdef HWPMC_HOOKS
984157144Sjkoshy	struct pmckern_map_in pkm;
985157144Sjkoshy#endif
986159588Sjhb	const char *kldname, *modname;
98791040Sarr	linker_file_t lf;
988159588Sjhb	int error;
98925537Sdfr
99093159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
991159588Sjhb		return (error);
99293159Sarr
993164033Srwatson	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
994159588Sjhb		return (error);
99525537Sdfr
99691040Sarr	/*
997191917Szec	 * It is possible that kldloaded module will attach a new ifnet,
998191816Szec	 * so vnet context must be set when this ocurs.
999191816Szec	 */
1000191816Szec	CURVNET_SET(TD_TO_VNET(td));
1001191816Szec
1002191816Szec	/*
1003159841Sjhb	 * If file does not contain a qualified name or any dot in it
1004159841Sjhb	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
100591040Sarr	 * name.
100691040Sarr	 */
1007159588Sjhb	if (index(file, '/') || index(file, '.')) {
1008159588Sjhb		kldname = file;
100991040Sarr		modname = NULL;
101091040Sarr	} else {
101191040Sarr		kldname = NULL;
1012159588Sjhb		modname = file;
101391040Sarr	}
1014159588Sjhb
1015159845Sjhb	KLD_LOCK();
101691040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
101791040Sarr	if (error)
1018159588Sjhb		goto unlock;
1019157144Sjkoshy#ifdef HWPMC_HOOKS
1020157144Sjkoshy	pkm.pm_file = lf->filename;
1021157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
1022157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
1023157144Sjkoshy#endif
102491040Sarr	lf->userrefs++;
1025159588Sjhb	if (fileid != NULL)
1026159588Sjhb		*fileid = lf->id;
1027159588Sjhbunlock:
1028159845Sjhb	KLD_UNLOCK();
1029191816Szec	CURVNET_RESTORE();
103091040Sarr	return (error);
103125537Sdfr}
103225537Sdfr
1033159588Sjhbint
1034159588Sjhbkldload(struct thread *td, struct kldload_args *uap)
1035159588Sjhb{
1036159588Sjhb	char *pathname = NULL;
1037159596Smarcel	int error, fileid;
1038159588Sjhb
1039159588Sjhb	td->td_retval[0] = -1;
1040159588Sjhb
1041159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1042159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1043159596Smarcel	if (error == 0) {
1044159596Smarcel		error = kern_kldload(td, pathname, &fileid);
1045159596Smarcel		if (error == 0)
1046159596Smarcel			td->td_retval[0] = fileid;
1047159596Smarcel	}
1048159588Sjhb	free(pathname, M_TEMP);
1049159588Sjhb	return (error);
1050159588Sjhb}
1051159588Sjhb
1052159588Sjhbint
1053132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
105425537Sdfr{
1055157144Sjkoshy#ifdef HWPMC_HOOKS
1056157144Sjkoshy	struct pmckern_map_out pkm;
1057157144Sjkoshy#endif
105891040Sarr	linker_file_t lf;
105991040Sarr	int error = 0;
106025537Sdfr
106193159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1062159588Sjhb		return (error);
106393159Sarr
1064164033Srwatson	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1065159588Sjhb		return (error);
106625537Sdfr
1067191816Szec	CURVNET_SET(TD_TO_VNET(td));
1068159845Sjhb	KLD_LOCK();
1069132117Sphk	lf = linker_find_file_by_id(fileid);
107091040Sarr	if (lf) {
107191040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
1072172862Sjb
1073172862Sjb		/* Check if there are DTrace probes enabled on this file. */
1074172862Sjb		if (lf->nenabled > 0) {
1075172862Sjb			printf("kldunload: attempt to unload file that has"
1076172862Sjb			    " DTrace probes enabled\n");
1077172862Sjb			error = EBUSY;
1078172862Sjb		} else if (lf->userrefs == 0) {
1079132117Sphk			/*
1080132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
1081132117Sphk			 */
108291040Sarr			printf("kldunload: attempt to unload file that was"
108391040Sarr			    " loaded by the kernel\n");
1084159840Sjhb			error = EBUSY;
1085159588Sjhb		} else {
1086157144Sjkoshy#ifdef HWPMC_HOOKS
1087159588Sjhb			/* Save data needed by hwpmc(4) before unloading. */
1088159588Sjhb			pkm.pm_address = (uintptr_t) lf->address;
1089159588Sjhb			pkm.pm_size = lf->size;
1090157144Sjkoshy#endif
1091159588Sjhb			lf->userrefs--;
1092159588Sjhb			error = linker_file_unload(lf, flags);
1093159588Sjhb			if (error)
1094159588Sjhb				lf->userrefs++;
1095159588Sjhb		}
109691040Sarr	} else
109791040Sarr		error = ENOENT;
1098157144Sjkoshy
1099157144Sjkoshy#ifdef HWPMC_HOOKS
1100157144Sjkoshy	if (error == 0)
1101157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
1102157144Sjkoshy#endif
1103159845Sjhb	KLD_UNLOCK();
1104191816Szec	CURVNET_RESTORE();
110591068Sarr	return (error);
110625537Sdfr}
110725537Sdfr
110825537Sdfrint
1109132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
1110132117Sphk{
1111132117Sphk
1112132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
1113132117Sphk}
1114132117Sphk
1115132117Sphkint
1116132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
1117132117Sphk{
1118132117Sphk
1119132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
1120132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
1121132117Sphk		return (EINVAL);
1122132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
1123132117Sphk}
1124132117Sphk
1125132117Sphkint
112691040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
112725537Sdfr{
112891040Sarr	char *pathname;
112991040Sarr	const char *filename;
113091040Sarr	linker_file_t lf;
1131159791Sjhb	int error;
113225537Sdfr
1133107089Srwatson#ifdef MAC
1134172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1135107089Srwatson	if (error)
1136107089Srwatson		return (error);
1137107089Srwatson#endif
1138107089Srwatson
113991040Sarr	td->td_retval[0] = -1;
114082749Sdillon
1141111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1142107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
114391040Sarr		goto out;
114425537Sdfr
114591040Sarr	filename = linker_basename(pathname);
1146159845Sjhb	KLD_LOCK();
114791040Sarr	lf = linker_find_file_by_name(filename);
114891040Sarr	if (lf)
114991040Sarr		td->td_retval[0] = lf->id;
115091040Sarr	else
115191040Sarr		error = ENOENT;
1152159845Sjhb	KLD_UNLOCK();
115325537Sdfrout:
1154159791Sjhb	free(pathname, M_TEMP);
115591040Sarr	return (error);
115625537Sdfr}
115725537Sdfr
115825537Sdfrint
115991040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
116025537Sdfr{
116191040Sarr	linker_file_t lf;
116291040Sarr	int error = 0;
116325537Sdfr
1164107089Srwatson#ifdef MAC
1165172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1166107089Srwatson	if (error)
1167107089Srwatson		return (error);
1168107089Srwatson#endif
1169107089Srwatson
1170159845Sjhb	KLD_LOCK();
1171166921Sjhb	if (uap->fileid == 0)
1172166921Sjhb		lf = TAILQ_FIRST(&linker_files);
1173166921Sjhb	else {
1174166921Sjhb		lf = linker_find_file_by_id(uap->fileid);
1175166921Sjhb		if (lf == NULL) {
1176166921Sjhb			error = ENOENT;
1177166921Sjhb			goto out;
1178166921Sjhb		}
1179166921Sjhb		lf = TAILQ_NEXT(lf, link);
118091040Sarr	}
1181166921Sjhb
1182166921Sjhb	/* Skip partially loaded files. */
1183166921Sjhb	while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1184166921Sjhb		lf = TAILQ_NEXT(lf, link);
1185166921Sjhb
1186166921Sjhb	if (lf)
1187166921Sjhb		td->td_retval[0] = lf->id;
1188166921Sjhb	else
1189166921Sjhb		td->td_retval[0] = 0;
119082749Sdillonout:
1191159845Sjhb	KLD_UNLOCK();
119291040Sarr	return (error);
119325537Sdfr}
119425537Sdfr
119525537Sdfrint
119691040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
119725537Sdfr{
1198159587Sjhb	struct kld_file_stat stat;
119991040Sarr	linker_file_t lf;
1200172862Sjb	int error, namelen, version, version_num;
120125537Sdfr
1202159587Sjhb	/*
1203159587Sjhb	 * Check the version of the user's structure.
1204159587Sjhb	 */
1205172862Sjb	if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
1206159587Sjhb		return (error);
1207172862Sjb	if (version == sizeof(struct kld_file_stat_1))
1208172862Sjb		version_num = 1;
1209172862Sjb	else if (version == sizeof(struct kld_file_stat))
1210172862Sjb		version_num = 2;
1211172862Sjb	else
1212159587Sjhb		return (EINVAL);
1213159587Sjhb
1214107089Srwatson#ifdef MAC
1215172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1216107089Srwatson	if (error)
1217107089Srwatson		return (error);
1218107089Srwatson#endif
1219107089Srwatson
1220159845Sjhb	KLD_LOCK();
1221107849Salfred	lf = linker_find_file_by_id(uap->fileid);
122291040Sarr	if (lf == NULL) {
1223159845Sjhb		KLD_UNLOCK();
1224159587Sjhb		return (ENOENT);
122591040Sarr	}
122625537Sdfr
1227172862Sjb	/* Version 1 fields: */
122891040Sarr	namelen = strlen(lf->filename) + 1;
122991040Sarr	if (namelen > MAXPATHLEN)
123091040Sarr		namelen = MAXPATHLEN;
1231159587Sjhb	bcopy(lf->filename, &stat.name[0], namelen);
1232159587Sjhb	stat.refs = lf->refs;
1233159587Sjhb	stat.id = lf->id;
1234159587Sjhb	stat.address = lf->address;
1235159587Sjhb	stat.size = lf->size;
1236172862Sjb	if (version_num > 1) {
1237172862Sjb		/* Version 2 fields: */
1238172862Sjb		namelen = strlen(lf->pathname) + 1;
1239172862Sjb		if (namelen > MAXPATHLEN)
1240172862Sjb			namelen = MAXPATHLEN;
1241172862Sjb		bcopy(lf->pathname, &stat.pathname[0], namelen);
1242172862Sjb	}
1243159845Sjhb	KLD_UNLOCK();
124425537Sdfr
124591040Sarr	td->td_retval[0] = 0;
1246159587Sjhb
1247172862Sjb	return (copyout(&stat, uap->stat, version));
124825537Sdfr}
124925537Sdfr
125025537Sdfrint
125191040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
125225537Sdfr{
125391040Sarr	linker_file_t lf;
125491040Sarr	module_t mp;
125591040Sarr	int error = 0;
125625537Sdfr
1257107089Srwatson#ifdef MAC
1258172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1259107089Srwatson	if (error)
1260107089Srwatson		return (error);
1261107089Srwatson#endif
1262107089Srwatson
1263159845Sjhb	KLD_LOCK();
1264107849Salfred	lf = linker_find_file_by_id(uap->fileid);
126591040Sarr	if (lf) {
126692547Sarr		MOD_SLOCK;
126791040Sarr		mp = TAILQ_FIRST(&lf->modules);
126891040Sarr		if (mp != NULL)
126991040Sarr			td->td_retval[0] = module_getid(mp);
127091040Sarr		else
127191040Sarr			td->td_retval[0] = 0;
127292547Sarr		MOD_SUNLOCK;
127391040Sarr	} else
127491040Sarr		error = ENOENT;
1275159845Sjhb	KLD_UNLOCK();
127691040Sarr	return (error);
127725537Sdfr}
127840159Speter
127941090Speterint
128083366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
128141090Speter{
128291040Sarr	char *symstr = NULL;
128391040Sarr	c_linker_sym_t sym;
128491040Sarr	linker_symval_t symval;
128591040Sarr	linker_file_t lf;
128691040Sarr	struct kld_sym_lookup lookup;
128791040Sarr	int error = 0;
128841090Speter
1289107089Srwatson#ifdef MAC
1290172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1291107089Srwatson	if (error)
1292107089Srwatson		return (error);
1293107089Srwatson#endif
1294107089Srwatson
1295107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1296159843Sjhb		return (error);
129791068Sarr	if (lookup.version != sizeof(lookup) ||
1298159843Sjhb	    uap->cmd != KLDSYM_LOOKUP)
1299159843Sjhb		return (EINVAL);
1300111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
130191040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
130291040Sarr		goto out;
1303159845Sjhb	KLD_LOCK();
1304107849Salfred	if (uap->fileid != 0) {
1305107849Salfred		lf = linker_find_file_by_id(uap->fileid);
1306159843Sjhb		if (lf == NULL)
130791040Sarr			error = ENOENT;
1308159843Sjhb		else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
130991040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
131091040Sarr			lookup.symvalue = (uintptr_t) symval.value;
131191040Sarr			lookup.symsize = symval.size;
1312107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
131391040Sarr		} else
131491040Sarr			error = ENOENT;
131591040Sarr	} else {
131691040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
131791040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
131891040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
131991040Sarr				lookup.symvalue = (uintptr_t)symval.value;
132091040Sarr				lookup.symsize = symval.size;
1321107849Salfred				error = copyout(&lookup, uap->data,
132291040Sarr				    sizeof(lookup));
132391068Sarr				break;
132491040Sarr			}
132591040Sarr		}
132691040Sarr		if (lf == NULL)
132791040Sarr			error = ENOENT;
132841090Speter	}
1329159845Sjhb	KLD_UNLOCK();
133041090Speterout:
1331159843Sjhb	free(symstr, M_TEMP);
133291040Sarr	return (error);
133341090Speter}
133441090Speter
133540159Speter/*
133640159Speter * Preloaded module support
133740159Speter */
133840159Speter
133959751Speterstatic modlist_t
134074642Sbpmodlist_lookup(const char *name, int ver)
134159751Speter{
134291040Sarr	modlist_t mod;
134359751Speter
134491040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
134592032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
134692032Sdwmalone		    (ver == 0 || mod->version == ver))
134791040Sarr			return (mod);
134891040Sarr	}
134991040Sarr	return (NULL);
135059751Speter}
135159751Speter
135274642Sbpstatic modlist_t
135383321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
135483321Speter{
135591040Sarr	modlist_t mod, bestmod;
135692032Sdwmalone	int ver;
135783321Speter
135891040Sarr	if (verinfo == NULL)
135991040Sarr		return (modlist_lookup(name, 0));
136091040Sarr	bestmod = NULL;
1361159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
136292032Sdwmalone		if (strcmp(mod->name, name) != 0)
136391040Sarr			continue;
136491040Sarr		ver = mod->version;
136591040Sarr		if (ver == verinfo->md_ver_preferred)
136691040Sarr			return (mod);
136791040Sarr		if (ver >= verinfo->md_ver_minimum &&
136891068Sarr		    ver <= verinfo->md_ver_maximum &&
1369120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
137091040Sarr			bestmod = mod;
137191040Sarr	}
137291040Sarr	return (bestmod);
137383321Speter}
137483321Speter
137583321Speterstatic modlist_t
137678501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
137774642Sbp{
137891040Sarr	modlist_t mod;
137974642Sbp
138092705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
138191040Sarr	if (mod == NULL)
138291040Sarr		panic("no memory for module list");
138391040Sarr	mod->container = container;
138491040Sarr	mod->name = modname;
138591040Sarr	mod->version = version;
138691040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
138791040Sarr	return (mod);
138874642Sbp}
138974642Sbp
139040159Speterstatic void
139178161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
139291040Sarr    struct mod_metadata **stop, int preload)
139374642Sbp{
139491040Sarr	struct mod_metadata *mp, **mdp;
139591040Sarr	const char *modname;
139691040Sarr	int ver;
139774642Sbp
139891040Sarr	for (mdp = start; mdp < stop; mdp++) {
1399109605Sjake		mp = *mdp;
140091040Sarr		if (mp->md_type != MDT_VERSION)
140191040Sarr			continue;
1402109605Sjake		modname = mp->md_cval;
1403109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
140491040Sarr		if (modlist_lookup(modname, ver) != NULL) {
140591040Sarr			printf("module %s already present!\n", modname);
140691040Sarr			/* XXX what can we do? this is a build error. :-( */
140791040Sarr			continue;
140891040Sarr		}
140991040Sarr		modlist_newmodule(modname, ver, lf);
141074642Sbp	}
141174642Sbp}
141274642Sbp
141374642Sbpstatic void
141491040Sarrlinker_preload(void *arg)
141540159Speter{
141691040Sarr	caddr_t modptr;
141791040Sarr	const char *modname, *nmodname;
141891040Sarr	char *modtype;
1419160244Sjhb	linker_file_t lf, nlf;
142091040Sarr	linker_class_t lc;
142192032Sdwmalone	int error;
142291040Sarr	linker_file_list_t loaded_files;
142391040Sarr	linker_file_list_t depended_files;
142491040Sarr	struct mod_metadata *mp, *nmp;
142591040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
142691040Sarr	struct mod_depend *verinfo;
142791040Sarr	int nver;
142891040Sarr	int resolves;
142991040Sarr	modlist_t mod;
143091040Sarr	struct sysinit **si_start, **si_stop;
143140159Speter
143291040Sarr	TAILQ_INIT(&loaded_files);
143391040Sarr	TAILQ_INIT(&depended_files);
143491040Sarr	TAILQ_INIT(&found_modules);
143591040Sarr	error = 0;
143659751Speter
143791040Sarr	modptr = NULL;
143891040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
143991040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
144091040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
144191040Sarr		if (modname == NULL) {
144291040Sarr			printf("Preloaded module at %p does not have a"
144391040Sarr			    " name!\n", modptr);
144491040Sarr			continue;
144591040Sarr		}
144691040Sarr		if (modtype == NULL) {
144791040Sarr			printf("Preloaded module at %p does not have a type!\n",
144891040Sarr			    modptr);
144991040Sarr			continue;
145091040Sarr		}
1451131398Sjhb		if (bootverbose)
1452131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1453131398Sjhb			    modptr);
145440159Speter		lf = NULL;
145591040Sarr		TAILQ_FOREACH(lc, &classes, link) {
145691040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1457134364Siedowse			if (!error)
145891040Sarr				break;
1459134364Siedowse			lf = NULL;
146091040Sarr		}
146191040Sarr		if (lf)
146291040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
146340159Speter	}
146440159Speter
146591040Sarr	/*
146691040Sarr	 * First get a list of stuff in the kernel.
146791040Sarr	 */
146891040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
146991040Sarr	    &stop, NULL) == 0)
147091040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
147159751Speter
147259751Speter	/*
1473167019Sjhb	 * This is a once-off kinky bubble sort to resolve relocation
1474167019Sjhb	 * dependency requirements.
147559751Speter	 */
147691040Sarrrestart:
147791040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
147891040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
147991040Sarr		    &stop, NULL);
148091040Sarr		/*
148191040Sarr		 * First, look to see if we would successfully link with this
148291040Sarr		 * stuff.
148391040Sarr		 */
148491040Sarr		resolves = 1;	/* unless we know otherwise */
148591040Sarr		if (!error) {
148691040Sarr			for (mdp = start; mdp < stop; mdp++) {
1487109605Sjake				mp = *mdp;
148891040Sarr				if (mp->md_type != MDT_DEPEND)
148991040Sarr					continue;
1490109605Sjake				modname = mp->md_cval;
1491109605Sjake				verinfo = mp->md_data;
149291040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1493109605Sjake					nmp = *nmdp;
149491040Sarr					if (nmp->md_type != MDT_VERSION)
149591040Sarr						continue;
1496109605Sjake					nmodname = nmp->md_cval;
149792032Sdwmalone					if (strcmp(modname, nmodname) == 0)
149891040Sarr						break;
149991040Sarr				}
150091040Sarr				if (nmdp < stop)   /* it's a self reference */
150191040Sarr					continue;
1502159840Sjhb
150391040Sarr				/*
150491040Sarr				 * ok, the module isn't here yet, we
150591040Sarr				 * are not finished
150691040Sarr				 */
150791068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
150891040Sarr					resolves = 0;
150991040Sarr			}
151064143Speter		}
151191040Sarr		/*
151291040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
151391040Sarr		 * the modules inside and add it to the end of the link order
151491040Sarr		 * list.
151591040Sarr		 */
151691040Sarr		if (resolves) {
151791040Sarr			if (!error) {
151891040Sarr				for (mdp = start; mdp < stop; mdp++) {
1519109605Sjake					mp = *mdp;
152091040Sarr					if (mp->md_type != MDT_VERSION)
152191040Sarr						continue;
1522109605Sjake					modname = mp->md_cval;
1523109605Sjake					nver = ((struct mod_version *)
1524109605Sjake					    mp->md_data)->mv_version;
152591040Sarr					if (modlist_lookup(modname,
152691040Sarr					    nver) != NULL) {
152791040Sarr						printf("module %s already"
152891040Sarr						    " present!\n", modname);
1529160244Sjhb						TAILQ_REMOVE(&loaded_files,
1530160244Sjhb						    lf, loaded);
1531132117Sphk						linker_file_unload(lf,
1532132117Sphk						    LINKER_UNLOAD_FORCE);
153391040Sarr						/* we changed tailq next ptr */
153491068Sarr						goto restart;
153591040Sarr					}
153691040Sarr					modlist_newmodule(modname, nver, lf);
153791040Sarr				}
153891040Sarr			}
153991040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
154091040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
154191040Sarr			/*
154291040Sarr			 * Since we provided modules, we need to restart the
154391040Sarr			 * sort so that the previous files that depend on us
154491040Sarr			 * have a chance. Also, we've busted the tailq next
154591040Sarr			 * pointer with the REMOVE.
154691040Sarr			 */
154791040Sarr			goto restart;
154859751Speter		}
154959751Speter	}
155091040Sarr
155159751Speter	/*
155291040Sarr	 * At this point, we check to see what could not be resolved..
155359751Speter	 */
1554160242Sjhb	while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1555160242Sjhb		TAILQ_REMOVE(&loaded_files, lf, loaded);
155691040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1557132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
155840159Speter	}
155959751Speter
156078161Speter	/*
156191040Sarr	 * We made it. Finish off the linking in the order we determined.
156278161Speter	 */
1563160244Sjhb	TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
156491040Sarr		if (linker_kernel_file) {
156591040Sarr			linker_kernel_file->refs++;
156691040Sarr			error = linker_file_add_dependency(lf,
156791040Sarr			    linker_kernel_file);
156891040Sarr			if (error)
156991040Sarr				panic("cannot add dependency");
157091040Sarr		}
157191040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
157291040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
157391040Sarr		    &stop, NULL);
157491040Sarr		if (!error) {
157591040Sarr			for (mdp = start; mdp < stop; mdp++) {
1576109605Sjake				mp = *mdp;
157791040Sarr				if (mp->md_type != MDT_DEPEND)
157891040Sarr					continue;
1579109605Sjake				modname = mp->md_cval;
1580109605Sjake				verinfo = mp->md_data;
158191040Sarr				mod = modlist_lookup2(modname, verinfo);
1582151484Sjdp				/* Don't count self-dependencies */
1583151484Sjdp				if (lf == mod->container)
1584151484Sjdp					continue;
158591040Sarr				mod->container->refs++;
158691040Sarr				error = linker_file_add_dependency(lf,
158791040Sarr				    mod->container);
158891040Sarr				if (error)
158991040Sarr					panic("cannot add dependency");
159091040Sarr			}
159191040Sarr		}
159291040Sarr		/*
159391040Sarr		 * Now do relocation etc using the symbol search paths
159491040Sarr		 * established by the dependencies
159591040Sarr		 */
159691040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
159791040Sarr		if (error) {
1598160244Sjhb			TAILQ_REMOVE(&depended_files, lf, loaded);
159991040Sarr			printf("KLD file %s - could not finalize loading\n",
160091040Sarr			    lf->filename);
1601132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
160291040Sarr			continue;
160391040Sarr		}
160491040Sarr		linker_file_register_modules(lf);
160591040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
160691040Sarr		    &si_stop, NULL) == 0)
160791040Sarr			sysinit_add(si_start, si_stop);
160891040Sarr		linker_file_register_sysctls(lf);
160991040Sarr		lf->flags |= LINKER_FILE_LINKED;
161059751Speter	}
161191040Sarr	/* woohoo! we made it! */
161240159Speter}
161340159Speter
1614177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
161540159Speter
161640159Speter/*
161740159Speter * Search for a not-loaded module by name.
1618159840Sjhb *
161940159Speter * Modules may be found in the following locations:
1620159840Sjhb *
162191040Sarr * - preloaded (result is just the module name) - on disk (result is full path
162291040Sarr * to module)
1623159840Sjhb *
162491040Sarr * If the module name is qualified in any way (contains path, etc.) the we
162591040Sarr * simply return a copy of it.
1626159840Sjhb *
162740159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
162840159Speter * character as a separator to be consistent with the bootloader.
162940159Speter */
163040159Speter
163183321Speterstatic char linker_hintfile[] = "linker.hints";
1632111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
163340159Speter
163440159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
163591040Sarr    sizeof(linker_path), "module load search path");
163640159Speter
163777843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
163870417Speter
163959751Speterstatic char *linker_ext_list[] = {
164083321Speter	"",
164159751Speter	".ko",
164259751Speter	NULL
164359751Speter};
164459751Speter
164583321Speter/*
164691040Sarr * Check if file actually exists either with or without extension listed in
164791040Sarr * the linker_ext_list. (probably should be generic for the rest of the
164891040Sarr * kernel)
164983321Speter */
165059751Speterstatic char *
165191040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
165291040Sarr    int namelen, struct vattr *vap)
165340159Speter{
165491040Sarr	struct nameidata nd;
165591040Sarr	struct thread *td = curthread;	/* XXX */
165691040Sarr	char *result, **cpp, *sep;
1657159808Sjhb	int error, len, extlen, reclen, flags, vfslocked;
165891040Sarr	enum vtype type;
165940159Speter
166091040Sarr	extlen = 0;
166191040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
166291040Sarr		len = strlen(*cpp);
166391040Sarr		if (len > extlen)
166491040Sarr			extlen = len;
166591040Sarr	}
166691040Sarr	extlen++;		/* trailing '\0' */
166791040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
166883321Speter
166991040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1670111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
167191040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
167291040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
167391040Sarr		    namelen, name, *cpp);
167491040Sarr		/*
167591040Sarr		 * Attempt to open the file, and return the path if
167691040Sarr		 * we succeed and it's a regular file.
167791040Sarr		 */
1678159808Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td);
167991040Sarr		flags = FREAD;
1680170152Skib		error = vn_open(&nd, &flags, 0, NULL);
168191040Sarr		if (error == 0) {
1682159808Sjhb			vfslocked = NDHASGIANT(&nd);
168391040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
168491040Sarr			type = nd.ni_vp->v_type;
168591040Sarr			if (vap)
1686182371Sattilio				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1687175294Sattilio			VOP_UNLOCK(nd.ni_vp, 0);
168891406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
1689159808Sjhb			VFS_UNLOCK_GIANT(vfslocked);
169091040Sarr			if (type == VREG)
169191040Sarr				return (result);
169291040Sarr		}
169383321Speter	}
169491040Sarr	free(result, M_LINKER);
169591040Sarr	return (NULL);
169683321Speter}
169783321Speter
169891040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
169983321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
170083321Speter
170183321Speter/*
170291040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
170391040Sarr * version specification is available, then try to find the best KLD.
170483321Speter * Otherwise just find the latest one.
170583321Speter */
170683321Speterstatic char *
170791040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
170891040Sarr    int modnamelen, struct mod_depend *verinfo)
170983321Speter{
171091040Sarr	struct thread *td = curthread;	/* XXX */
171191406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
171291040Sarr	struct nameidata nd;
171391040Sarr	struct vattr vattr, mattr;
171491040Sarr	u_char *hints = NULL;
171591040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
171691040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1717159808Sjhb	int vfslocked = 0;
171883321Speter
171991040Sarr	result = NULL;
172091040Sarr	bestver = found = 0;
172183321Speter
172291040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
172391040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
172491040Sarr	    strlen(sep) + 1;
1725111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
172691040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
172791040Sarr	    linker_hintfile);
172883321Speter
1729159808Sjhb	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td);
173091040Sarr	flags = FREAD;
1731170152Skib	error = vn_open(&nd, &flags, 0, NULL);
173291040Sarr	if (error)
173391040Sarr		goto bad;
1734159808Sjhb	vfslocked = NDHASGIANT(&nd);
173591040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
173691040Sarr	if (nd.ni_vp->v_type != VREG)
173791040Sarr		goto bad;
173891040Sarr	best = cp = NULL;
1739182371Sattilio	error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
174091040Sarr	if (error)
174191040Sarr		goto bad;
174291040Sarr	/*
174391040Sarr	 * XXX: we need to limit this number to some reasonable value
174491040Sarr	 */
174591040Sarr	if (vattr.va_size > 100 * 1024) {
174691040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
174791040Sarr		goto bad;
174891040Sarr	}
1749111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
175091040Sarr	if (hints == NULL)
175191040Sarr		goto bad;
175291068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1753101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
175491040Sarr	if (error)
175591040Sarr		goto bad;
1756175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
175791040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
1758159808Sjhb	VFS_UNLOCK_GIANT(vfslocked);
175991040Sarr	nd.ni_vp = NULL;
176091040Sarr	if (reclen != 0) {
176191040Sarr		printf("can't read %d\n", reclen);
176291040Sarr		goto bad;
176391040Sarr	}
176491040Sarr	intp = (int *)hints;
176583321Speter	ival = *intp++;
176691040Sarr	if (ival != LINKER_HINTS_VERSION) {
176791040Sarr		printf("hints file version mismatch %d\n", ival);
176891040Sarr		goto bad;
176983321Speter	}
177091040Sarr	bufend = hints + vattr.va_size;
177191040Sarr	recptr = (u_char *)intp;
177291040Sarr	clen = blen = 0;
177391040Sarr	while (recptr < bufend && !found) {
177491040Sarr		intp = (int *)recptr;
177591040Sarr		reclen = *intp++;
177691040Sarr		ival = *intp++;
177791040Sarr		cp = (char *)intp;
177891040Sarr		switch (ival) {
177991040Sarr		case MDT_VERSION:
178091040Sarr			clen = *cp++;
178191040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
178291040Sarr				break;
178391040Sarr			cp += clen;
178491040Sarr			INT_ALIGN(hints, cp);
178591040Sarr			ival = *(int *)cp;
178691040Sarr			cp += sizeof(int);
178791040Sarr			clen = *cp++;
178891040Sarr			if (verinfo == NULL ||
178991040Sarr			    ival == verinfo->md_ver_preferred) {
179091040Sarr				found = 1;
179191040Sarr				break;
179291040Sarr			}
179391040Sarr			if (ival >= verinfo->md_ver_minimum &&
179491040Sarr			    ival <= verinfo->md_ver_maximum &&
179591040Sarr			    ival > bestver) {
179691040Sarr				bestver = ival;
179791040Sarr				best = cp;
179891040Sarr				blen = clen;
179991040Sarr			}
180091040Sarr			break;
180191040Sarr		default:
180291040Sarr			break;
180391040Sarr		}
180491040Sarr		recptr += reclen + sizeof(int);
180591040Sarr	}
180683321Speter	/*
180791040Sarr	 * Finally check if KLD is in the place
180883321Speter	 */
180991040Sarr	if (found)
181091040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
181191040Sarr	else if (best)
181291040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
181391040Sarr
181491040Sarr	/*
181591040Sarr	 * KLD is newer than hints file. What we should do now?
181691040Sarr	 */
181791040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
181891040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
181991040Sarr		    " file\n", result);
182083321Speterbad:
1821105167Sphk	free(pathbuf, M_LINKER);
182291040Sarr	if (hints)
182391040Sarr		free(hints, M_TEMP);
182499553Sjeff	if (nd.ni_vp != NULL) {
1825175294Sattilio		VOP_UNLOCK(nd.ni_vp, 0);
182691040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
1827159808Sjhb		VFS_UNLOCK_GIANT(vfslocked);
182899553Sjeff	}
182991040Sarr	/*
183091040Sarr	 * If nothing found or hints is absent - fallback to the old
183191040Sarr	 * way by using "kldname[.ko]" as module name.
183291040Sarr	 */
183391040Sarr	if (!found && !bestver && result == NULL)
183491040Sarr		result = linker_lookup_file(path, pathlen, modname,
183591040Sarr		    modnamelen, NULL);
183691040Sarr	return (result);
183783321Speter}
183883321Speter
183983321Speter/*
184083321Speter * Lookup KLD which contains requested module in the all directories.
184183321Speter */
184283321Speterstatic char *
184383321Speterlinker_search_module(const char *modname, int modnamelen,
184491040Sarr    struct mod_depend *verinfo)
184583321Speter{
184691040Sarr	char *cp, *ep, *result;
184783321Speter
184891040Sarr	/*
184991040Sarr	 * traverse the linker path
185091040Sarr	 */
185191040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
185291040Sarr		/* find the end of this component */
185391040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
185491068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
185591068Sarr		    modnamelen, verinfo);
185691040Sarr		if (result != NULL)
185791040Sarr			return (result);
185891040Sarr		if (*ep == 0)
185991040Sarr			break;
186091040Sarr	}
186191040Sarr	return (NULL);
186283321Speter}
186383321Speter
186483321Speter/*
186583321Speter * Search for module in all directories listed in the linker_path.
186683321Speter */
186783321Speterstatic char *
186883321Speterlinker_search_kld(const char *name)
186983321Speter{
1870158972Sdelphij	char *cp, *ep, *result;
1871158972Sdelphij	int len;
187283321Speter
187391040Sarr	/* qualified at all? */
187491040Sarr	if (index(name, '/'))
187591040Sarr		return (linker_strdup(name));
187640159Speter
187791040Sarr	/* traverse the linker path */
187891040Sarr	len = strlen(name);
187991040Sarr	for (ep = linker_path; *ep; ep++) {
188091040Sarr		cp = ep;
188191040Sarr		/* find the end of this component */
188291040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
188391040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
188491040Sarr		if (result != NULL)
188591040Sarr			return (result);
188691040Sarr	}
188791040Sarr	return (NULL);
188840159Speter}
188959751Speter
189059751Speterstatic const char *
189191040Sarrlinker_basename(const char *path)
189259751Speter{
189391040Sarr	const char *filename;
189459751Speter
189591040Sarr	filename = rindex(path, '/');
189691040Sarr	if (filename == NULL)
189791040Sarr		return path;
189891040Sarr	if (filename[1])
189991040Sarr		filename++;
190091040Sarr	return (filename);
190159751Speter}
190259751Speter
1903157144Sjkoshy#ifdef HWPMC_HOOKS
190459751Speter/*
1905157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1906157144Sjkoshy */
1907157144Sjkoshyvoid *
1908157144Sjkoshylinker_hwpmc_list_objects(void)
1909157144Sjkoshy{
1910195159Sattilio	linker_file_t lf;
1911195159Sattilio	struct pmckern_map_in *kobase;
1912195159Sattilio	int i, nmappings;
1913157144Sjkoshy
1914195159Sattilio	nmappings = 0;
1915195159Sattilio	KLD_LOCK();
1916195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link)
1917195159Sattilio		nmappings++;
1918157144Sjkoshy
1919195159Sattilio	/* Allocate nmappings + 1 entries. */
1920195159Sattilio	kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in),
1921184214Sdes	    M_LINKER, M_WAITOK | M_ZERO);
1922195159Sattilio	i = 0;
1923195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link) {
1924157144Sjkoshy
1925195159Sattilio		/* Save the info for this linker file. */
1926195159Sattilio		kobase[i].pm_file = lf->filename;
1927195159Sattilio		kobase[i].pm_address = (uintptr_t)lf->address;
1928195159Sattilio		i++;
1929157144Sjkoshy	}
1930195159Sattilio	KLD_UNLOCK();
1931157144Sjkoshy
1932195159Sattilio	KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
1933157144Sjkoshy
1934157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1935195159Sattilio	KASSERT(kobase[i].pm_file == NULL,
1936157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1937157144Sjkoshy
1938195159Sattilio	return ((void *)kobase);
1939157144Sjkoshy}
1940157144Sjkoshy#endif
1941157144Sjkoshy
1942157144Sjkoshy/*
194391040Sarr * Find a file which contains given module and load it, if "parent" is not
194491040Sarr * NULL, register a reference to it.
194559751Speter */
1946159796Sjhbstatic int
194783321Speterlinker_load_module(const char *kldname, const char *modname,
194891040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
194991040Sarr    struct linker_file **lfpp)
195059751Speter{
195191040Sarr	linker_file_t lfdep;
195291040Sarr	const char *filename;
195391040Sarr	char *pathname;
195491040Sarr	int error;
195559751Speter
1956159845Sjhb	KLD_LOCK_ASSERT();
195791040Sarr	if (modname == NULL) {
195891040Sarr		/*
195991040Sarr 		 * We have to load KLD
196091040Sarr 		 */
196191068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
196291068Sarr		    " is not NULL"));
196391040Sarr		pathname = linker_search_kld(kldname);
196491040Sarr	} else {
196591040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
196691040Sarr			return (EEXIST);
196794322Sbrian		if (kldname != NULL)
196894322Sbrian			pathname = linker_strdup(kldname);
196995488Sbrian		else if (rootvnode == NULL)
197094322Sbrian			pathname = NULL;
197194322Sbrian		else
197291040Sarr			/*
197391040Sarr			 * Need to find a KLD with required module
197491040Sarr			 */
197591040Sarr			pathname = linker_search_module(modname,
197691040Sarr			    strlen(modname), verinfo);
197791040Sarr	}
197891040Sarr	if (pathname == NULL)
197991040Sarr		return (ENOENT);
198091040Sarr
198183321Speter	/*
198291040Sarr	 * Can't load more than one file with the same basename XXX:
198391040Sarr	 * Actually it should be possible to have multiple KLDs with
198491040Sarr	 * the same basename but different path because they can
198591040Sarr	 * provide different versions of the same modules.
198683321Speter	 */
198791040Sarr	filename = linker_basename(pathname);
1988159792Sjhb	if (linker_find_file_by_name(filename))
198991040Sarr		error = EEXIST;
1990159792Sjhb	else do {
199191040Sarr		error = linker_load_file(pathname, &lfdep);
199291040Sarr		if (error)
199391040Sarr			break;
199491040Sarr		if (modname && verinfo &&
199591040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
1996132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
199791040Sarr			error = ENOENT;
199891040Sarr			break;
199991040Sarr		}
200091040Sarr		if (parent) {
200191040Sarr			error = linker_file_add_dependency(parent, lfdep);
200291040Sarr			if (error)
200391040Sarr				break;
200491040Sarr		}
200591040Sarr		if (lfpp)
200691040Sarr			*lfpp = lfdep;
200791040Sarr	} while (0);
2008159791Sjhb	free(pathname, M_LINKER);
200991040Sarr	return (error);
201059751Speter}
201159751Speter
201259751Speter/*
201391040Sarr * This routine is responsible for finding dependencies of userland initiated
201491040Sarr * kldload(2)'s of files.
201559751Speter */
201659751Speterint
201786469Siedowselinker_load_dependencies(linker_file_t lf)
201859751Speter{
201991040Sarr	linker_file_t lfdep;
202091040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
202191040Sarr	struct mod_metadata *mp, *nmp;
202291040Sarr	struct mod_depend *verinfo;
202391040Sarr	modlist_t mod;
202491040Sarr	const char *modname, *nmodname;
202592032Sdwmalone	int ver, error = 0, count;
202659751Speter
202791040Sarr	/*
202891040Sarr	 * All files are dependant on /kernel.
202991040Sarr	 */
2030159845Sjhb	KLD_LOCK_ASSERT();
203191040Sarr	if (linker_kernel_file) {
203291040Sarr		linker_kernel_file->refs++;
203391040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
203491040Sarr		if (error)
203591040Sarr			return (error);
203659751Speter	}
203791040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
203891040Sarr	    &count) != 0)
203991040Sarr		return (0);
204091040Sarr	for (mdp = start; mdp < stop; mdp++) {
2041109605Sjake		mp = *mdp;
204291040Sarr		if (mp->md_type != MDT_VERSION)
204391040Sarr			continue;
2044109605Sjake		modname = mp->md_cval;
2045109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
204691040Sarr		mod = modlist_lookup(modname, ver);
204791040Sarr		if (mod != NULL) {
204891040Sarr			printf("interface %s.%d already present in the KLD"
204991040Sarr			    " '%s'!\n", modname, ver,
205091040Sarr			    mod->container->filename);
205191040Sarr			return (EEXIST);
205291040Sarr		}
205391040Sarr	}
205474642Sbp
205591040Sarr	for (mdp = start; mdp < stop; mdp++) {
2056109605Sjake		mp = *mdp;
205791040Sarr		if (mp->md_type != MDT_DEPEND)
205891040Sarr			continue;
2059109605Sjake		modname = mp->md_cval;
2060109605Sjake		verinfo = mp->md_data;
206191040Sarr		nmodname = NULL;
206291040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
2063109605Sjake			nmp = *nmdp;
206491040Sarr			if (nmp->md_type != MDT_VERSION)
206591040Sarr				continue;
2066109605Sjake			nmodname = nmp->md_cval;
206792032Sdwmalone			if (strcmp(modname, nmodname) == 0)
206891040Sarr				break;
206991040Sarr		}
207091040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
207191040Sarr			continue;
207291040Sarr		mod = modlist_lookup2(modname, verinfo);
207391040Sarr		if (mod) {	/* woohoo, it's loaded already */
207491040Sarr			lfdep = mod->container;
207591040Sarr			lfdep->refs++;
207691040Sarr			error = linker_file_add_dependency(lf, lfdep);
207791040Sarr			if (error)
207891040Sarr				break;
207991040Sarr			continue;
208091040Sarr		}
208191040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
208291040Sarr		if (error) {
2083195803Srpaulo			printf("KLD %s: depends on %s - not available or"
2084195803Srpaulo			    " version mismatch\n", lf->filename, modname);
208591040Sarr			break;
208691040Sarr		}
208759751Speter	}
208859751Speter
208991040Sarr	if (error)
209091040Sarr		return (error);
209191040Sarr	linker_addmodules(lf, start, stop, 0);
209291040Sarr	return (error);
209359751Speter}
209485736Sgreen
209585736Sgreenstatic int
209685736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
209785736Sgreen{
209885736Sgreen	struct sysctl_req *req;
209985736Sgreen
210085736Sgreen	req = opaque;
210185736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
210285736Sgreen}
210385736Sgreen
210485736Sgreen/*
210585736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
210685736Sgreen * in the kernel.
210785736Sgreen */
210885736Sgreenstatic int
210985736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
211085736Sgreen{
211185736Sgreen	linker_file_t lf;
211285736Sgreen	int error;
211385736Sgreen
2114107089Srwatson#ifdef MAC
2115172930Srwatson	error = mac_kld_check_stat(req->td->td_ucred);
2116107089Srwatson	if (error)
2117107089Srwatson		return (error);
2118107089Srwatson#endif
2119126253Struckman	error = sysctl_wire_old_buffer(req, 0);
2120126253Struckman	if (error != 0)
2121126253Struckman		return (error);
2122159845Sjhb	KLD_LOCK();
212385736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
212485736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
212585736Sgreen		    sysctl_kern_function_list_iterate, req);
212698452Sarr		if (error) {
2127159845Sjhb			KLD_UNLOCK();
212885736Sgreen			return (error);
212998452Sarr		}
213085736Sgreen	}
2131159845Sjhb	KLD_UNLOCK();
213285736Sgreen	return (SYSCTL_OUT(req, "", 1));
213385736Sgreen}
213485736Sgreen
213585736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
213691040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2137