kern_linker.c revision 199457
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 199457 2009-11-17 21:56:12Z gonzo $");
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;
67199457SgonzoSYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW,
68199457Sgonzo        &kld_debug, 0, "Set various levels of KLD debug");
6940961Speter#endif
7040961Speter
71160142Sjhb#define	KLD_LOCK()		sx_xlock(&kld_sx)
72160142Sjhb#define	KLD_UNLOCK()		sx_xunlock(&kld_sx)
73159845Sjhb#define	KLD_LOCKED()		sx_xlocked(&kld_sx)
74160142Sjhb#define	KLD_LOCK_ASSERT() do {						\
75160142Sjhb	if (!cold)							\
76160142Sjhb		sx_assert(&kld_sx, SX_XLOCKED);				\
77160142Sjhb} while (0)
78159845Sjhb
7991040Sarr/*
8091040Sarr * static char *linker_search_path(const char *name, struct mod_depend
8191040Sarr * *verinfo);
8291040Sarr */
8391040Sarrstatic const char 	*linker_basename(const char *path);
8459751Speter
85159800Sjhb/*
86159800Sjhb * Find a currently loaded file given its filename.
87159800Sjhb */
88159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
89159800Sjhb
90159800Sjhb/*
91159800Sjhb * Find a currently loaded file given its file id.
92159800Sjhb */
93159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
94159800Sjhb
9578161Speter/* Metadata from the static kernel */
9678161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
9778161Speter
9859751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
9959751Speter
10040906Speterlinker_file_t linker_kernel_file;
10131324Sbde
102159845Sjhbstatic struct sx kld_sx;	/* kernel linker lock */
10398452Sarr
104172862Sjb/*
105172862Sjb * Load counter used by clients to determine if a linker file has been
106172862Sjb * re-loaded. This counter is incremented for each file load.
107172862Sjb */
108172862Sjbstatic int loadcnt;
109172862Sjb
11025537Sdfrstatic linker_class_list_t classes;
11150068Sgrogstatic linker_file_list_t linker_files;
11225537Sdfrstatic int next_file_id = 1;
11398452Sarrstatic int linker_no_more_classes = 0;
11425537Sdfr
11586553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
11691040Sarr	linker_file_t lftmp;						\
11786553Sarr									\
118159845Sjhb	KLD_LOCK_ASSERT();						\
11986553Sarrretry:									\
12091040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
12191040Sarr		if (next_file_id == lftmp->id) {			\
12291040Sarr			next_file_id++;					\
12391040Sarr			goto retry;					\
12491040Sarr		}							\
12591040Sarr	}								\
12691040Sarr	(a) = next_file_id;						\
12786553Sarr} while(0)
12886553Sarr
12986553Sarr
13059751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
13160938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
13259751Speterstruct modlist {
13391040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
13491040Sarr	linker_file_t   container;
13591040Sarr	const char 	*name;
13691040Sarr	int             version;
13759751Speter};
13891040Sarrtypedef struct modlist *modlist_t;
13991040Sarrstatic modlisthead_t found_modules;
14059751Speter
141159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
142159796Sjhb		    linker_file_t dep);
143159845Sjhbstatic caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
144159845Sjhb		    const char* name, int deps);
145159796Sjhbstatic int	linker_load_module(const char *kldname,
146159796Sjhb		    const char *modname, struct linker_file *parent,
147159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
148159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
14994321Sbrian
15059603Sdfrstatic char *
15159603Sdfrlinker_strdup(const char *str)
15259603Sdfr{
15391040Sarr	char *result;
15459603Sdfr
155111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
15691040Sarr		strcpy(result, str);
15791040Sarr	return (result);
15859603Sdfr}
15959603Sdfr
16025537Sdfrstatic void
16191040Sarrlinker_init(void *arg)
16225537Sdfr{
16391040Sarr
164159845Sjhb	sx_init(&kld_sx, "kernel linker");
16591040Sarr	TAILQ_INIT(&classes);
16691040Sarr	TAILQ_INIT(&linker_files);
16725537Sdfr}
16825537Sdfr
169177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
17025537Sdfr
17198452Sarrstatic void
17298452Sarrlinker_stop_class_add(void *arg)
17398452Sarr{
17498452Sarr
17598452Sarr	linker_no_more_classes = 1;
17698452Sarr}
17798452Sarr
178177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL);
17998452Sarr
18025537Sdfrint
18159603Sdfrlinker_add_class(linker_class_t lc)
18225537Sdfr{
18391040Sarr
18498452Sarr	/*
185144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
186144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
187144443Sjhb	 * ops from being freed.
18898452Sarr	 */
18998452Sarr	if (linker_no_more_classes == 1)
19098452Sarr		return (EPERM);
19191040Sarr	kobj_class_compile((kobj_class_t) lc);
192144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
19391040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
19491040Sarr	return (0);
19525537Sdfr}
19625537Sdfr
19725537Sdfrstatic void
19825537Sdfrlinker_file_sysinit(linker_file_t lf)
19925537Sdfr{
20091040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
20125537Sdfr
20291040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
20391040Sarr	    lf->filename));
20425537Sdfr
20591040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
20691040Sarr		return;
20791040Sarr	/*
20891040Sarr	 * Perform a bubble sort of the system initialization objects by
20991040Sarr	 * their subsystem (primary key) and order (secondary key).
210159840Sjhb	 *
21191040Sarr	 * Since some things care about execution order, this is the operation
21291040Sarr	 * which ensures continued function.
21391040Sarr	 */
21491040Sarr	for (sipp = start; sipp < stop; sipp++) {
21591040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
21691040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
21791040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
21891040Sarr			    (*sipp)->order <= (*xipp)->order))
21991040Sarr				continue;	/* skip */
22091040Sarr			save = *sipp;
22191040Sarr			*sipp = *xipp;
22291040Sarr			*xipp = save;
22391040Sarr		}
22425537Sdfr	}
22525537Sdfr
22691040Sarr	/*
22791040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
22891040Sarr	 * Perform each task, and continue on to the next task.
22991040Sarr	 */
230160142Sjhb	mtx_lock(&Giant);
23191040Sarr	for (sipp = start; sipp < stop; sipp++) {
23291040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
23391040Sarr			continue;	/* skip dummy task(s) */
23425537Sdfr
23591040Sarr		/* Call function */
23691040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
23791040Sarr	}
238160142Sjhb	mtx_unlock(&Giant);
23925537Sdfr}
24025537Sdfr
24141055Speterstatic void
24241055Speterlinker_file_sysuninit(linker_file_t lf)
24341055Speter{
24491040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
24541055Speter
24691040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
24791040Sarr	    lf->filename));
24841055Speter
24991068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
25091040Sarr	    NULL) != 0)
25191040Sarr		return;
25241055Speter
25391040Sarr	/*
25491040Sarr	 * Perform a reverse bubble sort of the system initialization objects
25591040Sarr	 * by their subsystem (primary key) and order (secondary key).
256159840Sjhb	 *
25791040Sarr	 * Since some things care about execution order, this is the operation
25891040Sarr	 * which ensures continued function.
25991040Sarr	 */
26091040Sarr	for (sipp = start; sipp < stop; sipp++) {
26191040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
26291040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
26391040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
26491040Sarr			    (*sipp)->order >= (*xipp)->order))
26591040Sarr				continue;	/* skip */
26691040Sarr			save = *sipp;
26791040Sarr			*sipp = *xipp;
26891040Sarr			*xipp = save;
26991040Sarr		}
27041055Speter	}
27141055Speter
27291040Sarr	/*
27391040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
27491040Sarr	 * Perform each task, and continue on to the next task.
27591040Sarr	 */
276160142Sjhb	mtx_lock(&Giant);
27791040Sarr	for (sipp = start; sipp < stop; sipp++) {
27891040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
27991040Sarr			continue;	/* skip dummy task(s) */
28041055Speter
28191040Sarr		/* Call function */
28291040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
28391040Sarr	}
284160142Sjhb	mtx_unlock(&Giant);
28541055Speter}
28641055Speter
28744078Sdfrstatic void
28844078Sdfrlinker_file_register_sysctls(linker_file_t lf)
28944078Sdfr{
29091040Sarr	struct sysctl_oid **start, **stop, **oidp;
29144078Sdfr
29291040Sarr	KLD_DPF(FILE,
29391040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
29491040Sarr	    lf->filename));
29544078Sdfr
29691040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
29791040Sarr		return;
29844078Sdfr
299188232Sjhb	sysctl_lock();
30091040Sarr	for (oidp = start; oidp < stop; oidp++)
30191040Sarr		sysctl_register_oid(*oidp);
302188232Sjhb	sysctl_unlock();
30344078Sdfr}
30444078Sdfr
30544078Sdfrstatic void
30644078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
30744078Sdfr{
30891040Sarr	struct sysctl_oid **start, **stop, **oidp;
30944078Sdfr
31091040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
31191040Sarr	    " for %s\n", lf->filename));
31244078Sdfr
31391040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
31491040Sarr		return;
31544078Sdfr
316188232Sjhb	sysctl_lock();
31791040Sarr	for (oidp = start; oidp < stop; oidp++)
31891040Sarr		sysctl_unregister_oid(*oidp);
319188232Sjhb	sysctl_unlock();
32044078Sdfr}
32144078Sdfr
32259751Speterstatic int
32359751Speterlinker_file_register_modules(linker_file_t lf)
32459751Speter{
32591040Sarr	struct mod_metadata **start, **stop, **mdp;
32691040Sarr	const moduledata_t *moddata;
327146733Spjd	int first_error, error;
32859751Speter
32991040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
33091040Sarr	    " in %s\n", lf->filename));
33159751Speter
33291068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
333159841Sjhb	    &stop, NULL) != 0) {
33491040Sarr		/*
33591040Sarr		 * This fallback should be unnecessary, but if we get booted
33691040Sarr		 * from boot2 instead of loader and we are missing our
33791040Sarr		 * metadata then we have to try the best we can.
33891040Sarr		 */
33991040Sarr		if (lf == linker_kernel_file) {
34091040Sarr			start = SET_BEGIN(modmetadata_set);
34191040Sarr			stop = SET_LIMIT(modmetadata_set);
34291040Sarr		} else
34391040Sarr			return (0);
34478161Speter	}
345146733Spjd	first_error = 0;
34691040Sarr	for (mdp = start; mdp < stop; mdp++) {
34791040Sarr		if ((*mdp)->md_type != MDT_MODULE)
34891040Sarr			continue;
34991040Sarr		moddata = (*mdp)->md_data;
35091040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
35191040Sarr		    moddata->name, lf->filename));
35291040Sarr		error = module_register(moddata, lf);
353146730Spjd		if (error) {
35491068Sarr			printf("Module %s failed to register: %d\n",
35591040Sarr			    moddata->name, error);
356146733Spjd			if (first_error == 0)
357146733Spjd				first_error = error;
358146730Spjd		}
35959751Speter	}
360146733Spjd	return (first_error);
36159751Speter}
36259751Speter
36359751Speterstatic void
36459751Speterlinker_init_kernel_modules(void)
36559751Speter{
36691040Sarr
36791040Sarr	linker_file_register_modules(linker_kernel_file);
36859751Speter}
36959751Speter
370177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules,
371177253Srwatson    0);
37259751Speter
373101241Smuxstatic int
37491040Sarrlinker_load_file(const char *filename, linker_file_t *result)
37525537Sdfr{
37691040Sarr	linker_class_t lc;
37791040Sarr	linker_file_t lf;
378159585Sjhb	int foundfile, error;
37925537Sdfr
38091040Sarr	/* Refuse to load modules if securelevel raised */
381192895Sjamie	if (prison0.pr_securelevel > 0)
38291040Sarr		return (EPERM);
38362261Sarchie
384159845Sjhb	KLD_LOCK_ASSERT();
38591040Sarr	lf = linker_find_file_by_name(filename);
38691040Sarr	if (lf) {
38791040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
38891040Sarr		    " incrementing refs\n", filename));
38991040Sarr		*result = lf;
39091040Sarr		lf->refs++;
391159585Sjhb		return (0);
39291040Sarr	}
39391040Sarr	foundfile = 0;
394159585Sjhb	error = 0;
39598452Sarr
39698452Sarr	/*
39798452Sarr	 * We do not need to protect (lock) classes here because there is
39898452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
39998452Sarr	 * and there is no class deregistration mechanism at this time.
40098452Sarr	 */
40191040Sarr	TAILQ_FOREACH(lc, &classes, link) {
40291040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
40391040Sarr		    filename));
40491040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
40591040Sarr		/*
40691040Sarr		 * If we got something other than ENOENT, then it exists but
40791040Sarr		 * we cannot load it for some other reason.
40891040Sarr		 */
40991040Sarr		if (error != ENOENT)
41091040Sarr			foundfile = 1;
41191040Sarr		if (lf) {
412146730Spjd			error = linker_file_register_modules(lf);
413146730Spjd			if (error == EEXIST) {
414146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
415159585Sjhb				return (error);
416146730Spjd			}
417166921Sjhb			KLD_UNLOCK();
41891040Sarr			linker_file_register_sysctls(lf);
41991040Sarr			linker_file_sysinit(lf);
420166921Sjhb			KLD_LOCK();
42191040Sarr			lf->flags |= LINKER_FILE_LINKED;
42291040Sarr			*result = lf;
423159585Sjhb			return (0);
42491040Sarr		}
42591040Sarr	}
42642755Speter	/*
42791040Sarr	 * Less than ideal, but tells the user whether it failed to load or
42891040Sarr	 * the module was not found.
42942755Speter	 */
430105337Ssam	if (foundfile) {
431188440Sattilio
432105337Ssam		/*
433188440Sattilio		 * If the file type has not been recognized by the last try
434188440Sattilio		 * printout a message before to fail.
435188440Sattilio		 */
436188440Sattilio		if (error == ENOSYS)
437188440Sattilio			printf("linker_load_file: Unsupported file type\n");
438188440Sattilio
439188440Sattilio		/*
440105337Ssam		 * Format not recognized or otherwise unloadable.
441105337Ssam		 * When loading a module that is statically built into
442105337Ssam		 * the kernel EEXIST percolates back up as the return
443105337Ssam		 * value.  Preserve this so that apps like sysinstall
444105337Ssam		 * can recognize this special case and not post bogus
445105337Ssam		 * dialog boxes.
446105337Ssam		 */
447105337Ssam		if (error != EEXIST)
448105337Ssam			error = ENOEXEC;
449105337Ssam	} else
45091068Sarr		error = ENOENT;		/* Nothing found */
45191040Sarr	return (error);
45225537Sdfr}
45325537Sdfr
45478413Sbrianint
45594321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
45694321Sbrian    linker_file_t *result)
45778413Sbrian{
45894321Sbrian	modlist_t mod;
459159804Sjhb	int error;
46094321Sbrian
461159845Sjhb	KLD_LOCK();
46294321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
46394321Sbrian		*result = mod->container;
46494321Sbrian		(*result)->refs++;
465159845Sjhb		KLD_UNLOCK();
46694321Sbrian		return (0);
46794321Sbrian	}
46894321Sbrian
469159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
470159845Sjhb	KLD_UNLOCK();
471159804Sjhb	return (error);
47278413Sbrian}
47378413Sbrian
474159804Sjhbint
475159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
476159804Sjhb    linker_file_t lf)
477159804Sjhb{
478159804Sjhb	modlist_t mod;
479159804Sjhb	int error;
480159804Sjhb
481159845Sjhb	KLD_LOCK();
482159804Sjhb	if (lf == NULL) {
483159804Sjhb		KASSERT(modname != NULL,
484159804Sjhb		    ("linker_release_module: no file or name"));
485159804Sjhb		mod = modlist_lookup2(modname, verinfo);
486159804Sjhb		if (mod == NULL) {
487159845Sjhb			KLD_UNLOCK();
488159804Sjhb			return (ESRCH);
489159804Sjhb		}
490159804Sjhb		lf = mod->container;
491159804Sjhb	} else
492159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
493159804Sjhb		    ("linker_release_module: both file and name"));
494159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
495159845Sjhb	KLD_UNLOCK();
496159804Sjhb	return (error);
497159804Sjhb}
498159804Sjhb
499159800Sjhbstatic linker_file_t
50091040Sarrlinker_find_file_by_name(const char *filename)
50125537Sdfr{
502159585Sjhb	linker_file_t lf;
50391040Sarr	char *koname;
50425537Sdfr
505111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
50691040Sarr	sprintf(koname, "%s.ko", filename);
50740861Speter
508159845Sjhb	KLD_LOCK_ASSERT();
50991040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
51092032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
51191040Sarr			break;
51292032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
51391040Sarr			break;
51491040Sarr	}
515159585Sjhb	free(koname, M_LINKER);
51691040Sarr	return (lf);
51725537Sdfr}
51825537Sdfr
519159800Sjhbstatic linker_file_t
52025537Sdfrlinker_find_file_by_id(int fileid)
52125537Sdfr{
522159585Sjhb	linker_file_t lf;
523159845Sjhb
524159845Sjhb	KLD_LOCK_ASSERT();
52591040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
526166921Sjhb		if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
52791040Sarr			break;
52891040Sarr	return (lf);
52925537Sdfr}
53025537Sdfr
531159797Sjhbint
532159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
533159797Sjhb{
534159797Sjhb	linker_file_t lf;
535159797Sjhb	int retval = 0;
536159797Sjhb
537159845Sjhb	KLD_LOCK();
538159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
539159797Sjhb		retval = predicate(lf, context);
540159797Sjhb		if (retval != 0)
541159797Sjhb			break;
542159797Sjhb	}
543159845Sjhb	KLD_UNLOCK();
544159797Sjhb	return (retval);
545159797Sjhb}
546159797Sjhb
54725537Sdfrlinker_file_t
54891040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
54925537Sdfr{
55091040Sarr	linker_file_t lf;
55191040Sarr	const char *filename;
55225537Sdfr
553159845Sjhb	KLD_LOCK_ASSERT();
55491040Sarr	filename = linker_basename(pathname);
55540159Speter
556172862Sjb	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
557111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
55891040Sarr	if (lf == NULL)
559159585Sjhb		return (NULL);
56091040Sarr	lf->refs = 1;
56191040Sarr	lf->userrefs = 0;
56291040Sarr	lf->flags = 0;
56391040Sarr	lf->filename = linker_strdup(filename);
564172862Sjb	lf->pathname = linker_strdup(pathname);
56591040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
56691040Sarr	lf->ndeps = 0;
56791040Sarr	lf->deps = NULL;
568172862Sjb	lf->loadcnt = ++loadcnt;
569172862Sjb	lf->sdt_probes = NULL;
570172862Sjb	lf->sdt_nprobes = 0;
57191040Sarr	STAILQ_INIT(&lf->common);
57291040Sarr	TAILQ_INIT(&lf->modules);
57391040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
57491040Sarr	return (lf);
57525537Sdfr}
57625537Sdfr
57725537Sdfrint
578132117Sphklinker_file_unload(linker_file_t file, int flags)
57925537Sdfr{
58091040Sarr	module_t mod, next;
58191040Sarr	modlist_t ml, nextml;
58291040Sarr	struct common_symbol *cp;
58391040Sarr	int error, i;
58425537Sdfr
58591040Sarr	/* Refuse to unload modules if securelevel raised. */
586192895Sjamie	if (prison0.pr_securelevel > 0)
58791040Sarr		return (EPERM);
58825537Sdfr
589159845Sjhb	KLD_LOCK_ASSERT();
59091040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
59191040Sarr
592159584Sjhb	/* Easy case of just dropping a reference. */
593159584Sjhb	if (file->refs > 1) {
594159584Sjhb		file->refs--;
595159584Sjhb		return (0);
596159584Sjhb	}
597159584Sjhb
598159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
599159584Sjhb	    " informing modules\n"));
600159584Sjhb
601159584Sjhb	/*
602185635Sjhb	 * Quiesce all the modules to give them a chance to veto the unload.
603159584Sjhb	 */
604185635Sjhb	MOD_SLOCK;
605185635Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod;
606185635Sjhb	     mod = module_getfnext(mod)) {
607185635Sjhb
608185635Sjhb		error = module_quiesce(mod);
609185635Sjhb		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
610185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
611185635Sjhb			    " vetoed unload\n", module_getname(mod)));
612185635Sjhb			/*
613185635Sjhb			 * XXX: Do we need to tell all the quiesced modules
614185635Sjhb			 * that they can resume work now via a new module
615185635Sjhb			 * event?
616185635Sjhb			 */
617185635Sjhb			MOD_SUNLOCK;
618185635Sjhb			return (error);
619185635Sjhb		}
620185635Sjhb	}
621185635Sjhb	MOD_SUNLOCK;
622185635Sjhb
623185635Sjhb	/*
624185635Sjhb	 * Inform any modules associated with this file that they are
625185635Sjhb	 * being be unloaded.
626185635Sjhb	 */
627159584Sjhb	MOD_XLOCK;
628159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
629159584Sjhb		next = module_getfnext(mod);
630159584Sjhb		MOD_XUNLOCK;
631159584Sjhb
63291040Sarr		/*
633159584Sjhb		 * Give the module a chance to veto the unload.
63491040Sarr		 */
635185635Sjhb		if ((error = module_unload(mod)) != 0) {
636185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
637199457Sgonzo			    " failed unload\n", module_getname(mod)));
638159584Sjhb			return (error);
639159584Sjhb		}
64092547Sarr		MOD_XLOCK;
641159584Sjhb		module_release(mod);
642159584Sjhb	}
643159584Sjhb	MOD_XUNLOCK;
64491040Sarr
645159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
646128057Speadar		if (ml->container == file) {
64791040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
648128057Speadar			free(ml, M_LINKER);
649128057Speadar		}
65091040Sarr	}
65125537Sdfr
652159840Sjhb	/*
653159840Sjhb	 * Don't try to run SYSUNINITs if we are unloaded due to a
65491040Sarr	 * link error.
65591040Sarr	 */
65691040Sarr	if (file->flags & LINKER_FILE_LINKED) {
657188209Sjhb		file->flags &= ~LINKER_FILE_LINKED;
658188209Sjhb		KLD_UNLOCK();
65991040Sarr		linker_file_sysuninit(file);
66091040Sarr		linker_file_unregister_sysctls(file);
661188209Sjhb		KLD_LOCK();
66225537Sdfr	}
66391040Sarr	TAILQ_REMOVE(&linker_files, file, link);
66425537Sdfr
66591040Sarr	if (file->deps) {
66691040Sarr		for (i = 0; i < file->ndeps; i++)
667132117Sphk			linker_file_unload(file->deps[i], flags);
66891040Sarr		free(file->deps, M_LINKER);
66991040Sarr		file->deps = NULL;
67059751Speter	}
671160245Sjhb	while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
672160245Sjhb		STAILQ_REMOVE_HEAD(&file->common, link);
67391040Sarr		free(cp, M_LINKER);
67491040Sarr	}
67559751Speter
67691040Sarr	LINKER_UNLOAD(file);
67791040Sarr	if (file->filename) {
67891040Sarr		free(file->filename, M_LINKER);
67991040Sarr		file->filename = NULL;
68091040Sarr	}
681172862Sjb	if (file->pathname) {
682172862Sjb		free(file->pathname, M_LINKER);
683172862Sjb		file->pathname = NULL;
684172862Sjb	}
68591040Sarr	kobj_delete((kobj_t) file, M_LINKER);
686159584Sjhb	return (0);
68725537Sdfr}
68825537Sdfr
689179238Sjbint
690179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc)
691179238Sjb{
692179238Sjb	return (LINKER_CTF_GET(file, lc));
693179238Sjb}
694179238Sjb
695159796Sjhbstatic int
69686469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
69725537Sdfr{
69891040Sarr	linker_file_t *newdeps;
69925537Sdfr
700159845Sjhb	KLD_LOCK_ASSERT();
70191040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
702111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
70391040Sarr	if (newdeps == NULL)
70491040Sarr		return (ENOMEM);
70525537Sdfr
70691040Sarr	if (file->deps) {
70791040Sarr		bcopy(file->deps, newdeps,
70891040Sarr		    file->ndeps * sizeof(linker_file_t *));
70991040Sarr		free(file->deps, M_LINKER);
71091040Sarr	}
71191040Sarr	file->deps = newdeps;
71291040Sarr	file->deps[file->ndeps] = dep;
71391040Sarr	file->ndeps++;
714199457Sgonzo	KLD_DPF(FILE, ("linker_file_add_dependency:"
715199457Sgonzo	    " adding %s as dependency for %s\n",
716199457Sgonzo	    dep->filename, file->filename));
71791040Sarr	return (0);
71825537Sdfr}
71925537Sdfr
72078161Speter/*
72191040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
722159841Sjhb * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
723159841Sjhb * This function is used in this file so we can avoid having lots of (void **)
724159841Sjhb * casts.
72578161Speter */
72678161Speterint
72778161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
72891040Sarr    void *firstp, void *lastp, int *countp)
72978161Speter{
730159845Sjhb	int error, locked;
73178161Speter
732159845Sjhb	locked = KLD_LOCKED();
733159845Sjhb	if (!locked)
734159845Sjhb		KLD_LOCK();
735159845Sjhb	error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
736159845Sjhb	if (!locked)
737159845Sjhb		KLD_UNLOCK();
738159845Sjhb	return (error);
73978161Speter}
74078161Speter
741173714Sjb/*
742173714Sjb * List all functions in a file.
743173714Sjb */
744173714Sjbint
745173714Sjblinker_file_function_listall(linker_file_t lf,
746179238Sjb    linker_function_nameval_callback_t callback_func, void *arg)
747173714Sjb{
748173714Sjb	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
749173714Sjb}
750173714Sjb
75125537Sdfrcaddr_t
75291040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
75325537Sdfr{
754159845Sjhb	caddr_t sym;
755159845Sjhb	int locked;
756159845Sjhb
757159845Sjhb	locked = KLD_LOCKED();
758159845Sjhb	if (!locked)
759159845Sjhb		KLD_LOCK();
760159845Sjhb	sym = linker_file_lookup_symbol_internal(file, name, deps);
761159845Sjhb	if (!locked)
762159845Sjhb		KLD_UNLOCK();
763159845Sjhb	return (sym);
764159845Sjhb}
765159845Sjhb
766159845Sjhbstatic caddr_t
767159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name,
768159845Sjhb    int deps)
769159845Sjhb{
77091040Sarr	c_linker_sym_t sym;
77191040Sarr	linker_symval_t symval;
77291040Sarr	caddr_t address;
77391040Sarr	size_t common_size = 0;
77492032Sdwmalone	int i;
77525537Sdfr
776159845Sjhb	KLD_LOCK_ASSERT();
777109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
77891040Sarr	    file, name, deps));
77925537Sdfr
78091040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
78191040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
78291040Sarr		if (symval.value == 0)
78391040Sarr			/*
78491040Sarr			 * For commons, first look them up in the
78591040Sarr			 * dependencies and only allocate space if not found
78691040Sarr			 * there.
78791040Sarr			 */
78891040Sarr			common_size = symval.size;
78991040Sarr		else {
79091040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
791109605Sjake			    ".value=%p\n", symval.value));
79291040Sarr			return (symval.value);
79391040Sarr		}
79440159Speter	}
79591040Sarr	if (deps) {
79691040Sarr		for (i = 0; i < file->ndeps; i++) {
797159845Sjhb			address = linker_file_lookup_symbol_internal(
798159845Sjhb			    file->deps[i], name, 0);
79991040Sarr			if (address) {
80091040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
801109605Sjake				    " deps value=%p\n", address));
80291040Sarr				return (address);
80391040Sarr			}
80491040Sarr		}
80525537Sdfr	}
80691040Sarr	if (common_size > 0) {
80791040Sarr		/*
80891040Sarr		 * This is a common symbol which was not found in the
80991040Sarr		 * dependencies.  We maintain a simple common symbol table in
81091040Sarr		 * the file object.
81191040Sarr		 */
81291040Sarr		struct common_symbol *cp;
81342849Speter
81491040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
81592032Sdwmalone			if (strcmp(cp->name, name) == 0) {
81691040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
817109605Sjake				    " old common value=%p\n", cp->address));
81891040Sarr				return (cp->address);
81991040Sarr			}
82091040Sarr		}
82191040Sarr		/*
82291040Sarr		 * Round the symbol size up to align.
82391040Sarr		 */
82491040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
82591040Sarr		cp = malloc(sizeof(struct common_symbol)
82691040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
827111119Simp		    M_WAITOK | M_ZERO);
82891040Sarr		cp->address = (caddr_t)(cp + 1);
82991040Sarr		cp->name = cp->address + common_size;
83091040Sarr		strcpy(cp->name, name);
83191040Sarr		bzero(cp->address, common_size);
83291040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
83325537Sdfr
83491040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
835109605Sjake		    " value=%p\n", cp->address));
83691040Sarr		return (cp->address);
83740159Speter	}
83891040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
83991040Sarr	return (0);
84025537Sdfr}
84125537Sdfr
84225537Sdfr/*
843174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and
844174132Srwatson * backward lookup of symbols.  However, DDB and sometimes stack(9) need to
845174132Srwatson * do this in a lockfree manner.  We provide a set of internal helper
846174132Srwatson * routines to perform these operations without locks, and then wrappers that
847174132Srwatson * optionally lock.
848159840Sjhb *
849174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
85040159Speter */
851174132Srwatson#ifdef DDB
852174132Srwatsonstatic int
853174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
85440159Speter{
85591040Sarr	linker_file_t lf;
85640159Speter
85791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
85891040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
85991040Sarr			return (0);
86091040Sarr	}
86191040Sarr	return (ENOENT);
86240159Speter}
863174132Srwatson#endif
86440159Speter
865174132Srwatsonstatic int
866174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
86740159Speter{
86891040Sarr	linker_file_t lf;
86991040Sarr	c_linker_sym_t best, es;
87091040Sarr	u_long diff, bestdiff, off;
87140159Speter
87291040Sarr	best = 0;
87391040Sarr	off = (uintptr_t)value;
87491040Sarr	bestdiff = off;
87591040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
87691040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
87791040Sarr			continue;
87891040Sarr		if (es != 0 && diff < bestdiff) {
87991040Sarr			best = es;
88091040Sarr			bestdiff = diff;
88191040Sarr		}
88291040Sarr		if (bestdiff == 0)
88391040Sarr			break;
88440159Speter	}
88591040Sarr	if (best) {
88691040Sarr		*sym = best;
88791040Sarr		*diffp = bestdiff;
88891040Sarr		return (0);
88991040Sarr	} else {
89091040Sarr		*sym = 0;
89191040Sarr		*diffp = off;
89291040Sarr		return (ENOENT);
89391040Sarr	}
89440159Speter}
89540159Speter
896174132Srwatsonstatic int
897174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
89840159Speter{
89991040Sarr	linker_file_t lf;
90040159Speter
90191040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
90291040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
90391040Sarr			return (0);
90491040Sarr	}
90591040Sarr	return (ENOENT);
90640159Speter}
907174132Srwatson
908174132Srwatsonstatic int
909174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
910174132Srwatson    long *offset)
911174132Srwatson{
912174132Srwatson	linker_symval_t symval;
913174132Srwatson	c_linker_sym_t sym;
914174132Srwatson	int error;
915174132Srwatson
916174132Srwatson	*offset = 0;
917174132Srwatson	error = linker_debug_search_symbol(value, &sym, offset);
918174132Srwatson	if (error)
919174132Srwatson		return (error);
920174132Srwatson	error = linker_debug_symbol_values(sym, &symval);
921174132Srwatson	if (error)
922174132Srwatson		return (error);
923174132Srwatson	strlcpy(buf, symval.name, buflen);
924174132Srwatson	return (0);
925174132Srwatson}
926174132Srwatson
927174132Srwatson#ifdef DDB
928174132Srwatson/*
929174132Srwatson * DDB Helpers.  DDB has to look across multiple files with their own symbol
930174132Srwatson * tables and string tables.
931174132Srwatson *
932174132Srwatson * Note that we do not obey list locking protocols here.  We really don't need
933174132Srwatson * DDB to hang because somebody's got the lock held.  We'll take the chance
934174132Srwatson * that the files list is inconsistant instead.
935174132Srwatson */
936174132Srwatsonint
937174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
938174132Srwatson{
939174132Srwatson
940174132Srwatson	return (linker_debug_lookup(symstr, sym));
941174132Srwatson}
942174132Srwatson
943174132Srwatsonint
944174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
945174132Srwatson{
946174132Srwatson
947174132Srwatson	return (linker_debug_search_symbol(value, sym, diffp));
948174132Srwatson}
949174132Srwatson
950174132Srwatsonint
951174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
952174132Srwatson{
953174132Srwatson
954174132Srwatson	return (linker_debug_symbol_values(sym, symval));
955174132Srwatson}
956174132Srwatson
957174132Srwatsonint
958174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
959174132Srwatson    long *offset)
960174132Srwatson{
961174132Srwatson
962174132Srwatson	return (linker_debug_search_symbol_name(value, buf, buflen, offset));
963174132Srwatson}
96440159Speter#endif
96540159Speter
96640159Speter/*
967174132Srwatson * stack(9) helper for non-debugging environemnts.  Unlike DDB helpers, we do
968174132Srwatson * obey locking protocols, and offer a significantly less complex interface.
969174132Srwatson */
970174132Srwatsonint
971174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
972174132Srwatson    long *offset)
973174132Srwatson{
974178380Spjd	int error;
975174132Srwatson
976178380Spjd	KLD_LOCK();
977174132Srwatson	error = linker_debug_search_symbol_name(value, buf, buflen, offset);
978178380Spjd	KLD_UNLOCK();
979174132Srwatson	return (error);
980174132Srwatson}
981174132Srwatson
982174132Srwatson/*
98325537Sdfr * Syscalls.
98425537Sdfr */
98525537Sdfrint
986159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
98725537Sdfr{
988157144Sjkoshy#ifdef HWPMC_HOOKS
989157144Sjkoshy	struct pmckern_map_in pkm;
990157144Sjkoshy#endif
991159588Sjhb	const char *kldname, *modname;
99291040Sarr	linker_file_t lf;
993159588Sjhb	int error;
99425537Sdfr
99593159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
996159588Sjhb		return (error);
99793159Sarr
998164033Srwatson	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
999159588Sjhb		return (error);
100025537Sdfr
100191040Sarr	/*
1002191917Szec	 * It is possible that kldloaded module will attach a new ifnet,
1003191816Szec	 * so vnet context must be set when this ocurs.
1004191816Szec	 */
1005191816Szec	CURVNET_SET(TD_TO_VNET(td));
1006191816Szec
1007191816Szec	/*
1008159841Sjhb	 * If file does not contain a qualified name or any dot in it
1009159841Sjhb	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
101091040Sarr	 * name.
101191040Sarr	 */
1012159588Sjhb	if (index(file, '/') || index(file, '.')) {
1013159588Sjhb		kldname = file;
101491040Sarr		modname = NULL;
101591040Sarr	} else {
101691040Sarr		kldname = NULL;
1017159588Sjhb		modname = file;
101891040Sarr	}
1019159588Sjhb
1020159845Sjhb	KLD_LOCK();
102191040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
102291040Sarr	if (error)
1023159588Sjhb		goto unlock;
1024157144Sjkoshy#ifdef HWPMC_HOOKS
1025157144Sjkoshy	pkm.pm_file = lf->filename;
1026157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
1027157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
1028157144Sjkoshy#endif
102991040Sarr	lf->userrefs++;
1030159588Sjhb	if (fileid != NULL)
1031159588Sjhb		*fileid = lf->id;
1032159588Sjhbunlock:
1033159845Sjhb	KLD_UNLOCK();
1034191816Szec	CURVNET_RESTORE();
103591040Sarr	return (error);
103625537Sdfr}
103725537Sdfr
1038159588Sjhbint
1039159588Sjhbkldload(struct thread *td, struct kldload_args *uap)
1040159588Sjhb{
1041159588Sjhb	char *pathname = NULL;
1042159596Smarcel	int error, fileid;
1043159588Sjhb
1044159588Sjhb	td->td_retval[0] = -1;
1045159588Sjhb
1046159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1047159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1048159596Smarcel	if (error == 0) {
1049159596Smarcel		error = kern_kldload(td, pathname, &fileid);
1050159596Smarcel		if (error == 0)
1051159596Smarcel			td->td_retval[0] = fileid;
1052159596Smarcel	}
1053159588Sjhb	free(pathname, M_TEMP);
1054159588Sjhb	return (error);
1055159588Sjhb}
1056159588Sjhb
1057159588Sjhbint
1058132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
105925537Sdfr{
1060157144Sjkoshy#ifdef HWPMC_HOOKS
1061157144Sjkoshy	struct pmckern_map_out pkm;
1062157144Sjkoshy#endif
106391040Sarr	linker_file_t lf;
106491040Sarr	int error = 0;
106525537Sdfr
106693159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1067159588Sjhb		return (error);
106893159Sarr
1069164033Srwatson	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1070159588Sjhb		return (error);
107125537Sdfr
1072191816Szec	CURVNET_SET(TD_TO_VNET(td));
1073159845Sjhb	KLD_LOCK();
1074132117Sphk	lf = linker_find_file_by_id(fileid);
107591040Sarr	if (lf) {
107691040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
1077172862Sjb
1078172862Sjb		/* Check if there are DTrace probes enabled on this file. */
1079172862Sjb		if (lf->nenabled > 0) {
1080172862Sjb			printf("kldunload: attempt to unload file that has"
1081172862Sjb			    " DTrace probes enabled\n");
1082172862Sjb			error = EBUSY;
1083172862Sjb		} else if (lf->userrefs == 0) {
1084132117Sphk			/*
1085132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
1086132117Sphk			 */
108791040Sarr			printf("kldunload: attempt to unload file that was"
108891040Sarr			    " loaded by the kernel\n");
1089159840Sjhb			error = EBUSY;
1090159588Sjhb		} else {
1091157144Sjkoshy#ifdef HWPMC_HOOKS
1092159588Sjhb			/* Save data needed by hwpmc(4) before unloading. */
1093159588Sjhb			pkm.pm_address = (uintptr_t) lf->address;
1094159588Sjhb			pkm.pm_size = lf->size;
1095157144Sjkoshy#endif
1096159588Sjhb			lf->userrefs--;
1097159588Sjhb			error = linker_file_unload(lf, flags);
1098159588Sjhb			if (error)
1099159588Sjhb				lf->userrefs++;
1100159588Sjhb		}
110191040Sarr	} else
110291040Sarr		error = ENOENT;
1103157144Sjkoshy
1104157144Sjkoshy#ifdef HWPMC_HOOKS
1105157144Sjkoshy	if (error == 0)
1106157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
1107157144Sjkoshy#endif
1108159845Sjhb	KLD_UNLOCK();
1109191816Szec	CURVNET_RESTORE();
111091068Sarr	return (error);
111125537Sdfr}
111225537Sdfr
111325537Sdfrint
1114132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
1115132117Sphk{
1116132117Sphk
1117132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
1118132117Sphk}
1119132117Sphk
1120132117Sphkint
1121132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
1122132117Sphk{
1123132117Sphk
1124132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
1125132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
1126132117Sphk		return (EINVAL);
1127132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
1128132117Sphk}
1129132117Sphk
1130132117Sphkint
113191040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
113225537Sdfr{
113391040Sarr	char *pathname;
113491040Sarr	const char *filename;
113591040Sarr	linker_file_t lf;
1136159791Sjhb	int error;
113725537Sdfr
1138107089Srwatson#ifdef MAC
1139172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1140107089Srwatson	if (error)
1141107089Srwatson		return (error);
1142107089Srwatson#endif
1143107089Srwatson
114491040Sarr	td->td_retval[0] = -1;
114582749Sdillon
1146111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1147107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
114891040Sarr		goto out;
114925537Sdfr
115091040Sarr	filename = linker_basename(pathname);
1151159845Sjhb	KLD_LOCK();
115291040Sarr	lf = linker_find_file_by_name(filename);
115391040Sarr	if (lf)
115491040Sarr		td->td_retval[0] = lf->id;
115591040Sarr	else
115691040Sarr		error = ENOENT;
1157159845Sjhb	KLD_UNLOCK();
115825537Sdfrout:
1159159791Sjhb	free(pathname, M_TEMP);
116091040Sarr	return (error);
116125537Sdfr}
116225537Sdfr
116325537Sdfrint
116491040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
116525537Sdfr{
116691040Sarr	linker_file_t lf;
116791040Sarr	int error = 0;
116825537Sdfr
1169107089Srwatson#ifdef MAC
1170172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1171107089Srwatson	if (error)
1172107089Srwatson		return (error);
1173107089Srwatson#endif
1174107089Srwatson
1175159845Sjhb	KLD_LOCK();
1176166921Sjhb	if (uap->fileid == 0)
1177166921Sjhb		lf = TAILQ_FIRST(&linker_files);
1178166921Sjhb	else {
1179166921Sjhb		lf = linker_find_file_by_id(uap->fileid);
1180166921Sjhb		if (lf == NULL) {
1181166921Sjhb			error = ENOENT;
1182166921Sjhb			goto out;
1183166921Sjhb		}
1184166921Sjhb		lf = TAILQ_NEXT(lf, link);
118591040Sarr	}
1186166921Sjhb
1187166921Sjhb	/* Skip partially loaded files. */
1188166921Sjhb	while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1189166921Sjhb		lf = TAILQ_NEXT(lf, link);
1190166921Sjhb
1191166921Sjhb	if (lf)
1192166921Sjhb		td->td_retval[0] = lf->id;
1193166921Sjhb	else
1194166921Sjhb		td->td_retval[0] = 0;
119582749Sdillonout:
1196159845Sjhb	KLD_UNLOCK();
119791040Sarr	return (error);
119825537Sdfr}
119925537Sdfr
120025537Sdfrint
120191040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
120225537Sdfr{
1203159587Sjhb	struct kld_file_stat stat;
120491040Sarr	linker_file_t lf;
1205172862Sjb	int error, namelen, version, version_num;
120625537Sdfr
1207159587Sjhb	/*
1208159587Sjhb	 * Check the version of the user's structure.
1209159587Sjhb	 */
1210172862Sjb	if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
1211159587Sjhb		return (error);
1212172862Sjb	if (version == sizeof(struct kld_file_stat_1))
1213172862Sjb		version_num = 1;
1214172862Sjb	else if (version == sizeof(struct kld_file_stat))
1215172862Sjb		version_num = 2;
1216172862Sjb	else
1217159587Sjhb		return (EINVAL);
1218159587Sjhb
1219107089Srwatson#ifdef MAC
1220172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1221107089Srwatson	if (error)
1222107089Srwatson		return (error);
1223107089Srwatson#endif
1224107089Srwatson
1225159845Sjhb	KLD_LOCK();
1226107849Salfred	lf = linker_find_file_by_id(uap->fileid);
122791040Sarr	if (lf == NULL) {
1228159845Sjhb		KLD_UNLOCK();
1229159587Sjhb		return (ENOENT);
123091040Sarr	}
123125537Sdfr
1232172862Sjb	/* Version 1 fields: */
123391040Sarr	namelen = strlen(lf->filename) + 1;
123491040Sarr	if (namelen > MAXPATHLEN)
123591040Sarr		namelen = MAXPATHLEN;
1236159587Sjhb	bcopy(lf->filename, &stat.name[0], namelen);
1237159587Sjhb	stat.refs = lf->refs;
1238159587Sjhb	stat.id = lf->id;
1239159587Sjhb	stat.address = lf->address;
1240159587Sjhb	stat.size = lf->size;
1241172862Sjb	if (version_num > 1) {
1242172862Sjb		/* Version 2 fields: */
1243172862Sjb		namelen = strlen(lf->pathname) + 1;
1244172862Sjb		if (namelen > MAXPATHLEN)
1245172862Sjb			namelen = MAXPATHLEN;
1246172862Sjb		bcopy(lf->pathname, &stat.pathname[0], namelen);
1247172862Sjb	}
1248159845Sjhb	KLD_UNLOCK();
124925537Sdfr
125091040Sarr	td->td_retval[0] = 0;
1251159587Sjhb
1252172862Sjb	return (copyout(&stat, uap->stat, version));
125325537Sdfr}
125425537Sdfr
125525537Sdfrint
125691040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
125725537Sdfr{
125891040Sarr	linker_file_t lf;
125991040Sarr	module_t mp;
126091040Sarr	int error = 0;
126125537Sdfr
1262107089Srwatson#ifdef MAC
1263172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1264107089Srwatson	if (error)
1265107089Srwatson		return (error);
1266107089Srwatson#endif
1267107089Srwatson
1268159845Sjhb	KLD_LOCK();
1269107849Salfred	lf = linker_find_file_by_id(uap->fileid);
127091040Sarr	if (lf) {
127192547Sarr		MOD_SLOCK;
127291040Sarr		mp = TAILQ_FIRST(&lf->modules);
127391040Sarr		if (mp != NULL)
127491040Sarr			td->td_retval[0] = module_getid(mp);
127591040Sarr		else
127691040Sarr			td->td_retval[0] = 0;
127792547Sarr		MOD_SUNLOCK;
127891040Sarr	} else
127991040Sarr		error = ENOENT;
1280159845Sjhb	KLD_UNLOCK();
128191040Sarr	return (error);
128225537Sdfr}
128340159Speter
128441090Speterint
128583366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
128641090Speter{
128791040Sarr	char *symstr = NULL;
128891040Sarr	c_linker_sym_t sym;
128991040Sarr	linker_symval_t symval;
129091040Sarr	linker_file_t lf;
129191040Sarr	struct kld_sym_lookup lookup;
129291040Sarr	int error = 0;
129341090Speter
1294107089Srwatson#ifdef MAC
1295172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1296107089Srwatson	if (error)
1297107089Srwatson		return (error);
1298107089Srwatson#endif
1299107089Srwatson
1300107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1301159843Sjhb		return (error);
130291068Sarr	if (lookup.version != sizeof(lookup) ||
1303159843Sjhb	    uap->cmd != KLDSYM_LOOKUP)
1304159843Sjhb		return (EINVAL);
1305111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
130691040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
130791040Sarr		goto out;
1308159845Sjhb	KLD_LOCK();
1309107849Salfred	if (uap->fileid != 0) {
1310107849Salfred		lf = linker_find_file_by_id(uap->fileid);
1311159843Sjhb		if (lf == NULL)
131291040Sarr			error = ENOENT;
1313159843Sjhb		else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
131491040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
131591040Sarr			lookup.symvalue = (uintptr_t) symval.value;
131691040Sarr			lookup.symsize = symval.size;
1317107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
131891040Sarr		} else
131991040Sarr			error = ENOENT;
132091040Sarr	} else {
132191040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
132291040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
132391040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
132491040Sarr				lookup.symvalue = (uintptr_t)symval.value;
132591040Sarr				lookup.symsize = symval.size;
1326107849Salfred				error = copyout(&lookup, uap->data,
132791040Sarr				    sizeof(lookup));
132891068Sarr				break;
132991040Sarr			}
133091040Sarr		}
133191040Sarr		if (lf == NULL)
133291040Sarr			error = ENOENT;
133341090Speter	}
1334159845Sjhb	KLD_UNLOCK();
133541090Speterout:
1336159843Sjhb	free(symstr, M_TEMP);
133791040Sarr	return (error);
133841090Speter}
133941090Speter
134040159Speter/*
134140159Speter * Preloaded module support
134240159Speter */
134340159Speter
134459751Speterstatic modlist_t
134574642Sbpmodlist_lookup(const char *name, int ver)
134659751Speter{
134791040Sarr	modlist_t mod;
134859751Speter
134991040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
135092032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
135192032Sdwmalone		    (ver == 0 || mod->version == ver))
135291040Sarr			return (mod);
135391040Sarr	}
135491040Sarr	return (NULL);
135559751Speter}
135659751Speter
135774642Sbpstatic modlist_t
135883321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
135983321Speter{
136091040Sarr	modlist_t mod, bestmod;
136192032Sdwmalone	int ver;
136283321Speter
136391040Sarr	if (verinfo == NULL)
136491040Sarr		return (modlist_lookup(name, 0));
136591040Sarr	bestmod = NULL;
1366159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
136792032Sdwmalone		if (strcmp(mod->name, name) != 0)
136891040Sarr			continue;
136991040Sarr		ver = mod->version;
137091040Sarr		if (ver == verinfo->md_ver_preferred)
137191040Sarr			return (mod);
137291040Sarr		if (ver >= verinfo->md_ver_minimum &&
137391068Sarr		    ver <= verinfo->md_ver_maximum &&
1374120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
137591040Sarr			bestmod = mod;
137691040Sarr	}
137791040Sarr	return (bestmod);
137883321Speter}
137983321Speter
138083321Speterstatic modlist_t
138178501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
138274642Sbp{
138391040Sarr	modlist_t mod;
138474642Sbp
138592705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
138691040Sarr	if (mod == NULL)
138791040Sarr		panic("no memory for module list");
138891040Sarr	mod->container = container;
138991040Sarr	mod->name = modname;
139091040Sarr	mod->version = version;
139191040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
139291040Sarr	return (mod);
139374642Sbp}
139474642Sbp
139540159Speterstatic void
139678161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
139791040Sarr    struct mod_metadata **stop, int preload)
139874642Sbp{
139991040Sarr	struct mod_metadata *mp, **mdp;
140091040Sarr	const char *modname;
140191040Sarr	int ver;
140274642Sbp
140391040Sarr	for (mdp = start; mdp < stop; mdp++) {
1404109605Sjake		mp = *mdp;
140591040Sarr		if (mp->md_type != MDT_VERSION)
140691040Sarr			continue;
1407109605Sjake		modname = mp->md_cval;
1408109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
140991040Sarr		if (modlist_lookup(modname, ver) != NULL) {
141091040Sarr			printf("module %s already present!\n", modname);
141191040Sarr			/* XXX what can we do? this is a build error. :-( */
141291040Sarr			continue;
141391040Sarr		}
141491040Sarr		modlist_newmodule(modname, ver, lf);
141574642Sbp	}
141674642Sbp}
141774642Sbp
141874642Sbpstatic void
141991040Sarrlinker_preload(void *arg)
142040159Speter{
142191040Sarr	caddr_t modptr;
142291040Sarr	const char *modname, *nmodname;
142391040Sarr	char *modtype;
1424160244Sjhb	linker_file_t lf, nlf;
142591040Sarr	linker_class_t lc;
142692032Sdwmalone	int error;
142791040Sarr	linker_file_list_t loaded_files;
142891040Sarr	linker_file_list_t depended_files;
142991040Sarr	struct mod_metadata *mp, *nmp;
143091040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
143191040Sarr	struct mod_depend *verinfo;
143291040Sarr	int nver;
143391040Sarr	int resolves;
143491040Sarr	modlist_t mod;
143591040Sarr	struct sysinit **si_start, **si_stop;
143640159Speter
143791040Sarr	TAILQ_INIT(&loaded_files);
143891040Sarr	TAILQ_INIT(&depended_files);
143991040Sarr	TAILQ_INIT(&found_modules);
144091040Sarr	error = 0;
144159751Speter
144291040Sarr	modptr = NULL;
144391040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
144491040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
144591040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
144691040Sarr		if (modname == NULL) {
144791040Sarr			printf("Preloaded module at %p does not have a"
144891040Sarr			    " name!\n", modptr);
144991040Sarr			continue;
145091040Sarr		}
145191040Sarr		if (modtype == NULL) {
145291040Sarr			printf("Preloaded module at %p does not have a type!\n",
145391040Sarr			    modptr);
145491040Sarr			continue;
145591040Sarr		}
1456131398Sjhb		if (bootverbose)
1457131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1458131398Sjhb			    modptr);
145940159Speter		lf = NULL;
146091040Sarr		TAILQ_FOREACH(lc, &classes, link) {
146191040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1462134364Siedowse			if (!error)
146391040Sarr				break;
1464134364Siedowse			lf = NULL;
146591040Sarr		}
146691040Sarr		if (lf)
146791040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
146840159Speter	}
146940159Speter
147091040Sarr	/*
147191040Sarr	 * First get a list of stuff in the kernel.
147291040Sarr	 */
147391040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
147491040Sarr	    &stop, NULL) == 0)
147591040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
147659751Speter
147759751Speter	/*
1478167019Sjhb	 * This is a once-off kinky bubble sort to resolve relocation
1479167019Sjhb	 * dependency requirements.
148059751Speter	 */
148191040Sarrrestart:
148291040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
148391040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
148491040Sarr		    &stop, NULL);
148591040Sarr		/*
148691040Sarr		 * First, look to see if we would successfully link with this
148791040Sarr		 * stuff.
148891040Sarr		 */
148991040Sarr		resolves = 1;	/* unless we know otherwise */
149091040Sarr		if (!error) {
149191040Sarr			for (mdp = start; mdp < stop; mdp++) {
1492109605Sjake				mp = *mdp;
149391040Sarr				if (mp->md_type != MDT_DEPEND)
149491040Sarr					continue;
1495109605Sjake				modname = mp->md_cval;
1496109605Sjake				verinfo = mp->md_data;
149791040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1498109605Sjake					nmp = *nmdp;
149991040Sarr					if (nmp->md_type != MDT_VERSION)
150091040Sarr						continue;
1501109605Sjake					nmodname = nmp->md_cval;
150292032Sdwmalone					if (strcmp(modname, nmodname) == 0)
150391040Sarr						break;
150491040Sarr				}
150591040Sarr				if (nmdp < stop)   /* it's a self reference */
150691040Sarr					continue;
1507159840Sjhb
150891040Sarr				/*
150991040Sarr				 * ok, the module isn't here yet, we
151091040Sarr				 * are not finished
151191040Sarr				 */
151291068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
151391040Sarr					resolves = 0;
151491040Sarr			}
151564143Speter		}
151691040Sarr		/*
151791040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
151891040Sarr		 * the modules inside and add it to the end of the link order
151991040Sarr		 * list.
152091040Sarr		 */
152191040Sarr		if (resolves) {
152291040Sarr			if (!error) {
152391040Sarr				for (mdp = start; mdp < stop; mdp++) {
1524109605Sjake					mp = *mdp;
152591040Sarr					if (mp->md_type != MDT_VERSION)
152691040Sarr						continue;
1527109605Sjake					modname = mp->md_cval;
1528109605Sjake					nver = ((struct mod_version *)
1529109605Sjake					    mp->md_data)->mv_version;
153091040Sarr					if (modlist_lookup(modname,
153191040Sarr					    nver) != NULL) {
153291040Sarr						printf("module %s already"
153391040Sarr						    " present!\n", modname);
1534160244Sjhb						TAILQ_REMOVE(&loaded_files,
1535160244Sjhb						    lf, loaded);
1536132117Sphk						linker_file_unload(lf,
1537132117Sphk						    LINKER_UNLOAD_FORCE);
153891040Sarr						/* we changed tailq next ptr */
153991068Sarr						goto restart;
154091040Sarr					}
154191040Sarr					modlist_newmodule(modname, nver, lf);
154291040Sarr				}
154391040Sarr			}
154491040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
154591040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
154691040Sarr			/*
154791040Sarr			 * Since we provided modules, we need to restart the
154891040Sarr			 * sort so that the previous files that depend on us
154991040Sarr			 * have a chance. Also, we've busted the tailq next
155091040Sarr			 * pointer with the REMOVE.
155191040Sarr			 */
155291040Sarr			goto restart;
155359751Speter		}
155459751Speter	}
155591040Sarr
155659751Speter	/*
155791040Sarr	 * At this point, we check to see what could not be resolved..
155859751Speter	 */
1559160242Sjhb	while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1560160242Sjhb		TAILQ_REMOVE(&loaded_files, lf, loaded);
156191040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1562132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
156340159Speter	}
156459751Speter
156578161Speter	/*
156691040Sarr	 * We made it. Finish off the linking in the order we determined.
156778161Speter	 */
1568160244Sjhb	TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
156991040Sarr		if (linker_kernel_file) {
157091040Sarr			linker_kernel_file->refs++;
157191040Sarr			error = linker_file_add_dependency(lf,
157291040Sarr			    linker_kernel_file);
157391040Sarr			if (error)
157491040Sarr				panic("cannot add dependency");
157591040Sarr		}
157691040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
157791040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
157891040Sarr		    &stop, NULL);
157991040Sarr		if (!error) {
158091040Sarr			for (mdp = start; mdp < stop; mdp++) {
1581109605Sjake				mp = *mdp;
158291040Sarr				if (mp->md_type != MDT_DEPEND)
158391040Sarr					continue;
1584109605Sjake				modname = mp->md_cval;
1585109605Sjake				verinfo = mp->md_data;
158691040Sarr				mod = modlist_lookup2(modname, verinfo);
1587151484Sjdp				/* Don't count self-dependencies */
1588151484Sjdp				if (lf == mod->container)
1589151484Sjdp					continue;
159091040Sarr				mod->container->refs++;
159191040Sarr				error = linker_file_add_dependency(lf,
159291040Sarr				    mod->container);
159391040Sarr				if (error)
159491040Sarr					panic("cannot add dependency");
159591040Sarr			}
159691040Sarr		}
159791040Sarr		/*
159891040Sarr		 * Now do relocation etc using the symbol search paths
159991040Sarr		 * established by the dependencies
160091040Sarr		 */
160191040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
160291040Sarr		if (error) {
1603160244Sjhb			TAILQ_REMOVE(&depended_files, lf, loaded);
160491040Sarr			printf("KLD file %s - could not finalize loading\n",
160591040Sarr			    lf->filename);
1606132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
160791040Sarr			continue;
160891040Sarr		}
160991040Sarr		linker_file_register_modules(lf);
161091040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
161191040Sarr		    &si_stop, NULL) == 0)
161291040Sarr			sysinit_add(si_start, si_stop);
161391040Sarr		linker_file_register_sysctls(lf);
161491040Sarr		lf->flags |= LINKER_FILE_LINKED;
161559751Speter	}
161691040Sarr	/* woohoo! we made it! */
161740159Speter}
161840159Speter
1619177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
162040159Speter
162140159Speter/*
162240159Speter * Search for a not-loaded module by name.
1623159840Sjhb *
162440159Speter * Modules may be found in the following locations:
1625159840Sjhb *
162691040Sarr * - preloaded (result is just the module name) - on disk (result is full path
162791040Sarr * to module)
1628159840Sjhb *
162991040Sarr * If the module name is qualified in any way (contains path, etc.) the we
163091040Sarr * simply return a copy of it.
1631159840Sjhb *
163240159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
163340159Speter * character as a separator to be consistent with the bootloader.
163440159Speter */
163540159Speter
163683321Speterstatic char linker_hintfile[] = "linker.hints";
1637111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
163840159Speter
163940159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
164091040Sarr    sizeof(linker_path), "module load search path");
164140159Speter
164277843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
164370417Speter
164459751Speterstatic char *linker_ext_list[] = {
164583321Speter	"",
164659751Speter	".ko",
164759751Speter	NULL
164859751Speter};
164959751Speter
165083321Speter/*
165191040Sarr * Check if file actually exists either with or without extension listed in
165291040Sarr * the linker_ext_list. (probably should be generic for the rest of the
165391040Sarr * kernel)
165483321Speter */
165559751Speterstatic char *
165691040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
165791040Sarr    int namelen, struct vattr *vap)
165840159Speter{
165991040Sarr	struct nameidata nd;
166091040Sarr	struct thread *td = curthread;	/* XXX */
166191040Sarr	char *result, **cpp, *sep;
1662159808Sjhb	int error, len, extlen, reclen, flags, vfslocked;
166391040Sarr	enum vtype type;
166440159Speter
166591040Sarr	extlen = 0;
166691040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
166791040Sarr		len = strlen(*cpp);
166891040Sarr		if (len > extlen)
166991040Sarr			extlen = len;
167091040Sarr	}
167191040Sarr	extlen++;		/* trailing '\0' */
167291040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
167383321Speter
167491040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1675111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
167691040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
167791040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
167891040Sarr		    namelen, name, *cpp);
167991040Sarr		/*
168091040Sarr		 * Attempt to open the file, and return the path if
168191040Sarr		 * we succeed and it's a regular file.
168291040Sarr		 */
1683159808Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td);
168491040Sarr		flags = FREAD;
1685170152Skib		error = vn_open(&nd, &flags, 0, NULL);
168691040Sarr		if (error == 0) {
1687159808Sjhb			vfslocked = NDHASGIANT(&nd);
168891040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
168991040Sarr			type = nd.ni_vp->v_type;
169091040Sarr			if (vap)
1691182371Sattilio				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1692175294Sattilio			VOP_UNLOCK(nd.ni_vp, 0);
169391406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
1694159808Sjhb			VFS_UNLOCK_GIANT(vfslocked);
169591040Sarr			if (type == VREG)
169691040Sarr				return (result);
169791040Sarr		}
169883321Speter	}
169991040Sarr	free(result, M_LINKER);
170091040Sarr	return (NULL);
170183321Speter}
170283321Speter
170391040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
170483321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
170583321Speter
170683321Speter/*
170791040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
170891040Sarr * version specification is available, then try to find the best KLD.
170983321Speter * Otherwise just find the latest one.
171083321Speter */
171183321Speterstatic char *
171291040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
171391040Sarr    int modnamelen, struct mod_depend *verinfo)
171483321Speter{
171591040Sarr	struct thread *td = curthread;	/* XXX */
171691406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
171791040Sarr	struct nameidata nd;
171891040Sarr	struct vattr vattr, mattr;
171991040Sarr	u_char *hints = NULL;
172091040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
172191040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1722159808Sjhb	int vfslocked = 0;
172383321Speter
172491040Sarr	result = NULL;
172591040Sarr	bestver = found = 0;
172683321Speter
172791040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
172891040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
172991040Sarr	    strlen(sep) + 1;
1730111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
173191040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
173291040Sarr	    linker_hintfile);
173383321Speter
1734159808Sjhb	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td);
173591040Sarr	flags = FREAD;
1736170152Skib	error = vn_open(&nd, &flags, 0, NULL);
173791040Sarr	if (error)
173891040Sarr		goto bad;
1739159808Sjhb	vfslocked = NDHASGIANT(&nd);
174091040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
174191040Sarr	if (nd.ni_vp->v_type != VREG)
174291040Sarr		goto bad;
174391040Sarr	best = cp = NULL;
1744182371Sattilio	error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
174591040Sarr	if (error)
174691040Sarr		goto bad;
174791040Sarr	/*
174891040Sarr	 * XXX: we need to limit this number to some reasonable value
174991040Sarr	 */
175091040Sarr	if (vattr.va_size > 100 * 1024) {
175191040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
175291040Sarr		goto bad;
175391040Sarr	}
1754111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
175591040Sarr	if (hints == NULL)
175691040Sarr		goto bad;
175791068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1758101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
175991040Sarr	if (error)
176091040Sarr		goto bad;
1761175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
176291040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
1763159808Sjhb	VFS_UNLOCK_GIANT(vfslocked);
176491040Sarr	nd.ni_vp = NULL;
176591040Sarr	if (reclen != 0) {
176691040Sarr		printf("can't read %d\n", reclen);
176791040Sarr		goto bad;
176891040Sarr	}
176991040Sarr	intp = (int *)hints;
177083321Speter	ival = *intp++;
177191040Sarr	if (ival != LINKER_HINTS_VERSION) {
177291040Sarr		printf("hints file version mismatch %d\n", ival);
177391040Sarr		goto bad;
177483321Speter	}
177591040Sarr	bufend = hints + vattr.va_size;
177691040Sarr	recptr = (u_char *)intp;
177791040Sarr	clen = blen = 0;
177891040Sarr	while (recptr < bufend && !found) {
177991040Sarr		intp = (int *)recptr;
178091040Sarr		reclen = *intp++;
178191040Sarr		ival = *intp++;
178291040Sarr		cp = (char *)intp;
178391040Sarr		switch (ival) {
178491040Sarr		case MDT_VERSION:
178591040Sarr			clen = *cp++;
178691040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
178791040Sarr				break;
178891040Sarr			cp += clen;
178991040Sarr			INT_ALIGN(hints, cp);
179091040Sarr			ival = *(int *)cp;
179191040Sarr			cp += sizeof(int);
179291040Sarr			clen = *cp++;
179391040Sarr			if (verinfo == NULL ||
179491040Sarr			    ival == verinfo->md_ver_preferred) {
179591040Sarr				found = 1;
179691040Sarr				break;
179791040Sarr			}
179891040Sarr			if (ival >= verinfo->md_ver_minimum &&
179991040Sarr			    ival <= verinfo->md_ver_maximum &&
180091040Sarr			    ival > bestver) {
180191040Sarr				bestver = ival;
180291040Sarr				best = cp;
180391040Sarr				blen = clen;
180491040Sarr			}
180591040Sarr			break;
180691040Sarr		default:
180791040Sarr			break;
180891040Sarr		}
180991040Sarr		recptr += reclen + sizeof(int);
181091040Sarr	}
181183321Speter	/*
181291040Sarr	 * Finally check if KLD is in the place
181383321Speter	 */
181491040Sarr	if (found)
181591040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
181691040Sarr	else if (best)
181791040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
181891040Sarr
181991040Sarr	/*
182091040Sarr	 * KLD is newer than hints file. What we should do now?
182191040Sarr	 */
182291040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
182391040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
182491040Sarr		    " file\n", result);
182583321Speterbad:
1826105167Sphk	free(pathbuf, M_LINKER);
182791040Sarr	if (hints)
182891040Sarr		free(hints, M_TEMP);
182999553Sjeff	if (nd.ni_vp != NULL) {
1830175294Sattilio		VOP_UNLOCK(nd.ni_vp, 0);
183191040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
1832159808Sjhb		VFS_UNLOCK_GIANT(vfslocked);
183399553Sjeff	}
183491040Sarr	/*
183591040Sarr	 * If nothing found or hints is absent - fallback to the old
183691040Sarr	 * way by using "kldname[.ko]" as module name.
183791040Sarr	 */
183891040Sarr	if (!found && !bestver && result == NULL)
183991040Sarr		result = linker_lookup_file(path, pathlen, modname,
184091040Sarr		    modnamelen, NULL);
184191040Sarr	return (result);
184283321Speter}
184383321Speter
184483321Speter/*
184583321Speter * Lookup KLD which contains requested module in the all directories.
184683321Speter */
184783321Speterstatic char *
184883321Speterlinker_search_module(const char *modname, int modnamelen,
184991040Sarr    struct mod_depend *verinfo)
185083321Speter{
185191040Sarr	char *cp, *ep, *result;
185283321Speter
185391040Sarr	/*
185491040Sarr	 * traverse the linker path
185591040Sarr	 */
185691040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
185791040Sarr		/* find the end of this component */
185891040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
185991068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
186091068Sarr		    modnamelen, verinfo);
186191040Sarr		if (result != NULL)
186291040Sarr			return (result);
186391040Sarr		if (*ep == 0)
186491040Sarr			break;
186591040Sarr	}
186691040Sarr	return (NULL);
186783321Speter}
186883321Speter
186983321Speter/*
187083321Speter * Search for module in all directories listed in the linker_path.
187183321Speter */
187283321Speterstatic char *
187383321Speterlinker_search_kld(const char *name)
187483321Speter{
1875158972Sdelphij	char *cp, *ep, *result;
1876158972Sdelphij	int len;
187783321Speter
187891040Sarr	/* qualified at all? */
187991040Sarr	if (index(name, '/'))
188091040Sarr		return (linker_strdup(name));
188140159Speter
188291040Sarr	/* traverse the linker path */
188391040Sarr	len = strlen(name);
188491040Sarr	for (ep = linker_path; *ep; ep++) {
188591040Sarr		cp = ep;
188691040Sarr		/* find the end of this component */
188791040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
188891040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
188991040Sarr		if (result != NULL)
189091040Sarr			return (result);
189191040Sarr	}
189291040Sarr	return (NULL);
189340159Speter}
189459751Speter
189559751Speterstatic const char *
189691040Sarrlinker_basename(const char *path)
189759751Speter{
189891040Sarr	const char *filename;
189959751Speter
190091040Sarr	filename = rindex(path, '/');
190191040Sarr	if (filename == NULL)
190291040Sarr		return path;
190391040Sarr	if (filename[1])
190491040Sarr		filename++;
190591040Sarr	return (filename);
190659751Speter}
190759751Speter
1908157144Sjkoshy#ifdef HWPMC_HOOKS
190959751Speter/*
1910157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1911157144Sjkoshy */
1912157144Sjkoshyvoid *
1913157144Sjkoshylinker_hwpmc_list_objects(void)
1914157144Sjkoshy{
1915195159Sattilio	linker_file_t lf;
1916195159Sattilio	struct pmckern_map_in *kobase;
1917195159Sattilio	int i, nmappings;
1918157144Sjkoshy
1919195159Sattilio	nmappings = 0;
1920195159Sattilio	KLD_LOCK();
1921195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link)
1922195159Sattilio		nmappings++;
1923157144Sjkoshy
1924195159Sattilio	/* Allocate nmappings + 1 entries. */
1925195159Sattilio	kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in),
1926184214Sdes	    M_LINKER, M_WAITOK | M_ZERO);
1927195159Sattilio	i = 0;
1928195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link) {
1929157144Sjkoshy
1930195159Sattilio		/* Save the info for this linker file. */
1931195159Sattilio		kobase[i].pm_file = lf->filename;
1932195159Sattilio		kobase[i].pm_address = (uintptr_t)lf->address;
1933195159Sattilio		i++;
1934157144Sjkoshy	}
1935195159Sattilio	KLD_UNLOCK();
1936157144Sjkoshy
1937195159Sattilio	KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
1938157144Sjkoshy
1939157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1940195159Sattilio	KASSERT(kobase[i].pm_file == NULL,
1941157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1942157144Sjkoshy
1943195159Sattilio	return ((void *)kobase);
1944157144Sjkoshy}
1945157144Sjkoshy#endif
1946157144Sjkoshy
1947157144Sjkoshy/*
194891040Sarr * Find a file which contains given module and load it, if "parent" is not
194991040Sarr * NULL, register a reference to it.
195059751Speter */
1951159796Sjhbstatic int
195283321Speterlinker_load_module(const char *kldname, const char *modname,
195391040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
195491040Sarr    struct linker_file **lfpp)
195559751Speter{
195691040Sarr	linker_file_t lfdep;
195791040Sarr	const char *filename;
195891040Sarr	char *pathname;
195991040Sarr	int error;
196059751Speter
1961159845Sjhb	KLD_LOCK_ASSERT();
196291040Sarr	if (modname == NULL) {
196391040Sarr		/*
196491040Sarr 		 * We have to load KLD
196591040Sarr 		 */
196691068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
196791068Sarr		    " is not NULL"));
196891040Sarr		pathname = linker_search_kld(kldname);
196991040Sarr	} else {
197091040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
197191040Sarr			return (EEXIST);
197294322Sbrian		if (kldname != NULL)
197394322Sbrian			pathname = linker_strdup(kldname);
197495488Sbrian		else if (rootvnode == NULL)
197594322Sbrian			pathname = NULL;
197694322Sbrian		else
197791040Sarr			/*
197891040Sarr			 * Need to find a KLD with required module
197991040Sarr			 */
198091040Sarr			pathname = linker_search_module(modname,
198191040Sarr			    strlen(modname), verinfo);
198291040Sarr	}
198391040Sarr	if (pathname == NULL)
198491040Sarr		return (ENOENT);
198591040Sarr
198683321Speter	/*
198791040Sarr	 * Can't load more than one file with the same basename XXX:
198891040Sarr	 * Actually it should be possible to have multiple KLDs with
198991040Sarr	 * the same basename but different path because they can
199091040Sarr	 * provide different versions of the same modules.
199183321Speter	 */
199291040Sarr	filename = linker_basename(pathname);
1993159792Sjhb	if (linker_find_file_by_name(filename))
199491040Sarr		error = EEXIST;
1995159792Sjhb	else do {
199691040Sarr		error = linker_load_file(pathname, &lfdep);
199791040Sarr		if (error)
199891040Sarr			break;
199991040Sarr		if (modname && verinfo &&
200091040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
2001132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
200291040Sarr			error = ENOENT;
200391040Sarr			break;
200491040Sarr		}
200591040Sarr		if (parent) {
200691040Sarr			error = linker_file_add_dependency(parent, lfdep);
200791040Sarr			if (error)
200891040Sarr				break;
200991040Sarr		}
201091040Sarr		if (lfpp)
201191040Sarr			*lfpp = lfdep;
201291040Sarr	} while (0);
2013159791Sjhb	free(pathname, M_LINKER);
201491040Sarr	return (error);
201559751Speter}
201659751Speter
201759751Speter/*
201891040Sarr * This routine is responsible for finding dependencies of userland initiated
201991040Sarr * kldload(2)'s of files.
202059751Speter */
202159751Speterint
202286469Siedowselinker_load_dependencies(linker_file_t lf)
202359751Speter{
202491040Sarr	linker_file_t lfdep;
202591040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
202691040Sarr	struct mod_metadata *mp, *nmp;
202791040Sarr	struct mod_depend *verinfo;
202891040Sarr	modlist_t mod;
202991040Sarr	const char *modname, *nmodname;
203092032Sdwmalone	int ver, error = 0, count;
203159751Speter
203291040Sarr	/*
203391040Sarr	 * All files are dependant on /kernel.
203491040Sarr	 */
2035159845Sjhb	KLD_LOCK_ASSERT();
203691040Sarr	if (linker_kernel_file) {
203791040Sarr		linker_kernel_file->refs++;
203891040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
203991040Sarr		if (error)
204091040Sarr			return (error);
204159751Speter	}
204291040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
204391040Sarr	    &count) != 0)
204491040Sarr		return (0);
204591040Sarr	for (mdp = start; mdp < stop; mdp++) {
2046109605Sjake		mp = *mdp;
204791040Sarr		if (mp->md_type != MDT_VERSION)
204891040Sarr			continue;
2049109605Sjake		modname = mp->md_cval;
2050109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
205191040Sarr		mod = modlist_lookup(modname, ver);
205291040Sarr		if (mod != NULL) {
205391040Sarr			printf("interface %s.%d already present in the KLD"
205491040Sarr			    " '%s'!\n", modname, ver,
205591040Sarr			    mod->container->filename);
205691040Sarr			return (EEXIST);
205791040Sarr		}
205891040Sarr	}
205974642Sbp
206091040Sarr	for (mdp = start; mdp < stop; mdp++) {
2061109605Sjake		mp = *mdp;
206291040Sarr		if (mp->md_type != MDT_DEPEND)
206391040Sarr			continue;
2064109605Sjake		modname = mp->md_cval;
2065109605Sjake		verinfo = mp->md_data;
206691040Sarr		nmodname = NULL;
206791040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
2068109605Sjake			nmp = *nmdp;
206991040Sarr			if (nmp->md_type != MDT_VERSION)
207091040Sarr				continue;
2071109605Sjake			nmodname = nmp->md_cval;
207292032Sdwmalone			if (strcmp(modname, nmodname) == 0)
207391040Sarr				break;
207491040Sarr		}
207591040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
207691040Sarr			continue;
207791040Sarr		mod = modlist_lookup2(modname, verinfo);
207891040Sarr		if (mod) {	/* woohoo, it's loaded already */
207991040Sarr			lfdep = mod->container;
208091040Sarr			lfdep->refs++;
208191040Sarr			error = linker_file_add_dependency(lf, lfdep);
208291040Sarr			if (error)
208391040Sarr				break;
208491040Sarr			continue;
208591040Sarr		}
208691040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
208791040Sarr		if (error) {
2088195803Srpaulo			printf("KLD %s: depends on %s - not available or"
2089195803Srpaulo			    " version mismatch\n", lf->filename, modname);
209091040Sarr			break;
209191040Sarr		}
209259751Speter	}
209359751Speter
209491040Sarr	if (error)
209591040Sarr		return (error);
209691040Sarr	linker_addmodules(lf, start, stop, 0);
209791040Sarr	return (error);
209859751Speter}
209985736Sgreen
210085736Sgreenstatic int
210185736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
210285736Sgreen{
210385736Sgreen	struct sysctl_req *req;
210485736Sgreen
210585736Sgreen	req = opaque;
210685736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
210785736Sgreen}
210885736Sgreen
210985736Sgreen/*
211085736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
211185736Sgreen * in the kernel.
211285736Sgreen */
211385736Sgreenstatic int
211485736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
211585736Sgreen{
211685736Sgreen	linker_file_t lf;
211785736Sgreen	int error;
211885736Sgreen
2119107089Srwatson#ifdef MAC
2120172930Srwatson	error = mac_kld_check_stat(req->td->td_ucred);
2121107089Srwatson	if (error)
2122107089Srwatson		return (error);
2123107089Srwatson#endif
2124126253Struckman	error = sysctl_wire_old_buffer(req, 0);
2125126253Struckman	if (error != 0)
2126126253Struckman		return (error);
2127159845Sjhb	KLD_LOCK();
212885736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
212985736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
213085736Sgreen		    sysctl_kern_function_list_iterate, req);
213198452Sarr		if (error) {
2132159845Sjhb			KLD_UNLOCK();
213385736Sgreen			return (error);
213498452Sarr		}
213585736Sgreen	}
2136159845Sjhb	KLD_UNLOCK();
213785736Sgreen	return (SYSCTL_OUT(req, "", 1));
213885736Sgreen}
213985736Sgreen
214085736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
214191040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2142