kern_linker.c revision 188232
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 188232 2009-02-06 14:51:32Z jhb $");
29116182Sobrien
3040159Speter#include "opt_ddb.h"
31157144Sjkoshy#include "opt_hwpmc_hooks.h"
32107089Srwatson#include "opt_mac.h"
3340159Speter
3425537Sdfr#include <sys/param.h>
3525537Sdfr#include <sys/kernel.h>
3625537Sdfr#include <sys/systm.h>
3725537Sdfr#include <sys/malloc.h>
3825537Sdfr#include <sys/sysproto.h>
3925537Sdfr#include <sys/sysent.h>
40164033Srwatson#include <sys/priv.h>
4125537Sdfr#include <sys/proc.h>
4225537Sdfr#include <sys/lock.h>
4382749Sdillon#include <sys/mutex.h>
4492547Sarr#include <sys/sx.h>
4525537Sdfr#include <sys/module.h>
46159808Sjhb#include <sys/mount.h>
4725537Sdfr#include <sys/linker.h>
4840159Speter#include <sys/fcntl.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>
54185895Szec#include <sys/vimage.h>
5525537Sdfr
56163606Srwatson#include <security/mac/mac_framework.h>
57163606Srwatson
5859603Sdfr#include "linker_if.h"
5959603Sdfr
60157144Sjkoshy#ifdef HWPMC_HOOKS
61157144Sjkoshy#include <sys/pmckern.h>
62157144Sjkoshy#endif
63157144Sjkoshy
6440961Speter#ifdef KLD_DEBUG
6540961Speterint kld_debug = 0;
6640961Speter#endif
6740961Speter
68160142Sjhb#define	KLD_LOCK()		sx_xlock(&kld_sx)
69160142Sjhb#define	KLD_UNLOCK()		sx_xunlock(&kld_sx)
70159845Sjhb#define	KLD_LOCKED()		sx_xlocked(&kld_sx)
71160142Sjhb#define	KLD_LOCK_ASSERT() do {						\
72160142Sjhb	if (!cold)							\
73160142Sjhb		sx_assert(&kld_sx, SX_XLOCKED);				\
74160142Sjhb} while (0)
75159845Sjhb
7691040Sarr/*
7791040Sarr * static char *linker_search_path(const char *name, struct mod_depend
7891040Sarr * *verinfo);
7991040Sarr */
8091040Sarrstatic const char 	*linker_basename(const char *path);
8159751Speter
82159800Sjhb/*
83159800Sjhb * Find a currently loaded file given its filename.
84159800Sjhb */
85159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
86159800Sjhb
87159800Sjhb/*
88159800Sjhb * Find a currently loaded file given its file id.
89159800Sjhb */
90159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
91159800Sjhb
9278161Speter/* Metadata from the static kernel */
9378161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
9478161Speter
9559751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
9659751Speter
9740906Speterlinker_file_t linker_kernel_file;
9831324Sbde
99159845Sjhbstatic struct sx kld_sx;	/* kernel linker lock */
10098452Sarr
101172862Sjb/*
102172862Sjb * Load counter used by clients to determine if a linker file has been
103172862Sjb * re-loaded. This counter is incremented for each file load.
104172862Sjb */
105172862Sjbstatic int loadcnt;
106172862Sjb
10725537Sdfrstatic linker_class_list_t classes;
10850068Sgrogstatic linker_file_list_t linker_files;
10925537Sdfrstatic int next_file_id = 1;
11098452Sarrstatic int linker_no_more_classes = 0;
11125537Sdfr
11286553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
11391040Sarr	linker_file_t lftmp;						\
11486553Sarr									\
115159845Sjhb	KLD_LOCK_ASSERT();						\
11686553Sarrretry:									\
11791040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
11891040Sarr		if (next_file_id == lftmp->id) {			\
11991040Sarr			next_file_id++;					\
12091040Sarr			goto retry;					\
12191040Sarr		}							\
12291040Sarr	}								\
12391040Sarr	(a) = next_file_id;						\
12486553Sarr} while(0)
12586553Sarr
12686553Sarr
12759751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
12860938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
12959751Speterstruct modlist {
13091040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
13191040Sarr	linker_file_t   container;
13291040Sarr	const char 	*name;
13391040Sarr	int             version;
13459751Speter};
13591040Sarrtypedef struct modlist *modlist_t;
13691040Sarrstatic modlisthead_t found_modules;
13759751Speter
138159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
139159796Sjhb		    linker_file_t dep);
140159845Sjhbstatic caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
141159845Sjhb		    const char* name, int deps);
142159796Sjhbstatic int	linker_load_module(const char *kldname,
143159796Sjhb		    const char *modname, struct linker_file *parent,
144159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
145159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
14694321Sbrian
14759603Sdfrstatic char *
14859603Sdfrlinker_strdup(const char *str)
14959603Sdfr{
15091040Sarr	char *result;
15159603Sdfr
152111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
15391040Sarr		strcpy(result, str);
15491040Sarr	return (result);
15559603Sdfr}
15659603Sdfr
15725537Sdfrstatic void
15891040Sarrlinker_init(void *arg)
15925537Sdfr{
16091040Sarr
161159845Sjhb	sx_init(&kld_sx, "kernel linker");
16291040Sarr	TAILQ_INIT(&classes);
16391040Sarr	TAILQ_INIT(&linker_files);
16425537Sdfr}
16525537Sdfr
166177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
16725537Sdfr
16898452Sarrstatic void
16998452Sarrlinker_stop_class_add(void *arg)
17098452Sarr{
17198452Sarr
17298452Sarr	linker_no_more_classes = 1;
17398452Sarr}
17498452Sarr
175177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL);
17698452Sarr
17725537Sdfrint
17859603Sdfrlinker_add_class(linker_class_t lc)
17925537Sdfr{
18091040Sarr
18198452Sarr	/*
182144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
183144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
184144443Sjhb	 * ops from being freed.
18598452Sarr	 */
18698452Sarr	if (linker_no_more_classes == 1)
18798452Sarr		return (EPERM);
18891040Sarr	kobj_class_compile((kobj_class_t) lc);
189144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
19091040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
19191040Sarr	return (0);
19225537Sdfr}
19325537Sdfr
19425537Sdfrstatic void
19525537Sdfrlinker_file_sysinit(linker_file_t lf)
19625537Sdfr{
19791040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
19825537Sdfr
19991040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
20091040Sarr	    lf->filename));
20125537Sdfr
20291040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
20391040Sarr		return;
20491040Sarr	/*
20591040Sarr	 * Perform a bubble sort of the system initialization objects by
20691040Sarr	 * their subsystem (primary key) and order (secondary key).
207159840Sjhb	 *
20891040Sarr	 * Since some things care about execution order, this is the operation
20991040Sarr	 * which ensures continued function.
21091040Sarr	 */
21191040Sarr	for (sipp = start; sipp < stop; sipp++) {
21291040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
21391040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
21491040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
21591040Sarr			    (*sipp)->order <= (*xipp)->order))
21691040Sarr				continue;	/* skip */
21791040Sarr			save = *sipp;
21891040Sarr			*sipp = *xipp;
21991040Sarr			*xipp = save;
22091040Sarr		}
22125537Sdfr	}
22225537Sdfr
22391040Sarr	/*
22491040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
22591040Sarr	 * Perform each task, and continue on to the next task.
22691040Sarr	 */
227160142Sjhb	mtx_lock(&Giant);
22891040Sarr	for (sipp = start; sipp < stop; sipp++) {
22991040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
23091040Sarr			continue;	/* skip dummy task(s) */
23125537Sdfr
23291040Sarr		/* Call function */
23391040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
23491040Sarr	}
235160142Sjhb	mtx_unlock(&Giant);
23625537Sdfr}
23725537Sdfr
23841055Speterstatic void
23941055Speterlinker_file_sysuninit(linker_file_t lf)
24041055Speter{
24191040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
24241055Speter
24391040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
24491040Sarr	    lf->filename));
24541055Speter
24691068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
24791040Sarr	    NULL) != 0)
24891040Sarr		return;
24941055Speter
25091040Sarr	/*
25191040Sarr	 * Perform a reverse bubble sort of the system initialization objects
25291040Sarr	 * by their subsystem (primary key) and order (secondary key).
253159840Sjhb	 *
25491040Sarr	 * Since some things care about execution order, this is the operation
25591040Sarr	 * which ensures continued function.
25691040Sarr	 */
25791040Sarr	for (sipp = start; sipp < stop; sipp++) {
25891040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
25991040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
26091040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
26191040Sarr			    (*sipp)->order >= (*xipp)->order))
26291040Sarr				continue;	/* skip */
26391040Sarr			save = *sipp;
26491040Sarr			*sipp = *xipp;
26591040Sarr			*xipp = save;
26691040Sarr		}
26741055Speter	}
26841055Speter
26991040Sarr	/*
27091040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
27191040Sarr	 * Perform each task, and continue on to the next task.
27291040Sarr	 */
273160142Sjhb	mtx_lock(&Giant);
27491040Sarr	for (sipp = start; sipp < stop; sipp++) {
27591040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
27691040Sarr			continue;	/* skip dummy task(s) */
27741055Speter
27891040Sarr		/* Call function */
27991040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
28091040Sarr	}
281160142Sjhb	mtx_unlock(&Giant);
28241055Speter}
28341055Speter
28444078Sdfrstatic void
28544078Sdfrlinker_file_register_sysctls(linker_file_t lf)
28644078Sdfr{
28791040Sarr	struct sysctl_oid **start, **stop, **oidp;
28844078Sdfr
28991040Sarr	KLD_DPF(FILE,
29091040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
29191040Sarr	    lf->filename));
29244078Sdfr
29391040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
29491040Sarr		return;
29544078Sdfr
296188232Sjhb	sysctl_lock();
29791040Sarr	for (oidp = start; oidp < stop; oidp++)
29891040Sarr		sysctl_register_oid(*oidp);
299188232Sjhb	sysctl_unlock();
30044078Sdfr}
30144078Sdfr
30244078Sdfrstatic void
30344078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
30444078Sdfr{
30591040Sarr	struct sysctl_oid **start, **stop, **oidp;
30644078Sdfr
30791040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
30891040Sarr	    " for %s\n", lf->filename));
30944078Sdfr
31091040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
31191040Sarr		return;
31244078Sdfr
313188232Sjhb	sysctl_lock();
31491040Sarr	for (oidp = start; oidp < stop; oidp++)
31591040Sarr		sysctl_unregister_oid(*oidp);
316188232Sjhb	sysctl_unlock();
31744078Sdfr}
31844078Sdfr
31959751Speterstatic int
32059751Speterlinker_file_register_modules(linker_file_t lf)
32159751Speter{
32291040Sarr	struct mod_metadata **start, **stop, **mdp;
32391040Sarr	const moduledata_t *moddata;
324146733Spjd	int first_error, error;
32559751Speter
32691040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
32791040Sarr	    " in %s\n", lf->filename));
32859751Speter
32991068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
330159841Sjhb	    &stop, NULL) != 0) {
33191040Sarr		/*
33291040Sarr		 * This fallback should be unnecessary, but if we get booted
33391040Sarr		 * from boot2 instead of loader and we are missing our
33491040Sarr		 * metadata then we have to try the best we can.
33591040Sarr		 */
33691040Sarr		if (lf == linker_kernel_file) {
33791040Sarr			start = SET_BEGIN(modmetadata_set);
33891040Sarr			stop = SET_LIMIT(modmetadata_set);
33991040Sarr		} else
34091040Sarr			return (0);
34178161Speter	}
342146733Spjd	first_error = 0;
34391040Sarr	for (mdp = start; mdp < stop; mdp++) {
34491040Sarr		if ((*mdp)->md_type != MDT_MODULE)
34591040Sarr			continue;
34691040Sarr		moddata = (*mdp)->md_data;
34791040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
34891040Sarr		    moddata->name, lf->filename));
34991040Sarr		error = module_register(moddata, lf);
350146730Spjd		if (error) {
35191068Sarr			printf("Module %s failed to register: %d\n",
35291040Sarr			    moddata->name, error);
353146733Spjd			if (first_error == 0)
354146733Spjd				first_error = error;
355146730Spjd		}
35659751Speter	}
357146733Spjd	return (first_error);
35859751Speter}
35959751Speter
36059751Speterstatic void
36159751Speterlinker_init_kernel_modules(void)
36259751Speter{
36391040Sarr
36491040Sarr	linker_file_register_modules(linker_kernel_file);
36559751Speter}
36659751Speter
367177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules,
368177253Srwatson    0);
36959751Speter
370101241Smuxstatic int
37191040Sarrlinker_load_file(const char *filename, linker_file_t *result)
37225537Sdfr{
37391040Sarr	linker_class_t lc;
37491040Sarr	linker_file_t lf;
375159585Sjhb	int foundfile, error;
37625537Sdfr
37791040Sarr	/* Refuse to load modules if securelevel raised */
37891040Sarr	if (securelevel > 0)
37991040Sarr		return (EPERM);
38062261Sarchie
381159845Sjhb	KLD_LOCK_ASSERT();
38291040Sarr	lf = linker_find_file_by_name(filename);
38391040Sarr	if (lf) {
38491040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
38591040Sarr		    " incrementing refs\n", filename));
38691040Sarr		*result = lf;
38791040Sarr		lf->refs++;
388159585Sjhb		return (0);
38991040Sarr	}
39091040Sarr	foundfile = 0;
391159585Sjhb	error = 0;
39298452Sarr
39398452Sarr	/*
39498452Sarr	 * We do not need to protect (lock) classes here because there is
39598452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
39698452Sarr	 * and there is no class deregistration mechanism at this time.
39798452Sarr	 */
39891040Sarr	TAILQ_FOREACH(lc, &classes, link) {
39991040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
40091040Sarr		    filename));
40191040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
40291040Sarr		/*
40391040Sarr		 * If we got something other than ENOENT, then it exists but
40491040Sarr		 * we cannot load it for some other reason.
40591040Sarr		 */
40691040Sarr		if (error != ENOENT)
40791040Sarr			foundfile = 1;
40891040Sarr		if (lf) {
409146730Spjd			error = linker_file_register_modules(lf);
410146730Spjd			if (error == EEXIST) {
411146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
412159585Sjhb				return (error);
413146730Spjd			}
414166921Sjhb			KLD_UNLOCK();
41591040Sarr			linker_file_register_sysctls(lf);
41691040Sarr			linker_file_sysinit(lf);
417166921Sjhb			KLD_LOCK();
41891040Sarr			lf->flags |= LINKER_FILE_LINKED;
41991040Sarr			*result = lf;
420159585Sjhb			return (0);
42191040Sarr		}
42291040Sarr	}
42342755Speter	/*
42491040Sarr	 * Less than ideal, but tells the user whether it failed to load or
42591040Sarr	 * the module was not found.
42642755Speter	 */
427105337Ssam	if (foundfile) {
428105337Ssam		/*
429105337Ssam		 * Format not recognized or otherwise unloadable.
430105337Ssam		 * When loading a module that is statically built into
431105337Ssam		 * the kernel EEXIST percolates back up as the return
432105337Ssam		 * value.  Preserve this so that apps like sysinstall
433105337Ssam		 * can recognize this special case and not post bogus
434105337Ssam		 * dialog boxes.
435105337Ssam		 */
436105337Ssam		if (error != EEXIST)
437105337Ssam			error = ENOEXEC;
438105337Ssam	} else
43991068Sarr		error = ENOENT;		/* Nothing found */
44091040Sarr	return (error);
44125537Sdfr}
44225537Sdfr
44378413Sbrianint
44494321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
44594321Sbrian    linker_file_t *result)
44678413Sbrian{
44794321Sbrian	modlist_t mod;
448159804Sjhb	int error;
44994321Sbrian
450159845Sjhb	KLD_LOCK();
45194321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
45294321Sbrian		*result = mod->container;
45394321Sbrian		(*result)->refs++;
454159845Sjhb		KLD_UNLOCK();
45594321Sbrian		return (0);
45694321Sbrian	}
45794321Sbrian
458159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
459159845Sjhb	KLD_UNLOCK();
460159804Sjhb	return (error);
46178413Sbrian}
46278413Sbrian
463159804Sjhbint
464159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
465159804Sjhb    linker_file_t lf)
466159804Sjhb{
467159804Sjhb	modlist_t mod;
468159804Sjhb	int error;
469159804Sjhb
470159845Sjhb	KLD_LOCK();
471159804Sjhb	if (lf == NULL) {
472159804Sjhb		KASSERT(modname != NULL,
473159804Sjhb		    ("linker_release_module: no file or name"));
474159804Sjhb		mod = modlist_lookup2(modname, verinfo);
475159804Sjhb		if (mod == NULL) {
476159845Sjhb			KLD_UNLOCK();
477159804Sjhb			return (ESRCH);
478159804Sjhb		}
479159804Sjhb		lf = mod->container;
480159804Sjhb	} else
481159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
482159804Sjhb		    ("linker_release_module: both file and name"));
483159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
484159845Sjhb	KLD_UNLOCK();
485159804Sjhb	return (error);
486159804Sjhb}
487159804Sjhb
488159800Sjhbstatic linker_file_t
48991040Sarrlinker_find_file_by_name(const char *filename)
49025537Sdfr{
491159585Sjhb	linker_file_t lf;
49291040Sarr	char *koname;
49325537Sdfr
494111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
49591040Sarr	sprintf(koname, "%s.ko", filename);
49640861Speter
497159845Sjhb	KLD_LOCK_ASSERT();
49891040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
49992032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
50091040Sarr			break;
50192032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
50291040Sarr			break;
50391040Sarr	}
504159585Sjhb	free(koname, M_LINKER);
50591040Sarr	return (lf);
50625537Sdfr}
50725537Sdfr
508159800Sjhbstatic linker_file_t
50925537Sdfrlinker_find_file_by_id(int fileid)
51025537Sdfr{
511159585Sjhb	linker_file_t lf;
512159845Sjhb
513159845Sjhb	KLD_LOCK_ASSERT();
51491040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
515166921Sjhb		if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
51691040Sarr			break;
51791040Sarr	return (lf);
51825537Sdfr}
51925537Sdfr
520159797Sjhbint
521159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
522159797Sjhb{
523159797Sjhb	linker_file_t lf;
524159797Sjhb	int retval = 0;
525159797Sjhb
526159845Sjhb	KLD_LOCK();
527159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
528159797Sjhb		retval = predicate(lf, context);
529159797Sjhb		if (retval != 0)
530159797Sjhb			break;
531159797Sjhb	}
532159845Sjhb	KLD_UNLOCK();
533159797Sjhb	return (retval);
534159797Sjhb}
535159797Sjhb
53625537Sdfrlinker_file_t
53791040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
53825537Sdfr{
53991040Sarr	linker_file_t lf;
54091040Sarr	const char *filename;
54125537Sdfr
542159845Sjhb	KLD_LOCK_ASSERT();
54391040Sarr	filename = linker_basename(pathname);
54440159Speter
545172862Sjb	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
546111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
54791040Sarr	if (lf == NULL)
548159585Sjhb		return (NULL);
54991040Sarr	lf->refs = 1;
55091040Sarr	lf->userrefs = 0;
55191040Sarr	lf->flags = 0;
55291040Sarr	lf->filename = linker_strdup(filename);
553172862Sjb	lf->pathname = linker_strdup(pathname);
55491040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
55591040Sarr	lf->ndeps = 0;
55691040Sarr	lf->deps = NULL;
557172862Sjb	lf->loadcnt = ++loadcnt;
558172862Sjb	lf->sdt_probes = NULL;
559172862Sjb	lf->sdt_nprobes = 0;
56091040Sarr	STAILQ_INIT(&lf->common);
56191040Sarr	TAILQ_INIT(&lf->modules);
56291040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
56391040Sarr	return (lf);
56425537Sdfr}
56525537Sdfr
56625537Sdfrint
567132117Sphklinker_file_unload(linker_file_t file, int flags)
56825537Sdfr{
56991040Sarr	module_t mod, next;
57091040Sarr	modlist_t ml, nextml;
57191040Sarr	struct common_symbol *cp;
57291040Sarr	int error, i;
57325537Sdfr
57491040Sarr	/* Refuse to unload modules if securelevel raised. */
57591040Sarr	if (securelevel > 0)
57691040Sarr		return (EPERM);
57725537Sdfr
578159845Sjhb	KLD_LOCK_ASSERT();
57991040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
58091040Sarr
581159584Sjhb	/* Easy case of just dropping a reference. */
582159584Sjhb	if (file->refs > 1) {
583159584Sjhb		file->refs--;
584159584Sjhb		return (0);
585159584Sjhb	}
586159584Sjhb
587159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
588159584Sjhb	    " informing modules\n"));
589159584Sjhb
590159584Sjhb	/*
591185635Sjhb	 * Quiesce all the modules to give them a chance to veto the unload.
592159584Sjhb	 */
593185635Sjhb	MOD_SLOCK;
594185635Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod;
595185635Sjhb	     mod = module_getfnext(mod)) {
596185635Sjhb
597185635Sjhb		error = module_quiesce(mod);
598185635Sjhb		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
599185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
600185635Sjhb			    " vetoed unload\n", module_getname(mod)));
601185635Sjhb			/*
602185635Sjhb			 * XXX: Do we need to tell all the quiesced modules
603185635Sjhb			 * that they can resume work now via a new module
604185635Sjhb			 * event?
605185635Sjhb			 */
606185635Sjhb			MOD_SUNLOCK;
607185635Sjhb			return (error);
608185635Sjhb		}
609185635Sjhb	}
610185635Sjhb	MOD_SUNLOCK;
611185635Sjhb
612185635Sjhb	/*
613185635Sjhb	 * Inform any modules associated with this file that they are
614185635Sjhb	 * being be unloaded.
615185635Sjhb	 */
616159584Sjhb	MOD_XLOCK;
617159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
618159584Sjhb		next = module_getfnext(mod);
619159584Sjhb		MOD_XUNLOCK;
620159584Sjhb
62191040Sarr		/*
622159584Sjhb		 * Give the module a chance to veto the unload.
62391040Sarr		 */
624185635Sjhb		if ((error = module_unload(mod)) != 0) {
625185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
626185635Sjhb			    " failed unload\n", mod));
627159584Sjhb			return (error);
628159584Sjhb		}
62992547Sarr		MOD_XLOCK;
630159584Sjhb		module_release(mod);
631159584Sjhb	}
632159584Sjhb	MOD_XUNLOCK;
63391040Sarr
634159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
635128057Speadar		if (ml->container == file) {
63691040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
637128057Speadar			free(ml, M_LINKER);
638128057Speadar		}
63991040Sarr	}
64025537Sdfr
641159840Sjhb	/*
642159840Sjhb	 * Don't try to run SYSUNINITs if we are unloaded due to a
64391040Sarr	 * link error.
64491040Sarr	 */
64591040Sarr	if (file->flags & LINKER_FILE_LINKED) {
646188209Sjhb		file->flags &= ~LINKER_FILE_LINKED;
647188209Sjhb		KLD_UNLOCK();
64891040Sarr		linker_file_sysuninit(file);
64991040Sarr		linker_file_unregister_sysctls(file);
650188209Sjhb		KLD_LOCK();
65125537Sdfr	}
65291040Sarr	TAILQ_REMOVE(&linker_files, file, link);
65325537Sdfr
65491040Sarr	if (file->deps) {
65591040Sarr		for (i = 0; i < file->ndeps; i++)
656132117Sphk			linker_file_unload(file->deps[i], flags);
65791040Sarr		free(file->deps, M_LINKER);
65891040Sarr		file->deps = NULL;
65959751Speter	}
660160245Sjhb	while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
661160245Sjhb		STAILQ_REMOVE_HEAD(&file->common, link);
66291040Sarr		free(cp, M_LINKER);
66391040Sarr	}
66459751Speter
66591040Sarr	LINKER_UNLOAD(file);
66691040Sarr	if (file->filename) {
66791040Sarr		free(file->filename, M_LINKER);
66891040Sarr		file->filename = NULL;
66991040Sarr	}
670172862Sjb	if (file->pathname) {
671172862Sjb		free(file->pathname, M_LINKER);
672172862Sjb		file->pathname = NULL;
673172862Sjb	}
67491040Sarr	kobj_delete((kobj_t) file, M_LINKER);
675159584Sjhb	return (0);
67625537Sdfr}
67725537Sdfr
678179238Sjbint
679179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc)
680179238Sjb{
681179238Sjb	return (LINKER_CTF_GET(file, lc));
682179238Sjb}
683179238Sjb
684159796Sjhbstatic int
68586469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
68625537Sdfr{
68791040Sarr	linker_file_t *newdeps;
68825537Sdfr
689159845Sjhb	KLD_LOCK_ASSERT();
69091040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
691111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
69291040Sarr	if (newdeps == NULL)
69391040Sarr		return (ENOMEM);
69425537Sdfr
69591040Sarr	if (file->deps) {
69691040Sarr		bcopy(file->deps, newdeps,
69791040Sarr		    file->ndeps * sizeof(linker_file_t *));
69891040Sarr		free(file->deps, M_LINKER);
69991040Sarr	}
70091040Sarr	file->deps = newdeps;
70191040Sarr	file->deps[file->ndeps] = dep;
70291040Sarr	file->ndeps++;
70391040Sarr	return (0);
70425537Sdfr}
70525537Sdfr
70678161Speter/*
70791040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
708159841Sjhb * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
709159841Sjhb * This function is used in this file so we can avoid having lots of (void **)
710159841Sjhb * casts.
71178161Speter */
71278161Speterint
71378161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
71491040Sarr    void *firstp, void *lastp, int *countp)
71578161Speter{
716159845Sjhb	int error, locked;
71778161Speter
718159845Sjhb	locked = KLD_LOCKED();
719159845Sjhb	if (!locked)
720159845Sjhb		KLD_LOCK();
721159845Sjhb	error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
722159845Sjhb	if (!locked)
723159845Sjhb		KLD_UNLOCK();
724159845Sjhb	return (error);
72578161Speter}
72678161Speter
727173714Sjb/*
728173714Sjb * List all functions in a file.
729173714Sjb */
730173714Sjbint
731173714Sjblinker_file_function_listall(linker_file_t lf,
732179238Sjb    linker_function_nameval_callback_t callback_func, void *arg)
733173714Sjb{
734173714Sjb	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
735173714Sjb}
736173714Sjb
73725537Sdfrcaddr_t
73891040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
73925537Sdfr{
740159845Sjhb	caddr_t sym;
741159845Sjhb	int locked;
742159845Sjhb
743159845Sjhb	locked = KLD_LOCKED();
744159845Sjhb	if (!locked)
745159845Sjhb		KLD_LOCK();
746159845Sjhb	sym = linker_file_lookup_symbol_internal(file, name, deps);
747159845Sjhb	if (!locked)
748159845Sjhb		KLD_UNLOCK();
749159845Sjhb	return (sym);
750159845Sjhb}
751159845Sjhb
752159845Sjhbstatic caddr_t
753159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name,
754159845Sjhb    int deps)
755159845Sjhb{
75691040Sarr	c_linker_sym_t sym;
75791040Sarr	linker_symval_t symval;
75891040Sarr	caddr_t address;
75991040Sarr	size_t common_size = 0;
76092032Sdwmalone	int i;
76125537Sdfr
762159845Sjhb	KLD_LOCK_ASSERT();
763109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
76491040Sarr	    file, name, deps));
76525537Sdfr
76691040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
76791040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
76891040Sarr		if (symval.value == 0)
76991040Sarr			/*
77091040Sarr			 * For commons, first look them up in the
77191040Sarr			 * dependencies and only allocate space if not found
77291040Sarr			 * there.
77391040Sarr			 */
77491040Sarr			common_size = symval.size;
77591040Sarr		else {
77691040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
777109605Sjake			    ".value=%p\n", symval.value));
77891040Sarr			return (symval.value);
77991040Sarr		}
78040159Speter	}
78191040Sarr	if (deps) {
78291040Sarr		for (i = 0; i < file->ndeps; i++) {
783159845Sjhb			address = linker_file_lookup_symbol_internal(
784159845Sjhb			    file->deps[i], name, 0);
78591040Sarr			if (address) {
78691040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
787109605Sjake				    " deps value=%p\n", address));
78891040Sarr				return (address);
78991040Sarr			}
79091040Sarr		}
79125537Sdfr	}
79291040Sarr	if (common_size > 0) {
79391040Sarr		/*
79491040Sarr		 * This is a common symbol which was not found in the
79591040Sarr		 * dependencies.  We maintain a simple common symbol table in
79691040Sarr		 * the file object.
79791040Sarr		 */
79891040Sarr		struct common_symbol *cp;
79942849Speter
80091040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
80192032Sdwmalone			if (strcmp(cp->name, name) == 0) {
80291040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
803109605Sjake				    " old common value=%p\n", cp->address));
80491040Sarr				return (cp->address);
80591040Sarr			}
80691040Sarr		}
80791040Sarr		/*
80891040Sarr		 * Round the symbol size up to align.
80991040Sarr		 */
81091040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
81191040Sarr		cp = malloc(sizeof(struct common_symbol)
81291040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
813111119Simp		    M_WAITOK | M_ZERO);
81491040Sarr		cp->address = (caddr_t)(cp + 1);
81591040Sarr		cp->name = cp->address + common_size;
81691040Sarr		strcpy(cp->name, name);
81791040Sarr		bzero(cp->address, common_size);
81891040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
81925537Sdfr
82091040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
821109605Sjake		    " value=%p\n", cp->address));
82291040Sarr		return (cp->address);
82340159Speter	}
82491040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
82591040Sarr	return (0);
82625537Sdfr}
82725537Sdfr
82825537Sdfr/*
829174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and
830174132Srwatson * backward lookup of symbols.  However, DDB and sometimes stack(9) need to
831174132Srwatson * do this in a lockfree manner.  We provide a set of internal helper
832174132Srwatson * routines to perform these operations without locks, and then wrappers that
833174132Srwatson * optionally lock.
834159840Sjhb *
835174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
83640159Speter */
837174132Srwatson#ifdef DDB
838174132Srwatsonstatic int
839174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
84040159Speter{
84191040Sarr	linker_file_t lf;
84240159Speter
84391040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
84491040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
84591040Sarr			return (0);
84691040Sarr	}
84791040Sarr	return (ENOENT);
84840159Speter}
849174132Srwatson#endif
85040159Speter
851174132Srwatsonstatic int
852174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
85340159Speter{
85491040Sarr	linker_file_t lf;
85591040Sarr	c_linker_sym_t best, es;
85691040Sarr	u_long diff, bestdiff, off;
85740159Speter
85891040Sarr	best = 0;
85991040Sarr	off = (uintptr_t)value;
86091040Sarr	bestdiff = off;
86191040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
86291040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
86391040Sarr			continue;
86491040Sarr		if (es != 0 && diff < bestdiff) {
86591040Sarr			best = es;
86691040Sarr			bestdiff = diff;
86791040Sarr		}
86891040Sarr		if (bestdiff == 0)
86991040Sarr			break;
87040159Speter	}
87191040Sarr	if (best) {
87291040Sarr		*sym = best;
87391040Sarr		*diffp = bestdiff;
87491040Sarr		return (0);
87591040Sarr	} else {
87691040Sarr		*sym = 0;
87791040Sarr		*diffp = off;
87891040Sarr		return (ENOENT);
87991040Sarr	}
88040159Speter}
88140159Speter
882174132Srwatsonstatic int
883174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
88440159Speter{
88591040Sarr	linker_file_t lf;
88640159Speter
88791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
88891040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
88991040Sarr			return (0);
89091040Sarr	}
89191040Sarr	return (ENOENT);
89240159Speter}
893174132Srwatson
894174132Srwatsonstatic int
895174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
896174132Srwatson    long *offset)
897174132Srwatson{
898174132Srwatson	linker_symval_t symval;
899174132Srwatson	c_linker_sym_t sym;
900174132Srwatson	int error;
901174132Srwatson
902174132Srwatson	*offset = 0;
903174132Srwatson	error = linker_debug_search_symbol(value, &sym, offset);
904174132Srwatson	if (error)
905174132Srwatson		return (error);
906174132Srwatson	error = linker_debug_symbol_values(sym, &symval);
907174132Srwatson	if (error)
908174132Srwatson		return (error);
909174132Srwatson	strlcpy(buf, symval.name, buflen);
910174132Srwatson	return (0);
911174132Srwatson}
912174132Srwatson
913174132Srwatson#ifdef DDB
914174132Srwatson/*
915174132Srwatson * DDB Helpers.  DDB has to look across multiple files with their own symbol
916174132Srwatson * tables and string tables.
917174132Srwatson *
918174132Srwatson * Note that we do not obey list locking protocols here.  We really don't need
919174132Srwatson * DDB to hang because somebody's got the lock held.  We'll take the chance
920174132Srwatson * that the files list is inconsistant instead.
921174132Srwatson */
922174132Srwatsonint
923174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
924174132Srwatson{
925174132Srwatson
926174132Srwatson	return (linker_debug_lookup(symstr, sym));
927174132Srwatson}
928174132Srwatson
929174132Srwatsonint
930174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
931174132Srwatson{
932174132Srwatson
933174132Srwatson	return (linker_debug_search_symbol(value, sym, diffp));
934174132Srwatson}
935174132Srwatson
936174132Srwatsonint
937174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
938174132Srwatson{
939174132Srwatson
940174132Srwatson	return (linker_debug_symbol_values(sym, symval));
941174132Srwatson}
942174132Srwatson
943174132Srwatsonint
944174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
945174132Srwatson    long *offset)
946174132Srwatson{
947174132Srwatson
948174132Srwatson	return (linker_debug_search_symbol_name(value, buf, buflen, offset));
949174132Srwatson}
95040159Speter#endif
95140159Speter
95240159Speter/*
953174132Srwatson * stack(9) helper for non-debugging environemnts.  Unlike DDB helpers, we do
954174132Srwatson * obey locking protocols, and offer a significantly less complex interface.
955174132Srwatson */
956174132Srwatsonint
957174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
958174132Srwatson    long *offset)
959174132Srwatson{
960178380Spjd	int error;
961174132Srwatson
962178380Spjd	KLD_LOCK();
963174132Srwatson	error = linker_debug_search_symbol_name(value, buf, buflen, offset);
964178380Spjd	KLD_UNLOCK();
965174132Srwatson	return (error);
966174132Srwatson}
967174132Srwatson
968174132Srwatson/*
96925537Sdfr * Syscalls.
97025537Sdfr */
97125537Sdfrint
972159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
97325537Sdfr{
974157144Sjkoshy#ifdef HWPMC_HOOKS
975157144Sjkoshy	struct pmckern_map_in pkm;
976157144Sjkoshy#endif
977159588Sjhb	const char *kldname, *modname;
97891040Sarr	linker_file_t lf;
979159588Sjhb	int error;
98025537Sdfr
98193159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
982159588Sjhb		return (error);
98393159Sarr
984164033Srwatson	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
985159588Sjhb		return (error);
98625537Sdfr
98791040Sarr	/*
988159841Sjhb	 * If file does not contain a qualified name or any dot in it
989159841Sjhb	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
99091040Sarr	 * name.
99191040Sarr	 */
992159588Sjhb	if (index(file, '/') || index(file, '.')) {
993159588Sjhb		kldname = file;
99491040Sarr		modname = NULL;
99591040Sarr	} else {
99691040Sarr		kldname = NULL;
997159588Sjhb		modname = file;
99891040Sarr	}
999159588Sjhb
1000159845Sjhb	KLD_LOCK();
100191040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
100291040Sarr	if (error)
1003159588Sjhb		goto unlock;
1004157144Sjkoshy#ifdef HWPMC_HOOKS
1005157144Sjkoshy	pkm.pm_file = lf->filename;
1006157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
1007157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
1008157144Sjkoshy#endif
100991040Sarr	lf->userrefs++;
1010159588Sjhb	if (fileid != NULL)
1011159588Sjhb		*fileid = lf->id;
1012159588Sjhbunlock:
1013159845Sjhb	KLD_UNLOCK();
101491040Sarr	return (error);
101525537Sdfr}
101625537Sdfr
1017159588Sjhbint
1018159588Sjhbkldload(struct thread *td, struct kldload_args *uap)
1019159588Sjhb{
1020159588Sjhb	char *pathname = NULL;
1021159596Smarcel	int error, fileid;
1022159588Sjhb
1023159588Sjhb	td->td_retval[0] = -1;
1024159588Sjhb
1025159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1026159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1027159596Smarcel	if (error == 0) {
1028159596Smarcel		error = kern_kldload(td, pathname, &fileid);
1029159596Smarcel		if (error == 0)
1030159596Smarcel			td->td_retval[0] = fileid;
1031159596Smarcel	}
1032159588Sjhb	free(pathname, M_TEMP);
1033159588Sjhb	return (error);
1034159588Sjhb}
1035159588Sjhb
1036159588Sjhbint
1037132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
103825537Sdfr{
1039157144Sjkoshy#ifdef HWPMC_HOOKS
1040157144Sjkoshy	struct pmckern_map_out pkm;
1041157144Sjkoshy#endif
104291040Sarr	linker_file_t lf;
104391040Sarr	int error = 0;
104425537Sdfr
104593159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1046159588Sjhb		return (error);
104793159Sarr
1048164033Srwatson	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1049159588Sjhb		return (error);
105025537Sdfr
1051159845Sjhb	KLD_LOCK();
1052132117Sphk	lf = linker_find_file_by_id(fileid);
105391040Sarr	if (lf) {
105491040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
1055172862Sjb
1056172862Sjb		/* Check if there are DTrace probes enabled on this file. */
1057172862Sjb		if (lf->nenabled > 0) {
1058172862Sjb			printf("kldunload: attempt to unload file that has"
1059172862Sjb			    " DTrace probes enabled\n");
1060172862Sjb			error = EBUSY;
1061172862Sjb		} else if (lf->userrefs == 0) {
1062132117Sphk			/*
1063132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
1064132117Sphk			 */
106591040Sarr			printf("kldunload: attempt to unload file that was"
106691040Sarr			    " loaded by the kernel\n");
1067159840Sjhb			error = EBUSY;
1068159588Sjhb		} else {
1069157144Sjkoshy#ifdef HWPMC_HOOKS
1070159588Sjhb			/* Save data needed by hwpmc(4) before unloading. */
1071159588Sjhb			pkm.pm_address = (uintptr_t) lf->address;
1072159588Sjhb			pkm.pm_size = lf->size;
1073157144Sjkoshy#endif
1074159588Sjhb			lf->userrefs--;
1075159588Sjhb			error = linker_file_unload(lf, flags);
1076159588Sjhb			if (error)
1077159588Sjhb				lf->userrefs++;
1078159588Sjhb		}
107991040Sarr	} else
108091040Sarr		error = ENOENT;
1081157144Sjkoshy
1082157144Sjkoshy#ifdef HWPMC_HOOKS
1083157144Sjkoshy	if (error == 0)
1084157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
1085157144Sjkoshy#endif
1086159845Sjhb	KLD_UNLOCK();
108791068Sarr	return (error);
108825537Sdfr}
108925537Sdfr
109025537Sdfrint
1091132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
1092132117Sphk{
1093132117Sphk
1094132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
1095132117Sphk}
1096132117Sphk
1097132117Sphkint
1098132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
1099132117Sphk{
1100132117Sphk
1101132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
1102132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
1103132117Sphk		return (EINVAL);
1104132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
1105132117Sphk}
1106132117Sphk
1107132117Sphkint
110891040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
110925537Sdfr{
111091040Sarr	char *pathname;
111191040Sarr	const char *filename;
111291040Sarr	linker_file_t lf;
1113159791Sjhb	int error;
111425537Sdfr
1115107089Srwatson#ifdef MAC
1116172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1117107089Srwatson	if (error)
1118107089Srwatson		return (error);
1119107089Srwatson#endif
1120107089Srwatson
112191040Sarr	td->td_retval[0] = -1;
112282749Sdillon
1123111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1124107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
112591040Sarr		goto out;
112625537Sdfr
112791040Sarr	filename = linker_basename(pathname);
1128159845Sjhb	KLD_LOCK();
112991040Sarr	lf = linker_find_file_by_name(filename);
113091040Sarr	if (lf)
113191040Sarr		td->td_retval[0] = lf->id;
113291040Sarr	else
113391040Sarr		error = ENOENT;
1134159845Sjhb	KLD_UNLOCK();
113525537Sdfrout:
1136159791Sjhb	free(pathname, M_TEMP);
113791040Sarr	return (error);
113825537Sdfr}
113925537Sdfr
114025537Sdfrint
114191040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
114225537Sdfr{
114391040Sarr	linker_file_t lf;
114491040Sarr	int error = 0;
114525537Sdfr
1146107089Srwatson#ifdef MAC
1147172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1148107089Srwatson	if (error)
1149107089Srwatson		return (error);
1150107089Srwatson#endif
1151107089Srwatson
1152159845Sjhb	KLD_LOCK();
1153166921Sjhb	if (uap->fileid == 0)
1154166921Sjhb		lf = TAILQ_FIRST(&linker_files);
1155166921Sjhb	else {
1156166921Sjhb		lf = linker_find_file_by_id(uap->fileid);
1157166921Sjhb		if (lf == NULL) {
1158166921Sjhb			error = ENOENT;
1159166921Sjhb			goto out;
1160166921Sjhb		}
1161166921Sjhb		lf = TAILQ_NEXT(lf, link);
116291040Sarr	}
1163166921Sjhb
1164166921Sjhb	/* Skip partially loaded files. */
1165166921Sjhb	while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1166166921Sjhb		lf = TAILQ_NEXT(lf, link);
1167166921Sjhb
1168166921Sjhb	if (lf)
1169166921Sjhb		td->td_retval[0] = lf->id;
1170166921Sjhb	else
1171166921Sjhb		td->td_retval[0] = 0;
117282749Sdillonout:
1173159845Sjhb	KLD_UNLOCK();
117491040Sarr	return (error);
117525537Sdfr}
117625537Sdfr
117725537Sdfrint
117891040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
117925537Sdfr{
1180159587Sjhb	struct kld_file_stat stat;
118191040Sarr	linker_file_t lf;
1182172862Sjb	int error, namelen, version, version_num;
118325537Sdfr
1184159587Sjhb	/*
1185159587Sjhb	 * Check the version of the user's structure.
1186159587Sjhb	 */
1187172862Sjb	if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
1188159587Sjhb		return (error);
1189172862Sjb	if (version == sizeof(struct kld_file_stat_1))
1190172862Sjb		version_num = 1;
1191172862Sjb	else if (version == sizeof(struct kld_file_stat))
1192172862Sjb		version_num = 2;
1193172862Sjb	else
1194159587Sjhb		return (EINVAL);
1195159587Sjhb
1196107089Srwatson#ifdef MAC
1197172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1198107089Srwatson	if (error)
1199107089Srwatson		return (error);
1200107089Srwatson#endif
1201107089Srwatson
1202159845Sjhb	KLD_LOCK();
1203107849Salfred	lf = linker_find_file_by_id(uap->fileid);
120491040Sarr	if (lf == NULL) {
1205159845Sjhb		KLD_UNLOCK();
1206159587Sjhb		return (ENOENT);
120791040Sarr	}
120825537Sdfr
1209172862Sjb	/* Version 1 fields: */
121091040Sarr	namelen = strlen(lf->filename) + 1;
121191040Sarr	if (namelen > MAXPATHLEN)
121291040Sarr		namelen = MAXPATHLEN;
1213159587Sjhb	bcopy(lf->filename, &stat.name[0], namelen);
1214159587Sjhb	stat.refs = lf->refs;
1215159587Sjhb	stat.id = lf->id;
1216159587Sjhb	stat.address = lf->address;
1217159587Sjhb	stat.size = lf->size;
1218172862Sjb	if (version_num > 1) {
1219172862Sjb		/* Version 2 fields: */
1220172862Sjb		namelen = strlen(lf->pathname) + 1;
1221172862Sjb		if (namelen > MAXPATHLEN)
1222172862Sjb			namelen = MAXPATHLEN;
1223172862Sjb		bcopy(lf->pathname, &stat.pathname[0], namelen);
1224172862Sjb	}
1225159845Sjhb	KLD_UNLOCK();
122625537Sdfr
122791040Sarr	td->td_retval[0] = 0;
1228159587Sjhb
1229172862Sjb	return (copyout(&stat, uap->stat, version));
123025537Sdfr}
123125537Sdfr
123225537Sdfrint
123391040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
123425537Sdfr{
123591040Sarr	linker_file_t lf;
123691040Sarr	module_t mp;
123791040Sarr	int error = 0;
123825537Sdfr
1239107089Srwatson#ifdef MAC
1240172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1241107089Srwatson	if (error)
1242107089Srwatson		return (error);
1243107089Srwatson#endif
1244107089Srwatson
1245159845Sjhb	KLD_LOCK();
1246107849Salfred	lf = linker_find_file_by_id(uap->fileid);
124791040Sarr	if (lf) {
124892547Sarr		MOD_SLOCK;
124991040Sarr		mp = TAILQ_FIRST(&lf->modules);
125091040Sarr		if (mp != NULL)
125191040Sarr			td->td_retval[0] = module_getid(mp);
125291040Sarr		else
125391040Sarr			td->td_retval[0] = 0;
125492547Sarr		MOD_SUNLOCK;
125591040Sarr	} else
125691040Sarr		error = ENOENT;
1257159845Sjhb	KLD_UNLOCK();
125891040Sarr	return (error);
125925537Sdfr}
126040159Speter
126141090Speterint
126283366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
126341090Speter{
126491040Sarr	char *symstr = NULL;
126591040Sarr	c_linker_sym_t sym;
126691040Sarr	linker_symval_t symval;
126791040Sarr	linker_file_t lf;
126891040Sarr	struct kld_sym_lookup lookup;
126991040Sarr	int error = 0;
127041090Speter
1271107089Srwatson#ifdef MAC
1272172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1273107089Srwatson	if (error)
1274107089Srwatson		return (error);
1275107089Srwatson#endif
1276107089Srwatson
1277107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1278159843Sjhb		return (error);
127991068Sarr	if (lookup.version != sizeof(lookup) ||
1280159843Sjhb	    uap->cmd != KLDSYM_LOOKUP)
1281159843Sjhb		return (EINVAL);
1282111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
128391040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
128491040Sarr		goto out;
1285159845Sjhb	KLD_LOCK();
1286107849Salfred	if (uap->fileid != 0) {
1287107849Salfred		lf = linker_find_file_by_id(uap->fileid);
1288159843Sjhb		if (lf == NULL)
128991040Sarr			error = ENOENT;
1290159843Sjhb		else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
129191040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
129291040Sarr			lookup.symvalue = (uintptr_t) symval.value;
129391040Sarr			lookup.symsize = symval.size;
1294107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
129591040Sarr		} else
129691040Sarr			error = ENOENT;
129791040Sarr	} else {
129891040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
129991040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
130091040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
130191040Sarr				lookup.symvalue = (uintptr_t)symval.value;
130291040Sarr				lookup.symsize = symval.size;
1303107849Salfred				error = copyout(&lookup, uap->data,
130491040Sarr				    sizeof(lookup));
130591068Sarr				break;
130691040Sarr			}
130791040Sarr		}
1308185895Szec#ifndef VIMAGE_GLOBALS
1309185895Szec		/*
1310185895Szec		 * If the symbol is not found in global namespace,
1311185895Szec		 * try to look it up in the current vimage namespace.
1312185895Szec		 */
1313185895Szec		if (lf == NULL) {
1314185895Szec			CURVNET_SET(TD_TO_VNET(td));
1315185895Szec			error = vi_symlookup(&lookup, symstr);
1316185895Szec			CURVNET_RESTORE();
1317185895Szec			if (error == 0)
1318185895Szec				error = copyout(&lookup, uap->data,
1319185895Szec						sizeof(lookup));
1320185895Szec		}
1321185895Szec#else
132291040Sarr		if (lf == NULL)
132391040Sarr			error = ENOENT;
1324185895Szec#endif
132541090Speter	}
1326159845Sjhb	KLD_UNLOCK();
132741090Speterout:
1328159843Sjhb	free(symstr, M_TEMP);
132991040Sarr	return (error);
133041090Speter}
133141090Speter
133240159Speter/*
133340159Speter * Preloaded module support
133440159Speter */
133540159Speter
133659751Speterstatic modlist_t
133774642Sbpmodlist_lookup(const char *name, int ver)
133859751Speter{
133991040Sarr	modlist_t mod;
134059751Speter
134191040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
134292032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
134392032Sdwmalone		    (ver == 0 || mod->version == ver))
134491040Sarr			return (mod);
134591040Sarr	}
134691040Sarr	return (NULL);
134759751Speter}
134859751Speter
134974642Sbpstatic modlist_t
135083321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
135183321Speter{
135291040Sarr	modlist_t mod, bestmod;
135392032Sdwmalone	int ver;
135483321Speter
135591040Sarr	if (verinfo == NULL)
135691040Sarr		return (modlist_lookup(name, 0));
135791040Sarr	bestmod = NULL;
1358159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
135992032Sdwmalone		if (strcmp(mod->name, name) != 0)
136091040Sarr			continue;
136191040Sarr		ver = mod->version;
136291040Sarr		if (ver == verinfo->md_ver_preferred)
136391040Sarr			return (mod);
136491040Sarr		if (ver >= verinfo->md_ver_minimum &&
136591068Sarr		    ver <= verinfo->md_ver_maximum &&
1366120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
136791040Sarr			bestmod = mod;
136891040Sarr	}
136991040Sarr	return (bestmod);
137083321Speter}
137183321Speter
137283321Speterstatic modlist_t
137378501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
137474642Sbp{
137591040Sarr	modlist_t mod;
137674642Sbp
137792705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
137891040Sarr	if (mod == NULL)
137991040Sarr		panic("no memory for module list");
138091040Sarr	mod->container = container;
138191040Sarr	mod->name = modname;
138291040Sarr	mod->version = version;
138391040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
138491040Sarr	return (mod);
138574642Sbp}
138674642Sbp
138740159Speterstatic void
138878161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
138991040Sarr    struct mod_metadata **stop, int preload)
139074642Sbp{
139191040Sarr	struct mod_metadata *mp, **mdp;
139291040Sarr	const char *modname;
139391040Sarr	int ver;
139474642Sbp
139591040Sarr	for (mdp = start; mdp < stop; mdp++) {
1396109605Sjake		mp = *mdp;
139791040Sarr		if (mp->md_type != MDT_VERSION)
139891040Sarr			continue;
1399109605Sjake		modname = mp->md_cval;
1400109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
140191040Sarr		if (modlist_lookup(modname, ver) != NULL) {
140291040Sarr			printf("module %s already present!\n", modname);
140391040Sarr			/* XXX what can we do? this is a build error. :-( */
140491040Sarr			continue;
140591040Sarr		}
140691040Sarr		modlist_newmodule(modname, ver, lf);
140774642Sbp	}
140874642Sbp}
140974642Sbp
141074642Sbpstatic void
141191040Sarrlinker_preload(void *arg)
141240159Speter{
141391040Sarr	caddr_t modptr;
141491040Sarr	const char *modname, *nmodname;
141591040Sarr	char *modtype;
1416160244Sjhb	linker_file_t lf, nlf;
141791040Sarr	linker_class_t lc;
141892032Sdwmalone	int error;
141991040Sarr	linker_file_list_t loaded_files;
142091040Sarr	linker_file_list_t depended_files;
142191040Sarr	struct mod_metadata *mp, *nmp;
142291040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
142391040Sarr	struct mod_depend *verinfo;
142491040Sarr	int nver;
142591040Sarr	int resolves;
142691040Sarr	modlist_t mod;
142791040Sarr	struct sysinit **si_start, **si_stop;
142840159Speter
142991040Sarr	TAILQ_INIT(&loaded_files);
143091040Sarr	TAILQ_INIT(&depended_files);
143191040Sarr	TAILQ_INIT(&found_modules);
143291040Sarr	error = 0;
143359751Speter
143491040Sarr	modptr = NULL;
143591040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
143691040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
143791040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
143891040Sarr		if (modname == NULL) {
143991040Sarr			printf("Preloaded module at %p does not have a"
144091040Sarr			    " name!\n", modptr);
144191040Sarr			continue;
144291040Sarr		}
144391040Sarr		if (modtype == NULL) {
144491040Sarr			printf("Preloaded module at %p does not have a type!\n",
144591040Sarr			    modptr);
144691040Sarr			continue;
144791040Sarr		}
1448131398Sjhb		if (bootverbose)
1449131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1450131398Sjhb			    modptr);
145140159Speter		lf = NULL;
145291040Sarr		TAILQ_FOREACH(lc, &classes, link) {
145391040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1454134364Siedowse			if (!error)
145591040Sarr				break;
1456134364Siedowse			lf = NULL;
145791040Sarr		}
145891040Sarr		if (lf)
145991040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
146040159Speter	}
146140159Speter
146291040Sarr	/*
146391040Sarr	 * First get a list of stuff in the kernel.
146491040Sarr	 */
146591040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
146691040Sarr	    &stop, NULL) == 0)
146791040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
146859751Speter
146959751Speter	/*
1470167019Sjhb	 * This is a once-off kinky bubble sort to resolve relocation
1471167019Sjhb	 * dependency requirements.
147259751Speter	 */
147391040Sarrrestart:
147491040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
147591040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
147691040Sarr		    &stop, NULL);
147791040Sarr		/*
147891040Sarr		 * First, look to see if we would successfully link with this
147991040Sarr		 * stuff.
148091040Sarr		 */
148191040Sarr		resolves = 1;	/* unless we know otherwise */
148291040Sarr		if (!error) {
148391040Sarr			for (mdp = start; mdp < stop; mdp++) {
1484109605Sjake				mp = *mdp;
148591040Sarr				if (mp->md_type != MDT_DEPEND)
148691040Sarr					continue;
1487109605Sjake				modname = mp->md_cval;
1488109605Sjake				verinfo = mp->md_data;
148991040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1490109605Sjake					nmp = *nmdp;
149191040Sarr					if (nmp->md_type != MDT_VERSION)
149291040Sarr						continue;
1493109605Sjake					nmodname = nmp->md_cval;
149492032Sdwmalone					if (strcmp(modname, nmodname) == 0)
149591040Sarr						break;
149691040Sarr				}
149791040Sarr				if (nmdp < stop)   /* it's a self reference */
149891040Sarr					continue;
1499159840Sjhb
150091040Sarr				/*
150191040Sarr				 * ok, the module isn't here yet, we
150291040Sarr				 * are not finished
150391040Sarr				 */
150491068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
150591040Sarr					resolves = 0;
150691040Sarr			}
150764143Speter		}
150891040Sarr		/*
150991040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
151091040Sarr		 * the modules inside and add it to the end of the link order
151191040Sarr		 * list.
151291040Sarr		 */
151391040Sarr		if (resolves) {
151491040Sarr			if (!error) {
151591040Sarr				for (mdp = start; mdp < stop; mdp++) {
1516109605Sjake					mp = *mdp;
151791040Sarr					if (mp->md_type != MDT_VERSION)
151891040Sarr						continue;
1519109605Sjake					modname = mp->md_cval;
1520109605Sjake					nver = ((struct mod_version *)
1521109605Sjake					    mp->md_data)->mv_version;
152291040Sarr					if (modlist_lookup(modname,
152391040Sarr					    nver) != NULL) {
152491040Sarr						printf("module %s already"
152591040Sarr						    " present!\n", modname);
1526160244Sjhb						TAILQ_REMOVE(&loaded_files,
1527160244Sjhb						    lf, loaded);
1528132117Sphk						linker_file_unload(lf,
1529132117Sphk						    LINKER_UNLOAD_FORCE);
153091040Sarr						/* we changed tailq next ptr */
153191068Sarr						goto restart;
153291040Sarr					}
153391040Sarr					modlist_newmodule(modname, nver, lf);
153491040Sarr				}
153591040Sarr			}
153691040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
153791040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
153891040Sarr			/*
153991040Sarr			 * Since we provided modules, we need to restart the
154091040Sarr			 * sort so that the previous files that depend on us
154191040Sarr			 * have a chance. Also, we've busted the tailq next
154291040Sarr			 * pointer with the REMOVE.
154391040Sarr			 */
154491040Sarr			goto restart;
154559751Speter		}
154659751Speter	}
154791040Sarr
154859751Speter	/*
154991040Sarr	 * At this point, we check to see what could not be resolved..
155059751Speter	 */
1551160242Sjhb	while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1552160242Sjhb		TAILQ_REMOVE(&loaded_files, lf, loaded);
155391040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1554132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
155540159Speter	}
155659751Speter
155778161Speter	/*
155891040Sarr	 * We made it. Finish off the linking in the order we determined.
155978161Speter	 */
1560160244Sjhb	TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
156191040Sarr		if (linker_kernel_file) {
156291040Sarr			linker_kernel_file->refs++;
156391040Sarr			error = linker_file_add_dependency(lf,
156491040Sarr			    linker_kernel_file);
156591040Sarr			if (error)
156691040Sarr				panic("cannot add dependency");
156791040Sarr		}
156891040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
156991040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
157091040Sarr		    &stop, NULL);
157191040Sarr		if (!error) {
157291040Sarr			for (mdp = start; mdp < stop; mdp++) {
1573109605Sjake				mp = *mdp;
157491040Sarr				if (mp->md_type != MDT_DEPEND)
157591040Sarr					continue;
1576109605Sjake				modname = mp->md_cval;
1577109605Sjake				verinfo = mp->md_data;
157891040Sarr				mod = modlist_lookup2(modname, verinfo);
1579151484Sjdp				/* Don't count self-dependencies */
1580151484Sjdp				if (lf == mod->container)
1581151484Sjdp					continue;
158291040Sarr				mod->container->refs++;
158391040Sarr				error = linker_file_add_dependency(lf,
158491040Sarr				    mod->container);
158591040Sarr				if (error)
158691040Sarr					panic("cannot add dependency");
158791040Sarr			}
158891040Sarr		}
158991040Sarr		/*
159091040Sarr		 * Now do relocation etc using the symbol search paths
159191040Sarr		 * established by the dependencies
159291040Sarr		 */
159391040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
159491040Sarr		if (error) {
1595160244Sjhb			TAILQ_REMOVE(&depended_files, lf, loaded);
159691040Sarr			printf("KLD file %s - could not finalize loading\n",
159791040Sarr			    lf->filename);
1598132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
159991040Sarr			continue;
160091040Sarr		}
160191040Sarr		linker_file_register_modules(lf);
160291040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
160391040Sarr		    &si_stop, NULL) == 0)
160491040Sarr			sysinit_add(si_start, si_stop);
160591040Sarr		linker_file_register_sysctls(lf);
160691040Sarr		lf->flags |= LINKER_FILE_LINKED;
160759751Speter	}
160891040Sarr	/* woohoo! we made it! */
160940159Speter}
161040159Speter
1611177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
161240159Speter
161340159Speter/*
161440159Speter * Search for a not-loaded module by name.
1615159840Sjhb *
161640159Speter * Modules may be found in the following locations:
1617159840Sjhb *
161891040Sarr * - preloaded (result is just the module name) - on disk (result is full path
161991040Sarr * to module)
1620159840Sjhb *
162191040Sarr * If the module name is qualified in any way (contains path, etc.) the we
162291040Sarr * simply return a copy of it.
1623159840Sjhb *
162440159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
162540159Speter * character as a separator to be consistent with the bootloader.
162640159Speter */
162740159Speter
162883321Speterstatic char linker_hintfile[] = "linker.hints";
1629111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
163040159Speter
163140159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
163291040Sarr    sizeof(linker_path), "module load search path");
163340159Speter
163477843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
163570417Speter
163659751Speterstatic char *linker_ext_list[] = {
163783321Speter	"",
163859751Speter	".ko",
163959751Speter	NULL
164059751Speter};
164159751Speter
164283321Speter/*
164391040Sarr * Check if file actually exists either with or without extension listed in
164491040Sarr * the linker_ext_list. (probably should be generic for the rest of the
164591040Sarr * kernel)
164683321Speter */
164759751Speterstatic char *
164891040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
164991040Sarr    int namelen, struct vattr *vap)
165040159Speter{
165191040Sarr	struct nameidata nd;
165291040Sarr	struct thread *td = curthread;	/* XXX */
165391040Sarr	char *result, **cpp, *sep;
1654159808Sjhb	int error, len, extlen, reclen, flags, vfslocked;
165591040Sarr	enum vtype type;
165640159Speter
165791040Sarr	extlen = 0;
165891040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
165991040Sarr		len = strlen(*cpp);
166091040Sarr		if (len > extlen)
166191040Sarr			extlen = len;
166291040Sarr	}
166391040Sarr	extlen++;		/* trailing '\0' */
166491040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
166583321Speter
166691040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1667111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
166891040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
166991040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
167091040Sarr		    namelen, name, *cpp);
167191040Sarr		/*
167291040Sarr		 * Attempt to open the file, and return the path if
167391040Sarr		 * we succeed and it's a regular file.
167491040Sarr		 */
1675159808Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td);
167691040Sarr		flags = FREAD;
1677170152Skib		error = vn_open(&nd, &flags, 0, NULL);
167891040Sarr		if (error == 0) {
1679159808Sjhb			vfslocked = NDHASGIANT(&nd);
168091040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
168191040Sarr			type = nd.ni_vp->v_type;
168291040Sarr			if (vap)
1683182371Sattilio				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1684175294Sattilio			VOP_UNLOCK(nd.ni_vp, 0);
168591406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
1686159808Sjhb			VFS_UNLOCK_GIANT(vfslocked);
168791040Sarr			if (type == VREG)
168891040Sarr				return (result);
168991040Sarr		}
169083321Speter	}
169191040Sarr	free(result, M_LINKER);
169291040Sarr	return (NULL);
169383321Speter}
169483321Speter
169591040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
169683321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
169783321Speter
169883321Speter/*
169991040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
170091040Sarr * version specification is available, then try to find the best KLD.
170183321Speter * Otherwise just find the latest one.
170283321Speter */
170383321Speterstatic char *
170491040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
170591040Sarr    int modnamelen, struct mod_depend *verinfo)
170683321Speter{
170791040Sarr	struct thread *td = curthread;	/* XXX */
170891406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
170991040Sarr	struct nameidata nd;
171091040Sarr	struct vattr vattr, mattr;
171191040Sarr	u_char *hints = NULL;
171291040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
171391040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1714159808Sjhb	int vfslocked = 0;
171583321Speter
171691040Sarr	result = NULL;
171791040Sarr	bestver = found = 0;
171883321Speter
171991040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
172091040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
172191040Sarr	    strlen(sep) + 1;
1722111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
172391040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
172491040Sarr	    linker_hintfile);
172583321Speter
1726159808Sjhb	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td);
172791040Sarr	flags = FREAD;
1728170152Skib	error = vn_open(&nd, &flags, 0, NULL);
172991040Sarr	if (error)
173091040Sarr		goto bad;
1731159808Sjhb	vfslocked = NDHASGIANT(&nd);
173291040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
173391040Sarr	if (nd.ni_vp->v_type != VREG)
173491040Sarr		goto bad;
173591040Sarr	best = cp = NULL;
1736182371Sattilio	error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
173791040Sarr	if (error)
173891040Sarr		goto bad;
173991040Sarr	/*
174091040Sarr	 * XXX: we need to limit this number to some reasonable value
174191040Sarr	 */
174291040Sarr	if (vattr.va_size > 100 * 1024) {
174391040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
174491040Sarr		goto bad;
174591040Sarr	}
1746111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
174791040Sarr	if (hints == NULL)
174891040Sarr		goto bad;
174991068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1750101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
175191040Sarr	if (error)
175291040Sarr		goto bad;
1753175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
175491040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
1755159808Sjhb	VFS_UNLOCK_GIANT(vfslocked);
175691040Sarr	nd.ni_vp = NULL;
175791040Sarr	if (reclen != 0) {
175891040Sarr		printf("can't read %d\n", reclen);
175991040Sarr		goto bad;
176091040Sarr	}
176191040Sarr	intp = (int *)hints;
176283321Speter	ival = *intp++;
176391040Sarr	if (ival != LINKER_HINTS_VERSION) {
176491040Sarr		printf("hints file version mismatch %d\n", ival);
176591040Sarr		goto bad;
176683321Speter	}
176791040Sarr	bufend = hints + vattr.va_size;
176891040Sarr	recptr = (u_char *)intp;
176991040Sarr	clen = blen = 0;
177091040Sarr	while (recptr < bufend && !found) {
177191040Sarr		intp = (int *)recptr;
177291040Sarr		reclen = *intp++;
177391040Sarr		ival = *intp++;
177491040Sarr		cp = (char *)intp;
177591040Sarr		switch (ival) {
177691040Sarr		case MDT_VERSION:
177791040Sarr			clen = *cp++;
177891040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
177991040Sarr				break;
178091040Sarr			cp += clen;
178191040Sarr			INT_ALIGN(hints, cp);
178291040Sarr			ival = *(int *)cp;
178391040Sarr			cp += sizeof(int);
178491040Sarr			clen = *cp++;
178591040Sarr			if (verinfo == NULL ||
178691040Sarr			    ival == verinfo->md_ver_preferred) {
178791040Sarr				found = 1;
178891040Sarr				break;
178991040Sarr			}
179091040Sarr			if (ival >= verinfo->md_ver_minimum &&
179191040Sarr			    ival <= verinfo->md_ver_maximum &&
179291040Sarr			    ival > bestver) {
179391040Sarr				bestver = ival;
179491040Sarr				best = cp;
179591040Sarr				blen = clen;
179691040Sarr			}
179791040Sarr			break;
179891040Sarr		default:
179991040Sarr			break;
180091040Sarr		}
180191040Sarr		recptr += reclen + sizeof(int);
180291040Sarr	}
180383321Speter	/*
180491040Sarr	 * Finally check if KLD is in the place
180583321Speter	 */
180691040Sarr	if (found)
180791040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
180891040Sarr	else if (best)
180991040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
181091040Sarr
181191040Sarr	/*
181291040Sarr	 * KLD is newer than hints file. What we should do now?
181391040Sarr	 */
181491040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
181591040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
181691040Sarr		    " file\n", result);
181783321Speterbad:
1818105167Sphk	free(pathbuf, M_LINKER);
181991040Sarr	if (hints)
182091040Sarr		free(hints, M_TEMP);
182199553Sjeff	if (nd.ni_vp != NULL) {
1822175294Sattilio		VOP_UNLOCK(nd.ni_vp, 0);
182391040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
1824159808Sjhb		VFS_UNLOCK_GIANT(vfslocked);
182599553Sjeff	}
182691040Sarr	/*
182791040Sarr	 * If nothing found or hints is absent - fallback to the old
182891040Sarr	 * way by using "kldname[.ko]" as module name.
182991040Sarr	 */
183091040Sarr	if (!found && !bestver && result == NULL)
183191040Sarr		result = linker_lookup_file(path, pathlen, modname,
183291040Sarr		    modnamelen, NULL);
183391040Sarr	return (result);
183483321Speter}
183583321Speter
183683321Speter/*
183783321Speter * Lookup KLD which contains requested module in the all directories.
183883321Speter */
183983321Speterstatic char *
184083321Speterlinker_search_module(const char *modname, int modnamelen,
184191040Sarr    struct mod_depend *verinfo)
184283321Speter{
184391040Sarr	char *cp, *ep, *result;
184483321Speter
184591040Sarr	/*
184691040Sarr	 * traverse the linker path
184791040Sarr	 */
184891040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
184991040Sarr		/* find the end of this component */
185091040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
185191068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
185291068Sarr		    modnamelen, verinfo);
185391040Sarr		if (result != NULL)
185491040Sarr			return (result);
185591040Sarr		if (*ep == 0)
185691040Sarr			break;
185791040Sarr	}
185891040Sarr	return (NULL);
185983321Speter}
186083321Speter
186183321Speter/*
186283321Speter * Search for module in all directories listed in the linker_path.
186383321Speter */
186483321Speterstatic char *
186583321Speterlinker_search_kld(const char *name)
186683321Speter{
1867158972Sdelphij	char *cp, *ep, *result;
1868158972Sdelphij	int len;
186983321Speter
187091040Sarr	/* qualified at all? */
187191040Sarr	if (index(name, '/'))
187291040Sarr		return (linker_strdup(name));
187340159Speter
187491040Sarr	/* traverse the linker path */
187591040Sarr	len = strlen(name);
187691040Sarr	for (ep = linker_path; *ep; ep++) {
187791040Sarr		cp = ep;
187891040Sarr		/* find the end of this component */
187991040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
188091040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
188191040Sarr		if (result != NULL)
188291040Sarr			return (result);
188391040Sarr	}
188491040Sarr	return (NULL);
188540159Speter}
188659751Speter
188759751Speterstatic const char *
188891040Sarrlinker_basename(const char *path)
188959751Speter{
189091040Sarr	const char *filename;
189159751Speter
189291040Sarr	filename = rindex(path, '/');
189391040Sarr	if (filename == NULL)
189491040Sarr		return path;
189591040Sarr	if (filename[1])
189691040Sarr		filename++;
189791040Sarr	return (filename);
189859751Speter}
189959751Speter
1900157144Sjkoshy#ifdef HWPMC_HOOKS
1901157144Sjkoshy
1902159797Sjhbstruct hwpmc_context {
1903159797Sjhb	int	nobjects;
1904159797Sjhb	int	nmappings;
1905159797Sjhb	struct pmckern_map_in *kobase;
1906159797Sjhb};
1907159797Sjhb
1908159797Sjhbstatic int
1909159797Sjhblinker_hwpmc_list_object(linker_file_t lf, void *arg)
1910159797Sjhb{
1911159797Sjhb	struct hwpmc_context *hc;
1912159797Sjhb
1913159797Sjhb	hc = arg;
1914159797Sjhb
1915159797Sjhb	/* If we run out of mappings, fail. */
1916159797Sjhb	if (hc->nobjects >= hc->nmappings)
1917159797Sjhb		return (1);
1918159797Sjhb
1919159797Sjhb	/* Save the info for this linker file. */
1920159797Sjhb	hc->kobase[hc->nobjects].pm_file = lf->filename;
1921159797Sjhb	hc->kobase[hc->nobjects].pm_address = (uintptr_t)lf->address;
1922159797Sjhb	hc->nobjects++;
1923159797Sjhb	return (0);
1924159797Sjhb}
1925159797Sjhb
192659751Speter/*
1927157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1928157144Sjkoshy */
1929157144Sjkoshyvoid *
1930157144Sjkoshylinker_hwpmc_list_objects(void)
1931157144Sjkoshy{
1932159797Sjhb	struct hwpmc_context hc;
1933157144Sjkoshy
1934159797Sjhb	hc.nmappings = 15;	/* a reasonable default */
1935157144Sjkoshy
1936157144Sjkoshy retry:
1937157144Sjkoshy	/* allocate nmappings+1 entries */
1938184214Sdes	hc.kobase = malloc((hc.nmappings + 1) * sizeof(struct pmckern_map_in),
1939184214Sdes	    M_LINKER, M_WAITOK | M_ZERO);
1940157144Sjkoshy
1941159797Sjhb	hc.nobjects = 0;
1942159797Sjhb	if (linker_file_foreach(linker_hwpmc_list_object, &hc) != 0) {
1943159797Sjhb		hc.nmappings = hc.nobjects;
1944184205Sdes		free(hc.kobase, M_LINKER);
1945157144Sjkoshy		goto retry;
1946157144Sjkoshy	}
1947157144Sjkoshy
1948159797Sjhb	KASSERT(hc.nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
1949159797Sjhb		"objects?"));
1950157144Sjkoshy
1951157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1952159797Sjhb	KASSERT(hc.kobase[hc.nobjects].pm_file == NULL,
1953157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1954157144Sjkoshy
1955159797Sjhb	return ((void *)hc.kobase);
1956157144Sjkoshy}
1957157144Sjkoshy#endif
1958157144Sjkoshy
1959157144Sjkoshy/*
196091040Sarr * Find a file which contains given module and load it, if "parent" is not
196191040Sarr * NULL, register a reference to it.
196259751Speter */
1963159796Sjhbstatic int
196483321Speterlinker_load_module(const char *kldname, const char *modname,
196591040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
196691040Sarr    struct linker_file **lfpp)
196759751Speter{
196891040Sarr	linker_file_t lfdep;
196991040Sarr	const char *filename;
197091040Sarr	char *pathname;
197191040Sarr	int error;
197259751Speter
1973159845Sjhb	KLD_LOCK_ASSERT();
197491040Sarr	if (modname == NULL) {
197591040Sarr		/*
197691040Sarr 		 * We have to load KLD
197791040Sarr 		 */
197891068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
197991068Sarr		    " is not NULL"));
198091040Sarr		pathname = linker_search_kld(kldname);
198191040Sarr	} else {
198291040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
198391040Sarr			return (EEXIST);
198494322Sbrian		if (kldname != NULL)
198594322Sbrian			pathname = linker_strdup(kldname);
198695488Sbrian		else if (rootvnode == NULL)
198794322Sbrian			pathname = NULL;
198894322Sbrian		else
198991040Sarr			/*
199091040Sarr			 * Need to find a KLD with required module
199191040Sarr			 */
199291040Sarr			pathname = linker_search_module(modname,
199391040Sarr			    strlen(modname), verinfo);
199491040Sarr	}
199591040Sarr	if (pathname == NULL)
199691040Sarr		return (ENOENT);
199791040Sarr
199883321Speter	/*
199991040Sarr	 * Can't load more than one file with the same basename XXX:
200091040Sarr	 * Actually it should be possible to have multiple KLDs with
200191040Sarr	 * the same basename but different path because they can
200291040Sarr	 * provide different versions of the same modules.
200383321Speter	 */
200491040Sarr	filename = linker_basename(pathname);
2005159792Sjhb	if (linker_find_file_by_name(filename))
200691040Sarr		error = EEXIST;
2007159792Sjhb	else do {
200891040Sarr		error = linker_load_file(pathname, &lfdep);
200991040Sarr		if (error)
201091040Sarr			break;
201191040Sarr		if (modname && verinfo &&
201291040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
2013132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
201491040Sarr			error = ENOENT;
201591040Sarr			break;
201691040Sarr		}
201791040Sarr		if (parent) {
201891040Sarr			error = linker_file_add_dependency(parent, lfdep);
201991040Sarr			if (error)
202091040Sarr				break;
202191040Sarr		}
202291040Sarr		if (lfpp)
202391040Sarr			*lfpp = lfdep;
202491040Sarr	} while (0);
2025159791Sjhb	free(pathname, M_LINKER);
202691040Sarr	return (error);
202759751Speter}
202859751Speter
202959751Speter/*
203091040Sarr * This routine is responsible for finding dependencies of userland initiated
203191040Sarr * kldload(2)'s of files.
203259751Speter */
203359751Speterint
203486469Siedowselinker_load_dependencies(linker_file_t lf)
203559751Speter{
203691040Sarr	linker_file_t lfdep;
203791040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
203891040Sarr	struct mod_metadata *mp, *nmp;
203991040Sarr	struct mod_depend *verinfo;
204091040Sarr	modlist_t mod;
204191040Sarr	const char *modname, *nmodname;
204292032Sdwmalone	int ver, error = 0, count;
204359751Speter
204491040Sarr	/*
204591040Sarr	 * All files are dependant on /kernel.
204691040Sarr	 */
2047159845Sjhb	KLD_LOCK_ASSERT();
204891040Sarr	if (linker_kernel_file) {
204991040Sarr		linker_kernel_file->refs++;
205091040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
205191040Sarr		if (error)
205291040Sarr			return (error);
205359751Speter	}
205491040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
205591040Sarr	    &count) != 0)
205691040Sarr		return (0);
205791040Sarr	for (mdp = start; mdp < stop; mdp++) {
2058109605Sjake		mp = *mdp;
205991040Sarr		if (mp->md_type != MDT_VERSION)
206091040Sarr			continue;
2061109605Sjake		modname = mp->md_cval;
2062109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
206391040Sarr		mod = modlist_lookup(modname, ver);
206491040Sarr		if (mod != NULL) {
206591040Sarr			printf("interface %s.%d already present in the KLD"
206691040Sarr			    " '%s'!\n", modname, ver,
206791040Sarr			    mod->container->filename);
206891040Sarr			return (EEXIST);
206991040Sarr		}
207091040Sarr	}
207174642Sbp
207291040Sarr	for (mdp = start; mdp < stop; mdp++) {
2073109605Sjake		mp = *mdp;
207491040Sarr		if (mp->md_type != MDT_DEPEND)
207591040Sarr			continue;
2076109605Sjake		modname = mp->md_cval;
2077109605Sjake		verinfo = mp->md_data;
207891040Sarr		nmodname = NULL;
207991040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
2080109605Sjake			nmp = *nmdp;
208191040Sarr			if (nmp->md_type != MDT_VERSION)
208291040Sarr				continue;
2083109605Sjake			nmodname = nmp->md_cval;
208492032Sdwmalone			if (strcmp(modname, nmodname) == 0)
208591040Sarr				break;
208691040Sarr		}
208791040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
208891040Sarr			continue;
208991040Sarr		mod = modlist_lookup2(modname, verinfo);
209091040Sarr		if (mod) {	/* woohoo, it's loaded already */
209191040Sarr			lfdep = mod->container;
209291040Sarr			lfdep->refs++;
209391040Sarr			error = linker_file_add_dependency(lf, lfdep);
209491040Sarr			if (error)
209591040Sarr				break;
209691040Sarr			continue;
209791040Sarr		}
209891040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
209991040Sarr		if (error) {
210091040Sarr			printf("KLD %s: depends on %s - not available\n",
210191040Sarr			    lf->filename, modname);
210291040Sarr			break;
210391040Sarr		}
210459751Speter	}
210559751Speter
210691040Sarr	if (error)
210791040Sarr		return (error);
210891040Sarr	linker_addmodules(lf, start, stop, 0);
210991040Sarr	return (error);
211059751Speter}
211185736Sgreen
211285736Sgreenstatic int
211385736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
211485736Sgreen{
211585736Sgreen	struct sysctl_req *req;
211685736Sgreen
211785736Sgreen	req = opaque;
211885736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
211985736Sgreen}
212085736Sgreen
212185736Sgreen/*
212285736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
212385736Sgreen * in the kernel.
212485736Sgreen */
212585736Sgreenstatic int
212685736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
212785736Sgreen{
212885736Sgreen	linker_file_t lf;
212985736Sgreen	int error;
213085736Sgreen
2131107089Srwatson#ifdef MAC
2132172930Srwatson	error = mac_kld_check_stat(req->td->td_ucred);
2133107089Srwatson	if (error)
2134107089Srwatson		return (error);
2135107089Srwatson#endif
2136126253Struckman	error = sysctl_wire_old_buffer(req, 0);
2137126253Struckman	if (error != 0)
2138126253Struckman		return (error);
2139159845Sjhb	KLD_LOCK();
214085736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
214185736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
214285736Sgreen		    sysctl_kern_function_list_iterate, req);
214398452Sarr		if (error) {
2144159845Sjhb			KLD_UNLOCK();
214585736Sgreen			return (error);
214698452Sarr		}
214785736Sgreen	}
2148159845Sjhb	KLD_UNLOCK();
214985736Sgreen	return (SYSCTL_OUT(req, "", 1));
215085736Sgreen}
215185736Sgreen
215285736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
215391040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2154