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: stable/10/sys/kern/kern_linker.c 355419 2019-12-05 14:53:46Z hselasky $");
29116182Sobrien
3040159Speter#include "opt_ddb.h"
31227151Sfjoe#include "opt_kld.h"
32157144Sjkoshy#include "opt_hwpmc_hooks.h"
3340159Speter
3425537Sdfr#include <sys/param.h>
3525537Sdfr#include <sys/kernel.h>
3625537Sdfr#include <sys/systm.h>
3725537Sdfr#include <sys/malloc.h>
3825537Sdfr#include <sys/sysproto.h>
3925537Sdfr#include <sys/sysent.h>
40164033Srwatson#include <sys/priv.h>
4125537Sdfr#include <sys/proc.h>
4225537Sdfr#include <sys/lock.h>
4382749Sdillon#include <sys/mutex.h>
4492547Sarr#include <sys/sx.h>
4525537Sdfr#include <sys/module.h>
46159808Sjhb#include <sys/mount.h>
4725537Sdfr#include <sys/linker.h>
48254266Smarkj#include <sys/eventhandler.h>
4940159Speter#include <sys/fcntl.h>
50192895Sjamie#include <sys/jail.h>
5140159Speter#include <sys/libkern.h>
5240159Speter#include <sys/namei.h>
5340159Speter#include <sys/vnode.h>
54159588Sjhb#include <sys/syscallsubr.h>
5540159Speter#include <sys/sysctl.h>
5625537Sdfr
57196019Srwatson#include <net/vnet.h>
58196019Srwatson
59163606Srwatson#include <security/mac/mac_framework.h>
60163606Srwatson
6159603Sdfr#include "linker_if.h"
6259603Sdfr
63157144Sjkoshy#ifdef HWPMC_HOOKS
64157144Sjkoshy#include <sys/pmckern.h>
65157144Sjkoshy#endif
66157144Sjkoshy
6740961Speter#ifdef KLD_DEBUG
6840961Speterint kld_debug = 0;
69232999SaeSYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW | CTLFLAG_TUN,
70232999Sae    &kld_debug, 0, "Set various levels of KLD debug");
71232997SaeTUNABLE_INT("debug.kld_debug", &kld_debug);
7240961Speter#endif
7340961Speter
74294283Sjhb/* These variables are used by kernel debuggers to enumerate loaded files. */
75294283Sjhbconst int kld_off_address = offsetof(struct linker_file, address);
76294283Sjhbconst int kld_off_filename = offsetof(struct linker_file, filename);
77294283Sjhbconst int kld_off_pathname = offsetof(struct linker_file, pathname);
78294283Sjhbconst int kld_off_next = offsetof(struct linker_file, link.tqe_next);
79294283Sjhb
8091040Sarr/*
8191040Sarr * static char *linker_search_path(const char *name, struct mod_depend
8291040Sarr * *verinfo);
8391040Sarr */
8491040Sarrstatic const char 	*linker_basename(const char *path);
8559751Speter
86159800Sjhb/*
87159800Sjhb * Find a currently loaded file given its filename.
88159800Sjhb */
89159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
90159800Sjhb
91159800Sjhb/*
92159800Sjhb * Find a currently loaded file given its file id.
93159800Sjhb */
94159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
95159800Sjhb
9678161Speter/* Metadata from the static kernel */
9778161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
9878161Speter
9959751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
10059751Speter
10140906Speterlinker_file_t linker_kernel_file;
10231324Sbde
103159845Sjhbstatic struct sx kld_sx;	/* kernel linker lock */
10498452Sarr
105172862Sjb/*
106172862Sjb * Load counter used by clients to determine if a linker file has been
107172862Sjb * re-loaded. This counter is incremented for each file load.
108172862Sjb */
109172862Sjbstatic int loadcnt;
110172862Sjb
11125537Sdfrstatic linker_class_list_t classes;
11250068Sgrogstatic linker_file_list_t linker_files;
11325537Sdfrstatic int next_file_id = 1;
11498452Sarrstatic int linker_no_more_classes = 0;
11525537Sdfr
11686553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
11791040Sarr	linker_file_t lftmp;						\
11886553Sarr									\
119254810Smarkj	if (!cold)							\
120254810Smarkj		sx_assert(&kld_sx, SA_XLOCKED);				\
12186553Sarrretry:									\
12291040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
12391040Sarr		if (next_file_id == lftmp->id) {			\
12491040Sarr			next_file_id++;					\
12591040Sarr			goto retry;					\
12691040Sarr		}							\
12791040Sarr	}								\
12891040Sarr	(a) = next_file_id;						\
12986553Sarr} while(0)
13086553Sarr
13186553Sarr
13259751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
13360938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
13459751Speterstruct modlist {
13591040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
13691040Sarr	linker_file_t   container;
13791040Sarr	const char 	*name;
13891040Sarr	int             version;
13959751Speter};
14091040Sarrtypedef struct modlist *modlist_t;
14191040Sarrstatic modlisthead_t found_modules;
14259751Speter
143159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
144159796Sjhb		    linker_file_t dep);
145159845Sjhbstatic caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
146159845Sjhb		    const char* name, int deps);
147159796Sjhbstatic int	linker_load_module(const char *kldname,
148159796Sjhb		    const char *modname, struct linker_file *parent,
149159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
150159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
15194321Sbrian
15225537Sdfrstatic void
15391040Sarrlinker_init(void *arg)
15425537Sdfr{
15591040Sarr
156159845Sjhb	sx_init(&kld_sx, "kernel linker");
15791040Sarr	TAILQ_INIT(&classes);
15891040Sarr	TAILQ_INIT(&linker_files);
15925537Sdfr}
16025537Sdfr
161177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
16225537Sdfr
16398452Sarrstatic void
16498452Sarrlinker_stop_class_add(void *arg)
16598452Sarr{
16698452Sarr
16798452Sarr	linker_no_more_classes = 1;
16898452Sarr}
16998452Sarr
170177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL);
17198452Sarr
17225537Sdfrint
17359603Sdfrlinker_add_class(linker_class_t lc)
17425537Sdfr{
17591040Sarr
17698452Sarr	/*
177144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
178144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
179144443Sjhb	 * ops from being freed.
18098452Sarr	 */
18198452Sarr	if (linker_no_more_classes == 1)
18298452Sarr		return (EPERM);
18391040Sarr	kobj_class_compile((kobj_class_t) lc);
184144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
18591040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
18691040Sarr	return (0);
18725537Sdfr}
18825537Sdfr
18925537Sdfrstatic void
19025537Sdfrlinker_file_sysinit(linker_file_t lf)
19125537Sdfr{
19291040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
19325537Sdfr
19491040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
19591040Sarr	    lf->filename));
19625537Sdfr
197254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
198254811Smarkj
19991040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
20091040Sarr		return;
20191040Sarr	/*
20291040Sarr	 * Perform a bubble sort of the system initialization objects by
20391040Sarr	 * their subsystem (primary key) and order (secondary key).
204159840Sjhb	 *
20591040Sarr	 * Since some things care about execution order, this is the operation
20691040Sarr	 * which ensures continued function.
20791040Sarr	 */
20891040Sarr	for (sipp = start; sipp < stop; sipp++) {
20991040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
21091040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
21191040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
21291040Sarr			    (*sipp)->order <= (*xipp)->order))
21391040Sarr				continue;	/* skip */
21491040Sarr			save = *sipp;
21591040Sarr			*sipp = *xipp;
21691040Sarr			*xipp = save;
21791040Sarr		}
21825537Sdfr	}
21925537Sdfr
22091040Sarr	/*
22191040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
22291040Sarr	 * Perform each task, and continue on to the next task.
22391040Sarr	 */
224254811Smarkj	sx_xunlock(&kld_sx);
225160142Sjhb	mtx_lock(&Giant);
22691040Sarr	for (sipp = start; sipp < stop; sipp++) {
22791040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
22891040Sarr			continue;	/* skip dummy task(s) */
22925537Sdfr
23091040Sarr		/* Call function */
23191040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
23291040Sarr	}
233160142Sjhb	mtx_unlock(&Giant);
234254811Smarkj	sx_xlock(&kld_sx);
23525537Sdfr}
23625537Sdfr
23741055Speterstatic void
23841055Speterlinker_file_sysuninit(linker_file_t lf)
23941055Speter{
24091040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
24141055Speter
24291040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
24391040Sarr	    lf->filename));
24441055Speter
245254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
246254811Smarkj
24791068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
24891040Sarr	    NULL) != 0)
24991040Sarr		return;
25041055Speter
25191040Sarr	/*
25291040Sarr	 * Perform a reverse bubble sort of the system initialization objects
25391040Sarr	 * by their subsystem (primary key) and order (secondary key).
254159840Sjhb	 *
25591040Sarr	 * Since some things care about execution order, this is the operation
25691040Sarr	 * which ensures continued function.
25791040Sarr	 */
25891040Sarr	for (sipp = start; sipp < stop; sipp++) {
25991040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
26091040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
26191040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
26291040Sarr			    (*sipp)->order >= (*xipp)->order))
26391040Sarr				continue;	/* skip */
26491040Sarr			save = *sipp;
26591040Sarr			*sipp = *xipp;
26691040Sarr			*xipp = save;
26791040Sarr		}
26841055Speter	}
26941055Speter
27091040Sarr	/*
27191040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
27291040Sarr	 * Perform each task, and continue on to the next task.
27391040Sarr	 */
274254811Smarkj	sx_xunlock(&kld_sx);
275160142Sjhb	mtx_lock(&Giant);
27691040Sarr	for (sipp = start; sipp < stop; sipp++) {
27791040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
27891040Sarr			continue;	/* skip dummy task(s) */
27941055Speter
28091040Sarr		/* Call function */
28191040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
28291040Sarr	}
283160142Sjhb	mtx_unlock(&Giant);
284254811Smarkj	sx_xlock(&kld_sx);
28541055Speter}
28641055Speter
28744078Sdfrstatic void
288324749Savglinker_file_register_sysctls(linker_file_t lf, bool enable)
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
296254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
297254811Smarkj
29891040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
29991040Sarr		return;
30044078Sdfr
301254811Smarkj	sx_xunlock(&kld_sx);
302188232Sjhb	sysctl_lock();
303324749Savg	for (oidp = start; oidp < stop; oidp++) {
304324749Savg		if (enable)
305324749Savg			sysctl_register_oid(*oidp);
306324749Savg		else
307324749Savg			sysctl_register_disabled_oid(*oidp);
308324749Savg	}
309324749Savg	sysctl_unlock();
310324749Savg	sx_xlock(&kld_sx);
311324749Savg}
312324749Savg
313324749Savgstatic void
314324749Savglinker_file_enable_sysctls(linker_file_t lf)
315324749Savg{
316324749Savg	struct sysctl_oid **start, **stop, **oidp;
317324749Savg
318324749Savg	KLD_DPF(FILE,
319324749Savg	    ("linker_file_enable_sysctls: enable SYSCTLs for %s\n",
320324749Savg	    lf->filename));
321324749Savg
322324749Savg	sx_assert(&kld_sx, SA_XLOCKED);
323324749Savg
324324749Savg	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
325324749Savg		return;
326324749Savg
327324749Savg	sx_xunlock(&kld_sx);
328324749Savg	sysctl_lock();
32991040Sarr	for (oidp = start; oidp < stop; oidp++)
330324749Savg		sysctl_enable_oid(*oidp);
331188232Sjhb	sysctl_unlock();
332254811Smarkj	sx_xlock(&kld_sx);
33344078Sdfr}
33444078Sdfr
33544078Sdfrstatic void
33644078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
33744078Sdfr{
33891040Sarr	struct sysctl_oid **start, **stop, **oidp;
33944078Sdfr
340233295Sae	KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs"
34191040Sarr	    " for %s\n", lf->filename));
34244078Sdfr
343254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
344254811Smarkj
34591040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
34691040Sarr		return;
34744078Sdfr
348254811Smarkj	sx_xunlock(&kld_sx);
349188232Sjhb	sysctl_lock();
35091040Sarr	for (oidp = start; oidp < stop; oidp++)
35191040Sarr		sysctl_unregister_oid(*oidp);
352188232Sjhb	sysctl_unlock();
353254811Smarkj	sx_xlock(&kld_sx);
35444078Sdfr}
35544078Sdfr
35659751Speterstatic int
35759751Speterlinker_file_register_modules(linker_file_t lf)
35859751Speter{
35991040Sarr	struct mod_metadata **start, **stop, **mdp;
36091040Sarr	const moduledata_t *moddata;
361146733Spjd	int first_error, error;
36259751Speter
36391040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
36491040Sarr	    " in %s\n", lf->filename));
36559751Speter
366254811Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
367254811Smarkj
36891068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
369159841Sjhb	    &stop, NULL) != 0) {
37091040Sarr		/*
37191040Sarr		 * This fallback should be unnecessary, but if we get booted
37291040Sarr		 * from boot2 instead of loader and we are missing our
37391040Sarr		 * metadata then we have to try the best we can.
37491040Sarr		 */
37591040Sarr		if (lf == linker_kernel_file) {
37691040Sarr			start = SET_BEGIN(modmetadata_set);
37791040Sarr			stop = SET_LIMIT(modmetadata_set);
37891040Sarr		} else
37991040Sarr			return (0);
38078161Speter	}
381146733Spjd	first_error = 0;
38291040Sarr	for (mdp = start; mdp < stop; mdp++) {
38391040Sarr		if ((*mdp)->md_type != MDT_MODULE)
38491040Sarr			continue;
38591040Sarr		moddata = (*mdp)->md_data;
38691040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
38791040Sarr		    moddata->name, lf->filename));
38891040Sarr		error = module_register(moddata, lf);
389146730Spjd		if (error) {
39091068Sarr			printf("Module %s failed to register: %d\n",
39191040Sarr			    moddata->name, error);
392146733Spjd			if (first_error == 0)
393146733Spjd				first_error = error;
394146730Spjd		}
39559751Speter	}
396146733Spjd	return (first_error);
39759751Speter}
39859751Speter
39959751Speterstatic void
40059751Speterlinker_init_kernel_modules(void)
40159751Speter{
40291040Sarr
403254810Smarkj	sx_xlock(&kld_sx);
40491040Sarr	linker_file_register_modules(linker_kernel_file);
405254810Smarkj	sx_xunlock(&kld_sx);
40659751Speter}
40759751Speter
408177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules,
409177253Srwatson    0);
41059751Speter
411101241Smuxstatic int
41291040Sarrlinker_load_file(const char *filename, linker_file_t *result)
41325537Sdfr{
41491040Sarr	linker_class_t lc;
41591040Sarr	linker_file_t lf;
416234186Sjhb	int foundfile, error, modules;
41725537Sdfr
41891040Sarr	/* Refuse to load modules if securelevel raised */
419192895Sjamie	if (prison0.pr_securelevel > 0)
42091040Sarr		return (EPERM);
42162261Sarchie
422254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
42391040Sarr	lf = linker_find_file_by_name(filename);
42491040Sarr	if (lf) {
42591040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
42691040Sarr		    " incrementing refs\n", filename));
42791040Sarr		*result = lf;
42891040Sarr		lf->refs++;
429159585Sjhb		return (0);
43091040Sarr	}
43191040Sarr	foundfile = 0;
432159585Sjhb	error = 0;
43398452Sarr
43498452Sarr	/*
43598452Sarr	 * We do not need to protect (lock) classes here because there is
43698452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
43798452Sarr	 * and there is no class deregistration mechanism at this time.
43898452Sarr	 */
43991040Sarr	TAILQ_FOREACH(lc, &classes, link) {
44091040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
44191040Sarr		    filename));
44291040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
44391040Sarr		/*
44491040Sarr		 * If we got something other than ENOENT, then it exists but
44591040Sarr		 * we cannot load it for some other reason.
44691040Sarr		 */
44791040Sarr		if (error != ENOENT)
44891040Sarr			foundfile = 1;
44991040Sarr		if (lf) {
450146730Spjd			error = linker_file_register_modules(lf);
451146730Spjd			if (error == EEXIST) {
452146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
453159585Sjhb				return (error);
454146730Spjd			}
455234186Sjhb			modules = !TAILQ_EMPTY(&lf->modules);
456324749Savg			linker_file_register_sysctls(lf, false);
45791040Sarr			linker_file_sysinit(lf);
45891040Sarr			lf->flags |= LINKER_FILE_LINKED;
459234186Sjhb
460234186Sjhb			/*
461234186Sjhb			 * If all of the modules in this file failed
462234186Sjhb			 * to load, unload the file and return an
463234186Sjhb			 * error of ENOEXEC.
464234186Sjhb			 */
465234186Sjhb			if (modules && TAILQ_EMPTY(&lf->modules)) {
466234186Sjhb				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
467234186Sjhb				return (ENOEXEC);
468234186Sjhb			}
469324749Savg			linker_file_enable_sysctls(lf);
470262039Savg			EVENTHANDLER_INVOKE(kld_load, lf);
47191040Sarr			*result = lf;
472159585Sjhb			return (0);
47391040Sarr		}
47491040Sarr	}
47542755Speter	/*
47691040Sarr	 * Less than ideal, but tells the user whether it failed to load or
47791040Sarr	 * the module was not found.
47842755Speter	 */
479105337Ssam	if (foundfile) {
480188440Sattilio
481105337Ssam		/*
482188440Sattilio		 * If the file type has not been recognized by the last try
483188440Sattilio		 * printout a message before to fail.
484188440Sattilio		 */
485188440Sattilio		if (error == ENOSYS)
486188440Sattilio			printf("linker_load_file: Unsupported file type\n");
487188440Sattilio
488188440Sattilio		/*
489105337Ssam		 * Format not recognized or otherwise unloadable.
490105337Ssam		 * When loading a module that is statically built into
491105337Ssam		 * the kernel EEXIST percolates back up as the return
492105337Ssam		 * value.  Preserve this so that apps like sysinstall
493105337Ssam		 * can recognize this special case and not post bogus
494105337Ssam		 * dialog boxes.
495105337Ssam		 */
496105337Ssam		if (error != EEXIST)
497105337Ssam			error = ENOEXEC;
498105337Ssam	} else
49991068Sarr		error = ENOENT;		/* Nothing found */
50091040Sarr	return (error);
50125537Sdfr}
50225537Sdfr
50378413Sbrianint
50494321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
50594321Sbrian    linker_file_t *result)
50678413Sbrian{
50794321Sbrian	modlist_t mod;
508159804Sjhb	int error;
50994321Sbrian
510254810Smarkj	sx_xlock(&kld_sx);
51194321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
51294321Sbrian		*result = mod->container;
51394321Sbrian		(*result)->refs++;
514254810Smarkj		sx_xunlock(&kld_sx);
51594321Sbrian		return (0);
51694321Sbrian	}
51794321Sbrian
518159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
519254810Smarkj	sx_xunlock(&kld_sx);
520159804Sjhb	return (error);
52178413Sbrian}
52278413Sbrian
523159804Sjhbint
524159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
525159804Sjhb    linker_file_t lf)
526159804Sjhb{
527159804Sjhb	modlist_t mod;
528159804Sjhb	int error;
529159804Sjhb
530254810Smarkj	sx_xlock(&kld_sx);
531159804Sjhb	if (lf == NULL) {
532159804Sjhb		KASSERT(modname != NULL,
533159804Sjhb		    ("linker_release_module: no file or name"));
534159804Sjhb		mod = modlist_lookup2(modname, verinfo);
535159804Sjhb		if (mod == NULL) {
536254810Smarkj			sx_xunlock(&kld_sx);
537159804Sjhb			return (ESRCH);
538159804Sjhb		}
539159804Sjhb		lf = mod->container;
540159804Sjhb	} else
541159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
542159804Sjhb		    ("linker_release_module: both file and name"));
543159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
544254810Smarkj	sx_xunlock(&kld_sx);
545159804Sjhb	return (error);
546159804Sjhb}
547159804Sjhb
548159800Sjhbstatic linker_file_t
54991040Sarrlinker_find_file_by_name(const char *filename)
55025537Sdfr{
551159585Sjhb	linker_file_t lf;
55291040Sarr	char *koname;
55325537Sdfr
554111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
55591040Sarr	sprintf(koname, "%s.ko", filename);
55640861Speter
557254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
55891040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
55992032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
56091040Sarr			break;
56192032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
56291040Sarr			break;
56391040Sarr	}
564159585Sjhb	free(koname, M_LINKER);
56591040Sarr	return (lf);
56625537Sdfr}
56725537Sdfr
568159800Sjhbstatic linker_file_t
56925537Sdfrlinker_find_file_by_id(int fileid)
57025537Sdfr{
571159585Sjhb	linker_file_t lf;
572159845Sjhb
573254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
57491040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
575166921Sjhb		if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
57691040Sarr			break;
57791040Sarr	return (lf);
57825537Sdfr}
57925537Sdfr
580159797Sjhbint
581159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
582159797Sjhb{
583159797Sjhb	linker_file_t lf;
584159797Sjhb	int retval = 0;
585159797Sjhb
586254810Smarkj	sx_xlock(&kld_sx);
587159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
588159797Sjhb		retval = predicate(lf, context);
589159797Sjhb		if (retval != 0)
590159797Sjhb			break;
591159797Sjhb	}
592254810Smarkj	sx_xunlock(&kld_sx);
593159797Sjhb	return (retval);
594159797Sjhb}
595159797Sjhb
59625537Sdfrlinker_file_t
59791040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
59825537Sdfr{
59991040Sarr	linker_file_t lf;
60091040Sarr	const char *filename;
60125537Sdfr
602254810Smarkj	if (!cold)
603254810Smarkj		sx_assert(&kld_sx, SA_XLOCKED);
60491040Sarr	filename = linker_basename(pathname);
60540159Speter
606172862Sjb	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
607111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
60891040Sarr	if (lf == NULL)
609159585Sjhb		return (NULL);
61091040Sarr	lf->refs = 1;
61191040Sarr	lf->userrefs = 0;
61291040Sarr	lf->flags = 0;
613254396Smarkj	lf->filename = strdup(filename, M_LINKER);
614254396Smarkj	lf->pathname = strdup(pathname, M_LINKER);
61591040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
61691040Sarr	lf->ndeps = 0;
61791040Sarr	lf->deps = NULL;
618172862Sjb	lf->loadcnt = ++loadcnt;
61991040Sarr	STAILQ_INIT(&lf->common);
62091040Sarr	TAILQ_INIT(&lf->modules);
62191040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
62291040Sarr	return (lf);
62325537Sdfr}
62425537Sdfr
62525537Sdfrint
626132117Sphklinker_file_unload(linker_file_t file, int flags)
62725537Sdfr{
62891040Sarr	module_t mod, next;
62991040Sarr	modlist_t ml, nextml;
63091040Sarr	struct common_symbol *cp;
63191040Sarr	int error, i;
63225537Sdfr
63391040Sarr	/* Refuse to unload modules if securelevel raised. */
634192895Sjamie	if (prison0.pr_securelevel > 0)
63591040Sarr		return (EPERM);
63625537Sdfr
637254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
63891040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
63991040Sarr
640159584Sjhb	/* Easy case of just dropping a reference. */
641159584Sjhb	if (file->refs > 1) {
642159584Sjhb		file->refs--;
643159584Sjhb		return (0);
644159584Sjhb	}
645159584Sjhb
646262039Savg	/* Give eventhandlers a chance to prevent the unload. */
647262039Savg	error = 0;
648262039Savg	EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
649262039Savg	if (error != 0)
650262039Savg		return (EBUSY);
651262039Savg
652159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
653159584Sjhb	    " informing modules\n"));
654159584Sjhb
655159584Sjhb	/*
656185635Sjhb	 * Quiesce all the modules to give them a chance to veto the unload.
657159584Sjhb	 */
658185635Sjhb	MOD_SLOCK;
659185635Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod;
660185635Sjhb	     mod = module_getfnext(mod)) {
661185635Sjhb
662185635Sjhb		error = module_quiesce(mod);
663185635Sjhb		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
664185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
665185635Sjhb			    " vetoed unload\n", module_getname(mod)));
666185635Sjhb			/*
667185635Sjhb			 * XXX: Do we need to tell all the quiesced modules
668185635Sjhb			 * that they can resume work now via a new module
669185635Sjhb			 * event?
670185635Sjhb			 */
671185635Sjhb			MOD_SUNLOCK;
672185635Sjhb			return (error);
673185635Sjhb		}
674185635Sjhb	}
675185635Sjhb	MOD_SUNLOCK;
676185635Sjhb
677185635Sjhb	/*
678185635Sjhb	 * Inform any modules associated with this file that they are
679234186Sjhb	 * being unloaded.
680185635Sjhb	 */
681159584Sjhb	MOD_XLOCK;
682159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
683159584Sjhb		next = module_getfnext(mod);
684159584Sjhb		MOD_XUNLOCK;
685159584Sjhb
68691040Sarr		/*
687159584Sjhb		 * Give the module a chance to veto the unload.
68891040Sarr		 */
689185635Sjhb		if ((error = module_unload(mod)) != 0) {
690233276Sae#ifdef KLD_DEBUG
691233276Sae			MOD_SLOCK;
692185635Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %s"
693199457Sgonzo			    " failed unload\n", module_getname(mod)));
694233276Sae			MOD_SUNLOCK;
695233276Sae#endif
696159584Sjhb			return (error);
697159584Sjhb		}
69892547Sarr		MOD_XLOCK;
699159584Sjhb		module_release(mod);
700159584Sjhb	}
701159584Sjhb	MOD_XUNLOCK;
70291040Sarr
703159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
704128057Speadar		if (ml->container == file) {
70591040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
706128057Speadar			free(ml, M_LINKER);
707128057Speadar		}
70891040Sarr	}
70925537Sdfr
710159840Sjhb	/*
711159840Sjhb	 * Don't try to run SYSUNINITs if we are unloaded due to a
71291040Sarr	 * link error.
71391040Sarr	 */
71491040Sarr	if (file->flags & LINKER_FILE_LINKED) {
715188209Sjhb		file->flags &= ~LINKER_FILE_LINKED;
716324749Savg		linker_file_unregister_sysctls(file);
71791040Sarr		linker_file_sysuninit(file);
71825537Sdfr	}
71991040Sarr	TAILQ_REMOVE(&linker_files, file, link);
72025537Sdfr
72191040Sarr	if (file->deps) {
72291040Sarr		for (i = 0; i < file->ndeps; i++)
723132117Sphk			linker_file_unload(file->deps[i], flags);
72491040Sarr		free(file->deps, M_LINKER);
72591040Sarr		file->deps = NULL;
72659751Speter	}
727160245Sjhb	while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
728160245Sjhb		STAILQ_REMOVE_HEAD(&file->common, link);
72991040Sarr		free(cp, M_LINKER);
73091040Sarr	}
73159751Speter
73291040Sarr	LINKER_UNLOAD(file);
733262039Savg
734262039Savg	EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
735262039Savg	    file->size);
736262039Savg
73791040Sarr	if (file->filename) {
73891040Sarr		free(file->filename, M_LINKER);
73991040Sarr		file->filename = NULL;
74091040Sarr	}
741172862Sjb	if (file->pathname) {
742172862Sjb		free(file->pathname, M_LINKER);
743172862Sjb		file->pathname = NULL;
744172862Sjb	}
74591040Sarr	kobj_delete((kobj_t) file, M_LINKER);
746159584Sjhb	return (0);
74725537Sdfr}
74825537Sdfr
749179238Sjbint
750179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc)
751179238Sjb{
752179238Sjb	return (LINKER_CTF_GET(file, lc));
753179238Sjb}
754179238Sjb
755159796Sjhbstatic int
75686469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
75725537Sdfr{
75891040Sarr	linker_file_t *newdeps;
75925537Sdfr
760254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
761264370Skib	file->deps = realloc(file->deps, (file->ndeps + 1) * sizeof(*newdeps),
762264370Skib	    M_LINKER, M_WAITOK | M_ZERO);
76391040Sarr	file->deps[file->ndeps] = dep;
76491040Sarr	file->ndeps++;
765199457Sgonzo	KLD_DPF(FILE, ("linker_file_add_dependency:"
766199457Sgonzo	    " adding %s as dependency for %s\n",
767199457Sgonzo	    dep->filename, file->filename));
76891040Sarr	return (0);
76925537Sdfr}
77025537Sdfr
77178161Speter/*
77291040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
773159841Sjhb * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
774159841Sjhb * This function is used in this file so we can avoid having lots of (void **)
775159841Sjhb * casts.
77678161Speter */
77778161Speterint
77878161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
77991040Sarr    void *firstp, void *lastp, int *countp)
78078161Speter{
78178161Speter
782254811Smarkj	sx_assert(&kld_sx, SA_LOCKED);
783254811Smarkj	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
78478161Speter}
78578161Speter
786173714Sjb/*
787173714Sjb * List all functions in a file.
788173714Sjb */
789173714Sjbint
790173714Sjblinker_file_function_listall(linker_file_t lf,
791179238Sjb    linker_function_nameval_callback_t callback_func, void *arg)
792173714Sjb{
793173714Sjb	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
794173714Sjb}
795173714Sjb
79625537Sdfrcaddr_t
79791040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
79825537Sdfr{
799159845Sjhb	caddr_t sym;
800159845Sjhb	int locked;
801159845Sjhb
802254810Smarkj	locked = sx_xlocked(&kld_sx);
803159845Sjhb	if (!locked)
804254810Smarkj		sx_xlock(&kld_sx);
805159845Sjhb	sym = linker_file_lookup_symbol_internal(file, name, deps);
806159845Sjhb	if (!locked)
807254810Smarkj		sx_xunlock(&kld_sx);
808159845Sjhb	return (sym);
809159845Sjhb}
810159845Sjhb
811159845Sjhbstatic caddr_t
812159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name,
813159845Sjhb    int deps)
814159845Sjhb{
81591040Sarr	c_linker_sym_t sym;
81691040Sarr	linker_symval_t symval;
81791040Sarr	caddr_t address;
81891040Sarr	size_t common_size = 0;
81992032Sdwmalone	int i;
82025537Sdfr
821254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
822109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
82391040Sarr	    file, name, deps));
82425537Sdfr
82591040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
82691040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
82791040Sarr		if (symval.value == 0)
82891040Sarr			/*
82991040Sarr			 * For commons, first look them up in the
83091040Sarr			 * dependencies and only allocate space if not found
83191040Sarr			 * there.
83291040Sarr			 */
83391040Sarr			common_size = symval.size;
83491040Sarr		else {
83591040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
836109605Sjake			    ".value=%p\n", symval.value));
83791040Sarr			return (symval.value);
83891040Sarr		}
83940159Speter	}
84091040Sarr	if (deps) {
84191040Sarr		for (i = 0; i < file->ndeps; i++) {
842159845Sjhb			address = linker_file_lookup_symbol_internal(
843159845Sjhb			    file->deps[i], name, 0);
84491040Sarr			if (address) {
84591040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
846109605Sjake				    " deps value=%p\n", address));
84791040Sarr				return (address);
84891040Sarr			}
84991040Sarr		}
85025537Sdfr	}
85191040Sarr	if (common_size > 0) {
85291040Sarr		/*
85391040Sarr		 * This is a common symbol which was not found in the
85491040Sarr		 * dependencies.  We maintain a simple common symbol table in
85591040Sarr		 * the file object.
85691040Sarr		 */
85791040Sarr		struct common_symbol *cp;
85842849Speter
85991040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
86092032Sdwmalone			if (strcmp(cp->name, name) == 0) {
86191040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
862109605Sjake				    " old common value=%p\n", cp->address));
86391040Sarr				return (cp->address);
86491040Sarr			}
86591040Sarr		}
86691040Sarr		/*
86791040Sarr		 * Round the symbol size up to align.
86891040Sarr		 */
86991040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
87091040Sarr		cp = malloc(sizeof(struct common_symbol)
87191040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
872111119Simp		    M_WAITOK | M_ZERO);
87391040Sarr		cp->address = (caddr_t)(cp + 1);
87491040Sarr		cp->name = cp->address + common_size;
87591040Sarr		strcpy(cp->name, name);
87691040Sarr		bzero(cp->address, common_size);
87791040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
87825537Sdfr
87991040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
880109605Sjake		    " value=%p\n", cp->address));
88191040Sarr		return (cp->address);
88240159Speter	}
88391040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
88491040Sarr	return (0);
88525537Sdfr}
88625537Sdfr
88725537Sdfr/*
888174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and
889174132Srwatson * backward lookup of symbols.  However, DDB and sometimes stack(9) need to
890174132Srwatson * do this in a lockfree manner.  We provide a set of internal helper
891174132Srwatson * routines to perform these operations without locks, and then wrappers that
892174132Srwatson * optionally lock.
893159840Sjhb *
894174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
89540159Speter */
896174132Srwatson#ifdef DDB
897174132Srwatsonstatic int
898174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
89940159Speter{
90091040Sarr	linker_file_t lf;
90140159Speter
90291040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
90391040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
90491040Sarr			return (0);
90591040Sarr	}
90691040Sarr	return (ENOENT);
90740159Speter}
908174132Srwatson#endif
90940159Speter
910174132Srwatsonstatic int
911174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
91240159Speter{
91391040Sarr	linker_file_t lf;
91491040Sarr	c_linker_sym_t best, es;
91591040Sarr	u_long diff, bestdiff, off;
91640159Speter
91791040Sarr	best = 0;
91891040Sarr	off = (uintptr_t)value;
91991040Sarr	bestdiff = off;
92091040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
92191040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
92291040Sarr			continue;
92391040Sarr		if (es != 0 && diff < bestdiff) {
92491040Sarr			best = es;
92591040Sarr			bestdiff = diff;
92691040Sarr		}
92791040Sarr		if (bestdiff == 0)
92891040Sarr			break;
92940159Speter	}
93091040Sarr	if (best) {
93191040Sarr		*sym = best;
93291040Sarr		*diffp = bestdiff;
93391040Sarr		return (0);
93491040Sarr	} else {
93591040Sarr		*sym = 0;
93691040Sarr		*diffp = off;
93791040Sarr		return (ENOENT);
93891040Sarr	}
93940159Speter}
94040159Speter
941174132Srwatsonstatic int
942174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
94340159Speter{
94491040Sarr	linker_file_t lf;
94540159Speter
94691040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
94791040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
94891040Sarr			return (0);
94991040Sarr	}
95091040Sarr	return (ENOENT);
95140159Speter}
952174132Srwatson
953174132Srwatsonstatic int
954174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
955174132Srwatson    long *offset)
956174132Srwatson{
957174132Srwatson	linker_symval_t symval;
958174132Srwatson	c_linker_sym_t sym;
959174132Srwatson	int error;
960174132Srwatson
961174132Srwatson	*offset = 0;
962174132Srwatson	error = linker_debug_search_symbol(value, &sym, offset);
963174132Srwatson	if (error)
964174132Srwatson		return (error);
965174132Srwatson	error = linker_debug_symbol_values(sym, &symval);
966174132Srwatson	if (error)
967174132Srwatson		return (error);
968174132Srwatson	strlcpy(buf, symval.name, buflen);
969174132Srwatson	return (0);
970174132Srwatson}
971174132Srwatson
972174132Srwatson/*
973174132Srwatson * DDB Helpers.  DDB has to look across multiple files with their own symbol
974174132Srwatson * tables and string tables.
975174132Srwatson *
976174132Srwatson * Note that we do not obey list locking protocols here.  We really don't need
977174132Srwatson * DDB to hang because somebody's got the lock held.  We'll take the chance
978302234Sbdrewery * that the files list is inconsistent instead.
979174132Srwatson */
980212994Savg#ifdef DDB
981174132Srwatsonint
982174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
983174132Srwatson{
984174132Srwatson
985174132Srwatson	return (linker_debug_lookup(symstr, sym));
986174132Srwatson}
987212994Savg#endif
988174132Srwatson
989174132Srwatsonint
990174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
991174132Srwatson{
992174132Srwatson
993174132Srwatson	return (linker_debug_search_symbol(value, sym, diffp));
994174132Srwatson}
995174132Srwatson
996174132Srwatsonint
997174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
998174132Srwatson{
999174132Srwatson
1000174132Srwatson	return (linker_debug_symbol_values(sym, symval));
1001174132Srwatson}
1002174132Srwatson
1003174132Srwatsonint
1004174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
1005174132Srwatson    long *offset)
1006174132Srwatson{
1007174132Srwatson
1008174132Srwatson	return (linker_debug_search_symbol_name(value, buf, buflen, offset));
1009174132Srwatson}
101040159Speter
101140159Speter/*
1012174132Srwatson * stack(9) helper for non-debugging environemnts.  Unlike DDB helpers, we do
1013174132Srwatson * obey locking protocols, and offer a significantly less complex interface.
1014174132Srwatson */
1015174132Srwatsonint
1016174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
1017174132Srwatson    long *offset)
1018174132Srwatson{
1019178380Spjd	int error;
1020174132Srwatson
1021254810Smarkj	sx_xlock(&kld_sx);
1022174132Srwatson	error = linker_debug_search_symbol_name(value, buf, buflen, offset);
1023254810Smarkj	sx_xunlock(&kld_sx);
1024174132Srwatson	return (error);
1025174132Srwatson}
1026174132Srwatson
1027174132Srwatson/*
102825537Sdfr * Syscalls.
102925537Sdfr */
103025537Sdfrint
1031159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
103225537Sdfr{
1033159588Sjhb	const char *kldname, *modname;
103491040Sarr	linker_file_t lf;
1035159588Sjhb	int error;
103625537Sdfr
103793159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1038159588Sjhb		return (error);
103993159Sarr
1040164033Srwatson	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
1041159588Sjhb		return (error);
104225537Sdfr
104391040Sarr	/*
1044191917Szec	 * It is possible that kldloaded module will attach a new ifnet,
1045191816Szec	 * so vnet context must be set when this ocurs.
1046191816Szec	 */
1047191816Szec	CURVNET_SET(TD_TO_VNET(td));
1048191816Szec
1049191816Szec	/*
1050159841Sjhb	 * If file does not contain a qualified name or any dot in it
1051159841Sjhb	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
105291040Sarr	 * name.
105391040Sarr	 */
1054229272Sed	if (strchr(file, '/') || strchr(file, '.')) {
1055159588Sjhb		kldname = file;
105691040Sarr		modname = NULL;
105791040Sarr	} else {
105891040Sarr		kldname = NULL;
1059159588Sjhb		modname = file;
106091040Sarr	}
1061159588Sjhb
1062254810Smarkj	sx_xlock(&kld_sx);
106391040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
1064224156Srstone	if (error) {
1065254810Smarkj		sx_xunlock(&kld_sx);
1066224156Srstone		goto done;
1067224156Srstone	}
1068224156Srstone	lf->userrefs++;
1069224156Srstone	if (fileid != NULL)
1070224156Srstone		*fileid = lf->id;
1071262039Savg	sx_xunlock(&kld_sx);
1072254266Smarkj
1073224156Srstonedone:
1074191816Szec	CURVNET_RESTORE();
107591040Sarr	return (error);
107625537Sdfr}
107725537Sdfr
1078159588Sjhbint
1079225617Skmacysys_kldload(struct thread *td, struct kldload_args *uap)
1080159588Sjhb{
1081159588Sjhb	char *pathname = NULL;
1082159596Smarcel	int error, fileid;
1083159588Sjhb
1084159588Sjhb	td->td_retval[0] = -1;
1085159588Sjhb
1086159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1087159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1088159596Smarcel	if (error == 0) {
1089159596Smarcel		error = kern_kldload(td, pathname, &fileid);
1090159596Smarcel		if (error == 0)
1091159596Smarcel			td->td_retval[0] = fileid;
1092159596Smarcel	}
1093159588Sjhb	free(pathname, M_TEMP);
1094159588Sjhb	return (error);
1095159588Sjhb}
1096159588Sjhb
1097159588Sjhbint
1098132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
109925537Sdfr{
110091040Sarr	linker_file_t lf;
110191040Sarr	int error = 0;
110225537Sdfr
110393159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
1104159588Sjhb		return (error);
110593159Sarr
1106164033Srwatson	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1107159588Sjhb		return (error);
110825537Sdfr
1109191816Szec	CURVNET_SET(TD_TO_VNET(td));
1110254810Smarkj	sx_xlock(&kld_sx);
1111132117Sphk	lf = linker_find_file_by_id(fileid);
111291040Sarr	if (lf) {
111391040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
1114172862Sjb
1115262039Savg		if (lf->userrefs == 0) {
1116132117Sphk			/*
1117132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
1118132117Sphk			 */
111991040Sarr			printf("kldunload: attempt to unload file that was"
112091040Sarr			    " loaded by the kernel\n");
1121159840Sjhb			error = EBUSY;
1122159588Sjhb		} else {
1123159588Sjhb			lf->userrefs--;
1124159588Sjhb			error = linker_file_unload(lf, flags);
1125159588Sjhb			if (error)
1126159588Sjhb				lf->userrefs++;
1127159588Sjhb		}
112891040Sarr	} else
112991040Sarr		error = ENOENT;
1130262039Savg	sx_xunlock(&kld_sx);
1131157144Sjkoshy
1132191816Szec	CURVNET_RESTORE();
113391068Sarr	return (error);
113425537Sdfr}
113525537Sdfr
113625537Sdfrint
1137225617Skmacysys_kldunload(struct thread *td, struct kldunload_args *uap)
1138132117Sphk{
1139132117Sphk
1140132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
1141132117Sphk}
1142132117Sphk
1143132117Sphkint
1144225617Skmacysys_kldunloadf(struct thread *td, struct kldunloadf_args *uap)
1145132117Sphk{
1146132117Sphk
1147132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
1148132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
1149132117Sphk		return (EINVAL);
1150132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
1151132117Sphk}
1152132117Sphk
1153132117Sphkint
1154225617Skmacysys_kldfind(struct thread *td, struct kldfind_args *uap)
115525537Sdfr{
115691040Sarr	char *pathname;
115791040Sarr	const char *filename;
115891040Sarr	linker_file_t lf;
1159159791Sjhb	int error;
116025537Sdfr
1161107089Srwatson#ifdef MAC
1162172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1163107089Srwatson	if (error)
1164107089Srwatson		return (error);
1165107089Srwatson#endif
1166107089Srwatson
116791040Sarr	td->td_retval[0] = -1;
116882749Sdillon
1169111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1170107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
117191040Sarr		goto out;
117225537Sdfr
117391040Sarr	filename = linker_basename(pathname);
1174254810Smarkj	sx_xlock(&kld_sx);
117591040Sarr	lf = linker_find_file_by_name(filename);
117691040Sarr	if (lf)
117791040Sarr		td->td_retval[0] = lf->id;
117891040Sarr	else
117991040Sarr		error = ENOENT;
1180254810Smarkj	sx_xunlock(&kld_sx);
118125537Sdfrout:
1182159791Sjhb	free(pathname, M_TEMP);
118391040Sarr	return (error);
118425537Sdfr}
118525537Sdfr
118625537Sdfrint
1187225617Skmacysys_kldnext(struct thread *td, struct kldnext_args *uap)
118825537Sdfr{
118991040Sarr	linker_file_t lf;
119091040Sarr	int error = 0;
119125537Sdfr
1192107089Srwatson#ifdef MAC
1193172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1194107089Srwatson	if (error)
1195107089Srwatson		return (error);
1196107089Srwatson#endif
1197107089Srwatson
1198254810Smarkj	sx_xlock(&kld_sx);
1199166921Sjhb	if (uap->fileid == 0)
1200166921Sjhb		lf = TAILQ_FIRST(&linker_files);
1201166921Sjhb	else {
1202166921Sjhb		lf = linker_find_file_by_id(uap->fileid);
1203166921Sjhb		if (lf == NULL) {
1204166921Sjhb			error = ENOENT;
1205166921Sjhb			goto out;
1206166921Sjhb		}
1207166921Sjhb		lf = TAILQ_NEXT(lf, link);
120891040Sarr	}
1209166921Sjhb
1210166921Sjhb	/* Skip partially loaded files. */
1211166921Sjhb	while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1212166921Sjhb		lf = TAILQ_NEXT(lf, link);
1213166921Sjhb
1214166921Sjhb	if (lf)
1215166921Sjhb		td->td_retval[0] = lf->id;
1216166921Sjhb	else
1217166921Sjhb		td->td_retval[0] = 0;
121882749Sdillonout:
1219254810Smarkj	sx_xunlock(&kld_sx);
122091040Sarr	return (error);
122125537Sdfr}
122225537Sdfr
122325537Sdfrint
1224225617Skmacysys_kldstat(struct thread *td, struct kldstat_args *uap)
122525537Sdfr{
1226325867Sgordon	struct kld_file_stat *stat;
1227220158Skib	int error, version;
122825537Sdfr
1229159587Sjhb	/*
1230159587Sjhb	 * Check the version of the user's structure.
1231159587Sjhb	 */
1232220158Skib	if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
1233220158Skib	    != 0)
1234159587Sjhb		return (error);
1235220158Skib	if (version != sizeof(struct kld_file_stat_1) &&
1236220158Skib	    version != sizeof(struct kld_file_stat))
1237159587Sjhb		return (EINVAL);
1238159587Sjhb
1239325867Sgordon	stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO);
1240325867Sgordon	error = kern_kldstat(td, uap->fileid, stat);
1241325867Sgordon	if (error == 0)
1242325867Sgordon		error = copyout(stat, uap->stat, version);
1243325867Sgordon	free(stat, M_TEMP);
1244325867Sgordon	return (error);
1245220158Skib}
1246220158Skib
1247220158Skibint
1248220158Skibkern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
1249220158Skib{
1250220158Skib	linker_file_t lf;
1251220158Skib	int namelen;
1252107089Srwatson#ifdef MAC
1253220158Skib	int error;
1254220158Skib
1255172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1256107089Srwatson	if (error)
1257107089Srwatson		return (error);
1258107089Srwatson#endif
1259107089Srwatson
1260254810Smarkj	sx_xlock(&kld_sx);
1261220158Skib	lf = linker_find_file_by_id(fileid);
126291040Sarr	if (lf == NULL) {
1263254810Smarkj		sx_xunlock(&kld_sx);
1264159587Sjhb		return (ENOENT);
126591040Sarr	}
126625537Sdfr
1267172862Sjb	/* Version 1 fields: */
126891040Sarr	namelen = strlen(lf->filename) + 1;
126991040Sarr	if (namelen > MAXPATHLEN)
127091040Sarr		namelen = MAXPATHLEN;
1271220158Skib	bcopy(lf->filename, &stat->name[0], namelen);
1272220158Skib	stat->refs = lf->refs;
1273220158Skib	stat->id = lf->id;
1274220158Skib	stat->address = lf->address;
1275220158Skib	stat->size = lf->size;
1276220158Skib	/* Version 2 fields: */
1277220158Skib	namelen = strlen(lf->pathname) + 1;
1278220158Skib	if (namelen > MAXPATHLEN)
1279220158Skib		namelen = MAXPATHLEN;
1280220158Skib	bcopy(lf->pathname, &stat->pathname[0], namelen);
1281254810Smarkj	sx_xunlock(&kld_sx);
128225537Sdfr
128391040Sarr	td->td_retval[0] = 0;
1284220158Skib	return (0);
128525537Sdfr}
128625537Sdfr
128725537Sdfrint
1288225617Skmacysys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
128925537Sdfr{
129091040Sarr	linker_file_t lf;
129191040Sarr	module_t mp;
129291040Sarr	int error = 0;
129325537Sdfr
1294107089Srwatson#ifdef MAC
1295172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1296107089Srwatson	if (error)
1297107089Srwatson		return (error);
1298107089Srwatson#endif
1299107089Srwatson
1300254810Smarkj	sx_xlock(&kld_sx);
1301107849Salfred	lf = linker_find_file_by_id(uap->fileid);
130291040Sarr	if (lf) {
130392547Sarr		MOD_SLOCK;
130491040Sarr		mp = TAILQ_FIRST(&lf->modules);
130591040Sarr		if (mp != NULL)
130691040Sarr			td->td_retval[0] = module_getid(mp);
130791040Sarr		else
130891040Sarr			td->td_retval[0] = 0;
130992547Sarr		MOD_SUNLOCK;
131091040Sarr	} else
131191040Sarr		error = ENOENT;
1312254810Smarkj	sx_xunlock(&kld_sx);
131391040Sarr	return (error);
131425537Sdfr}
131540159Speter
131641090Speterint
1317225617Skmacysys_kldsym(struct thread *td, struct kldsym_args *uap)
131841090Speter{
131991040Sarr	char *symstr = NULL;
132091040Sarr	c_linker_sym_t sym;
132191040Sarr	linker_symval_t symval;
132291040Sarr	linker_file_t lf;
132391040Sarr	struct kld_sym_lookup lookup;
132491040Sarr	int error = 0;
132541090Speter
1326107089Srwatson#ifdef MAC
1327172930Srwatson	error = mac_kld_check_stat(td->td_ucred);
1328107089Srwatson	if (error)
1329107089Srwatson		return (error);
1330107089Srwatson#endif
1331107089Srwatson
1332107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1333159843Sjhb		return (error);
133491068Sarr	if (lookup.version != sizeof(lookup) ||
1335159843Sjhb	    uap->cmd != KLDSYM_LOOKUP)
1336159843Sjhb		return (EINVAL);
1337111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
133891040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
133991040Sarr		goto out;
1340254810Smarkj	sx_xlock(&kld_sx);
1341107849Salfred	if (uap->fileid != 0) {
1342107849Salfred		lf = linker_find_file_by_id(uap->fileid);
1343159843Sjhb		if (lf == NULL)
134491040Sarr			error = ENOENT;
1345159843Sjhb		else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
134691040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
134791040Sarr			lookup.symvalue = (uintptr_t) symval.value;
134891040Sarr			lookup.symsize = symval.size;
1349107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
135091040Sarr		} else
135191040Sarr			error = ENOENT;
135291040Sarr	} else {
135391040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
135491040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
135591040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
135691040Sarr				lookup.symvalue = (uintptr_t)symval.value;
135791040Sarr				lookup.symsize = symval.size;
1358107849Salfred				error = copyout(&lookup, uap->data,
135991040Sarr				    sizeof(lookup));
136091068Sarr				break;
136191040Sarr			}
136291040Sarr		}
136391040Sarr		if (lf == NULL)
136491040Sarr			error = ENOENT;
136541090Speter	}
1366254810Smarkj	sx_xunlock(&kld_sx);
136741090Speterout:
1368159843Sjhb	free(symstr, M_TEMP);
136991040Sarr	return (error);
137041090Speter}
137141090Speter
137240159Speter/*
137340159Speter * Preloaded module support
137440159Speter */
137540159Speter
137659751Speterstatic modlist_t
137774642Sbpmodlist_lookup(const char *name, int ver)
137859751Speter{
137991040Sarr	modlist_t mod;
138059751Speter
138191040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
138292032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
138392032Sdwmalone		    (ver == 0 || mod->version == ver))
138491040Sarr			return (mod);
138591040Sarr	}
138691040Sarr	return (NULL);
138759751Speter}
138859751Speter
138974642Sbpstatic modlist_t
139083321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
139183321Speter{
139291040Sarr	modlist_t mod, bestmod;
139392032Sdwmalone	int ver;
139483321Speter
139591040Sarr	if (verinfo == NULL)
139691040Sarr		return (modlist_lookup(name, 0));
139791040Sarr	bestmod = NULL;
1398159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
139992032Sdwmalone		if (strcmp(mod->name, name) != 0)
140091040Sarr			continue;
140191040Sarr		ver = mod->version;
140291040Sarr		if (ver == verinfo->md_ver_preferred)
140391040Sarr			return (mod);
140491040Sarr		if (ver >= verinfo->md_ver_minimum &&
140591068Sarr		    ver <= verinfo->md_ver_maximum &&
1406120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
140791040Sarr			bestmod = mod;
140891040Sarr	}
140991040Sarr	return (bestmod);
141083321Speter}
141183321Speter
141283321Speterstatic modlist_t
141378501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
141474642Sbp{
141591040Sarr	modlist_t mod;
141674642Sbp
141792705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
141891040Sarr	if (mod == NULL)
141991040Sarr		panic("no memory for module list");
142091040Sarr	mod->container = container;
142191040Sarr	mod->name = modname;
142291040Sarr	mod->version = version;
142391040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
142491040Sarr	return (mod);
142574642Sbp}
142674642Sbp
142740159Speterstatic void
142878161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
142991040Sarr    struct mod_metadata **stop, int preload)
143074642Sbp{
143191040Sarr	struct mod_metadata *mp, **mdp;
143291040Sarr	const char *modname;
143391040Sarr	int ver;
143474642Sbp
143591040Sarr	for (mdp = start; mdp < stop; mdp++) {
1436109605Sjake		mp = *mdp;
143791040Sarr		if (mp->md_type != MDT_VERSION)
143891040Sarr			continue;
1439109605Sjake		modname = mp->md_cval;
1440109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
144191040Sarr		if (modlist_lookup(modname, ver) != NULL) {
144291040Sarr			printf("module %s already present!\n", modname);
144391040Sarr			/* XXX what can we do? this is a build error. :-( */
144491040Sarr			continue;
144591040Sarr		}
144691040Sarr		modlist_newmodule(modname, ver, lf);
144774642Sbp	}
144874642Sbp}
144974642Sbp
145074642Sbpstatic void
145191040Sarrlinker_preload(void *arg)
145240159Speter{
145391040Sarr	caddr_t modptr;
145491040Sarr	const char *modname, *nmodname;
145591040Sarr	char *modtype;
1456160244Sjhb	linker_file_t lf, nlf;
145791040Sarr	linker_class_t lc;
145892032Sdwmalone	int error;
145991040Sarr	linker_file_list_t loaded_files;
146091040Sarr	linker_file_list_t depended_files;
146191040Sarr	struct mod_metadata *mp, *nmp;
146291040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
146391040Sarr	struct mod_depend *verinfo;
146491040Sarr	int nver;
146591040Sarr	int resolves;
146691040Sarr	modlist_t mod;
146791040Sarr	struct sysinit **si_start, **si_stop;
146840159Speter
146991040Sarr	TAILQ_INIT(&loaded_files);
147091040Sarr	TAILQ_INIT(&depended_files);
147191040Sarr	TAILQ_INIT(&found_modules);
147291040Sarr	error = 0;
147359751Speter
147491040Sarr	modptr = NULL;
1475254810Smarkj	sx_xlock(&kld_sx);
147691040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
147791040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
147891040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
147991040Sarr		if (modname == NULL) {
148091040Sarr			printf("Preloaded module at %p does not have a"
148191040Sarr			    " name!\n", modptr);
148291040Sarr			continue;
148391040Sarr		}
148491040Sarr		if (modtype == NULL) {
148591040Sarr			printf("Preloaded module at %p does not have a type!\n",
148691040Sarr			    modptr);
148791040Sarr			continue;
148891040Sarr		}
1489131398Sjhb		if (bootverbose)
1490131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1491131398Sjhb			    modptr);
149240159Speter		lf = NULL;
149391040Sarr		TAILQ_FOREACH(lc, &classes, link) {
149491040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1495134364Siedowse			if (!error)
149691040Sarr				break;
1497134364Siedowse			lf = NULL;
149891040Sarr		}
149991040Sarr		if (lf)
150091040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
150140159Speter	}
150240159Speter
150391040Sarr	/*
150491040Sarr	 * First get a list of stuff in the kernel.
150591040Sarr	 */
150691040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
150791040Sarr	    &stop, NULL) == 0)
150891040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
150959751Speter
151059751Speter	/*
1511167019Sjhb	 * This is a once-off kinky bubble sort to resolve relocation
1512167019Sjhb	 * dependency requirements.
151359751Speter	 */
151491040Sarrrestart:
151591040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
151691040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
151791040Sarr		    &stop, NULL);
151891040Sarr		/*
151991040Sarr		 * First, look to see if we would successfully link with this
152091040Sarr		 * stuff.
152191040Sarr		 */
152291040Sarr		resolves = 1;	/* unless we know otherwise */
152391040Sarr		if (!error) {
152491040Sarr			for (mdp = start; mdp < stop; mdp++) {
1525109605Sjake				mp = *mdp;
152691040Sarr				if (mp->md_type != MDT_DEPEND)
152791040Sarr					continue;
1528109605Sjake				modname = mp->md_cval;
1529109605Sjake				verinfo = mp->md_data;
153091040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1531109605Sjake					nmp = *nmdp;
153291040Sarr					if (nmp->md_type != MDT_VERSION)
153391040Sarr						continue;
1534109605Sjake					nmodname = nmp->md_cval;
153592032Sdwmalone					if (strcmp(modname, nmodname) == 0)
153691040Sarr						break;
153791040Sarr				}
153891040Sarr				if (nmdp < stop)   /* it's a self reference */
153991040Sarr					continue;
1540159840Sjhb
154191040Sarr				/*
154291040Sarr				 * ok, the module isn't here yet, we
154391040Sarr				 * are not finished
154491040Sarr				 */
154591068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
154691040Sarr					resolves = 0;
154791040Sarr			}
154864143Speter		}
154991040Sarr		/*
155091040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
155191040Sarr		 * the modules inside and add it to the end of the link order
155291040Sarr		 * list.
155391040Sarr		 */
155491040Sarr		if (resolves) {
155591040Sarr			if (!error) {
155691040Sarr				for (mdp = start; mdp < stop; mdp++) {
1557109605Sjake					mp = *mdp;
155891040Sarr					if (mp->md_type != MDT_VERSION)
155991040Sarr						continue;
1560109605Sjake					modname = mp->md_cval;
1561109605Sjake					nver = ((struct mod_version *)
1562109605Sjake					    mp->md_data)->mv_version;
156391040Sarr					if (modlist_lookup(modname,
156491040Sarr					    nver) != NULL) {
156591040Sarr						printf("module %s already"
156691040Sarr						    " present!\n", modname);
1567160244Sjhb						TAILQ_REMOVE(&loaded_files,
1568160244Sjhb						    lf, loaded);
1569132117Sphk						linker_file_unload(lf,
1570132117Sphk						    LINKER_UNLOAD_FORCE);
157191040Sarr						/* we changed tailq next ptr */
157291068Sarr						goto restart;
157391040Sarr					}
157491040Sarr					modlist_newmodule(modname, nver, lf);
157591040Sarr				}
157691040Sarr			}
157791040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
157891040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
157991040Sarr			/*
158091040Sarr			 * Since we provided modules, we need to restart the
158191040Sarr			 * sort so that the previous files that depend on us
158291040Sarr			 * have a chance. Also, we've busted the tailq next
158391040Sarr			 * pointer with the REMOVE.
158491040Sarr			 */
158591040Sarr			goto restart;
158659751Speter		}
158759751Speter	}
158891040Sarr
158959751Speter	/*
159091040Sarr	 * At this point, we check to see what could not be resolved..
159159751Speter	 */
1592160242Sjhb	while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1593160242Sjhb		TAILQ_REMOVE(&loaded_files, lf, loaded);
159491040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1595132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
159640159Speter	}
159759751Speter
159878161Speter	/*
159991040Sarr	 * We made it. Finish off the linking in the order we determined.
160078161Speter	 */
1601160244Sjhb	TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
160291040Sarr		if (linker_kernel_file) {
160391040Sarr			linker_kernel_file->refs++;
160491040Sarr			error = linker_file_add_dependency(lf,
160591040Sarr			    linker_kernel_file);
160691040Sarr			if (error)
160791040Sarr				panic("cannot add dependency");
160891040Sarr		}
160991040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
161091040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
161191040Sarr		    &stop, NULL);
161291040Sarr		if (!error) {
161391040Sarr			for (mdp = start; mdp < stop; mdp++) {
1614109605Sjake				mp = *mdp;
161591040Sarr				if (mp->md_type != MDT_DEPEND)
161691040Sarr					continue;
1617109605Sjake				modname = mp->md_cval;
1618109605Sjake				verinfo = mp->md_data;
161991040Sarr				mod = modlist_lookup2(modname, verinfo);
1620216988Strasz				if (mod == NULL) {
1621216988Strasz					printf("KLD file %s - cannot find "
1622216988Strasz					    "dependency \"%s\"\n",
1623216988Strasz					    lf->filename, modname);
1624216988Strasz					goto fail;
1625216988Strasz				}
1626151484Sjdp				/* Don't count self-dependencies */
1627151484Sjdp				if (lf == mod->container)
1628151484Sjdp					continue;
162991040Sarr				mod->container->refs++;
163091040Sarr				error = linker_file_add_dependency(lf,
163191040Sarr				    mod->container);
163291040Sarr				if (error)
163391040Sarr					panic("cannot add dependency");
163491040Sarr			}
163591040Sarr		}
163691040Sarr		/*
163791040Sarr		 * Now do relocation etc using the symbol search paths
163891040Sarr		 * established by the dependencies
163991040Sarr		 */
164091040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
164191040Sarr		if (error) {
164291040Sarr			printf("KLD file %s - could not finalize loading\n",
164391040Sarr			    lf->filename);
1644216988Strasz			goto fail;
164591040Sarr		}
164691040Sarr		linker_file_register_modules(lf);
164791040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
164891040Sarr		    &si_stop, NULL) == 0)
164991040Sarr			sysinit_add(si_start, si_stop);
1650324749Savg		linker_file_register_sysctls(lf, true);
165191040Sarr		lf->flags |= LINKER_FILE_LINKED;
1652216988Strasz		continue;
1653216988Straszfail:
1654216988Strasz		TAILQ_REMOVE(&depended_files, lf, loaded);
1655216988Strasz		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
165659751Speter	}
1657254810Smarkj	sx_xunlock(&kld_sx);
165891040Sarr	/* woohoo! we made it! */
165940159Speter}
166040159Speter
1661177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
166240159Speter
166340159Speter/*
166440159Speter * Search for a not-loaded module by name.
1665159840Sjhb *
166640159Speter * Modules may be found in the following locations:
1667159840Sjhb *
166891040Sarr * - preloaded (result is just the module name) - on disk (result is full path
166991040Sarr * to module)
1670159840Sjhb *
167191040Sarr * If the module name is qualified in any way (contains path, etc.) the we
167291040Sarr * simply return a copy of it.
1673159840Sjhb *
167440159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
167540159Speter * character as a separator to be consistent with the bootloader.
167640159Speter */
167740159Speter
167883321Speterstatic char linker_hintfile[] = "linker.hints";
1679111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
168040159Speter
168140159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
168291040Sarr    sizeof(linker_path), "module load search path");
168340159Speter
168477843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
168570417Speter
168659751Speterstatic char *linker_ext_list[] = {
168783321Speter	"",
168859751Speter	".ko",
168959751Speter	NULL
169059751Speter};
169159751Speter
169283321Speter/*
169391040Sarr * Check if file actually exists either with or without extension listed in
169491040Sarr * the linker_ext_list. (probably should be generic for the rest of the
169591040Sarr * kernel)
169683321Speter */
169759751Speterstatic char *
169891040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
169991040Sarr    int namelen, struct vattr *vap)
170040159Speter{
170191040Sarr	struct nameidata nd;
170291040Sarr	struct thread *td = curthread;	/* XXX */
170391040Sarr	char *result, **cpp, *sep;
1704241896Skib	int error, len, extlen, reclen, flags;
170591040Sarr	enum vtype type;
170640159Speter
170791040Sarr	extlen = 0;
170891040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
170991040Sarr		len = strlen(*cpp);
171091040Sarr		if (len > extlen)
171191040Sarr			extlen = len;
171291040Sarr	}
171391040Sarr	extlen++;		/* trailing '\0' */
171491040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
171583321Speter
171691040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1717111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
171891040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
171991040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
172091040Sarr		    namelen, name, *cpp);
172191040Sarr		/*
172291040Sarr		 * Attempt to open the file, and return the path if
172391040Sarr		 * we succeed and it's a regular file.
172491040Sarr		 */
1725241896Skib		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
172691040Sarr		flags = FREAD;
1727170152Skib		error = vn_open(&nd, &flags, 0, NULL);
172891040Sarr		if (error == 0) {
172991040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
173091040Sarr			type = nd.ni_vp->v_type;
173191040Sarr			if (vap)
1732182371Sattilio				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1733175294Sattilio			VOP_UNLOCK(nd.ni_vp, 0);
173491406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
173591040Sarr			if (type == VREG)
173691040Sarr				return (result);
173791040Sarr		}
173883321Speter	}
173991040Sarr	free(result, M_LINKER);
174091040Sarr	return (NULL);
174183321Speter}
174283321Speter
174391040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
174483321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
174583321Speter
174683321Speter/*
174791040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
174891040Sarr * version specification is available, then try to find the best KLD.
174983321Speter * Otherwise just find the latest one.
175083321Speter */
175183321Speterstatic char *
175291040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
175391040Sarr    int modnamelen, struct mod_depend *verinfo)
175483321Speter{
175591040Sarr	struct thread *td = curthread;	/* XXX */
175691406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
175791040Sarr	struct nameidata nd;
175891040Sarr	struct vattr vattr, mattr;
175991040Sarr	u_char *hints = NULL;
176091040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
1761231949Skib	int error, ival, bestver, *intp, found, flags, clen, blen;
1762231949Skib	ssize_t reclen;
176383321Speter
176491040Sarr	result = NULL;
176591040Sarr	bestver = found = 0;
176683321Speter
176791040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
176891040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
176991040Sarr	    strlen(sep) + 1;
1770111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
177191040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
177291040Sarr	    linker_hintfile);
177383321Speter
1774241896Skib	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
177591040Sarr	flags = FREAD;
1776170152Skib	error = vn_open(&nd, &flags, 0, NULL);
177791040Sarr	if (error)
177891040Sarr		goto bad;
177991040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
178091040Sarr	if (nd.ni_vp->v_type != VREG)
178191040Sarr		goto bad;
178291040Sarr	best = cp = NULL;
1783182371Sattilio	error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
178491040Sarr	if (error)
178591040Sarr		goto bad;
178691040Sarr	/*
178791040Sarr	 * XXX: we need to limit this number to some reasonable value
178891040Sarr	 */
178991040Sarr	if (vattr.va_size > 100 * 1024) {
179091040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
179191040Sarr		goto bad;
179291040Sarr	}
1793111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
179491068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1795101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
179691040Sarr	if (error)
179791040Sarr		goto bad;
1798175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
179991040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
180091040Sarr	nd.ni_vp = NULL;
180191040Sarr	if (reclen != 0) {
1802231949Skib		printf("can't read %zd\n", reclen);
180391040Sarr		goto bad;
180491040Sarr	}
180591040Sarr	intp = (int *)hints;
180683321Speter	ival = *intp++;
180791040Sarr	if (ival != LINKER_HINTS_VERSION) {
180891040Sarr		printf("hints file version mismatch %d\n", ival);
180991040Sarr		goto bad;
181083321Speter	}
181191040Sarr	bufend = hints + vattr.va_size;
181291040Sarr	recptr = (u_char *)intp;
181391040Sarr	clen = blen = 0;
181491040Sarr	while (recptr < bufend && !found) {
181591040Sarr		intp = (int *)recptr;
181691040Sarr		reclen = *intp++;
181791040Sarr		ival = *intp++;
181891040Sarr		cp = (char *)intp;
181991040Sarr		switch (ival) {
182091040Sarr		case MDT_VERSION:
182191040Sarr			clen = *cp++;
182291040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
182391040Sarr				break;
182491040Sarr			cp += clen;
182591040Sarr			INT_ALIGN(hints, cp);
182691040Sarr			ival = *(int *)cp;
182791040Sarr			cp += sizeof(int);
182891040Sarr			clen = *cp++;
182991040Sarr			if (verinfo == NULL ||
183091040Sarr			    ival == verinfo->md_ver_preferred) {
183191040Sarr				found = 1;
183291040Sarr				break;
183391040Sarr			}
183491040Sarr			if (ival >= verinfo->md_ver_minimum &&
183591040Sarr			    ival <= verinfo->md_ver_maximum &&
183691040Sarr			    ival > bestver) {
183791040Sarr				bestver = ival;
183891040Sarr				best = cp;
183991040Sarr				blen = clen;
184091040Sarr			}
184191040Sarr			break;
184291040Sarr		default:
184391040Sarr			break;
184491040Sarr		}
184591040Sarr		recptr += reclen + sizeof(int);
184691040Sarr	}
184783321Speter	/*
184891040Sarr	 * Finally check if KLD is in the place
184983321Speter	 */
185091040Sarr	if (found)
185191040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
185291040Sarr	else if (best)
185391040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
185491040Sarr
185591040Sarr	/*
185691040Sarr	 * KLD is newer than hints file. What we should do now?
185791040Sarr	 */
185891040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
185991040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
186091040Sarr		    " file\n", result);
186183321Speterbad:
1862105167Sphk	free(pathbuf, M_LINKER);
186391040Sarr	if (hints)
186491040Sarr		free(hints, M_TEMP);
186599553Sjeff	if (nd.ni_vp != NULL) {
1866175294Sattilio		VOP_UNLOCK(nd.ni_vp, 0);
186791040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
186899553Sjeff	}
186991040Sarr	/*
187091040Sarr	 * If nothing found or hints is absent - fallback to the old
187191040Sarr	 * way by using "kldname[.ko]" as module name.
187291040Sarr	 */
187391040Sarr	if (!found && !bestver && result == NULL)
187491040Sarr		result = linker_lookup_file(path, pathlen, modname,
187591040Sarr		    modnamelen, NULL);
187691040Sarr	return (result);
187783321Speter}
187883321Speter
187983321Speter/*
188083321Speter * Lookup KLD which contains requested module in the all directories.
188183321Speter */
188283321Speterstatic char *
188383321Speterlinker_search_module(const char *modname, int modnamelen,
188491040Sarr    struct mod_depend *verinfo)
188583321Speter{
188691040Sarr	char *cp, *ep, *result;
188783321Speter
188891040Sarr	/*
188991040Sarr	 * traverse the linker path
189091040Sarr	 */
189191040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
189291040Sarr		/* find the end of this component */
189391040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
189491068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
189591068Sarr		    modnamelen, verinfo);
189691040Sarr		if (result != NULL)
189791040Sarr			return (result);
189891040Sarr		if (*ep == 0)
189991040Sarr			break;
190091040Sarr	}
190191040Sarr	return (NULL);
190283321Speter}
190383321Speter
190483321Speter/*
190583321Speter * Search for module in all directories listed in the linker_path.
190683321Speter */
190783321Speterstatic char *
190883321Speterlinker_search_kld(const char *name)
190983321Speter{
1910158972Sdelphij	char *cp, *ep, *result;
1911158972Sdelphij	int len;
191283321Speter
191391040Sarr	/* qualified at all? */
1914229272Sed	if (strchr(name, '/'))
1915254396Smarkj		return (strdup(name, M_LINKER));
191640159Speter
191791040Sarr	/* traverse the linker path */
191891040Sarr	len = strlen(name);
191991040Sarr	for (ep = linker_path; *ep; ep++) {
192091040Sarr		cp = ep;
192191040Sarr		/* find the end of this component */
192291040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
192391040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
192491040Sarr		if (result != NULL)
192591040Sarr			return (result);
192691040Sarr	}
192791040Sarr	return (NULL);
192840159Speter}
192959751Speter
193059751Speterstatic const char *
193191040Sarrlinker_basename(const char *path)
193259751Speter{
193391040Sarr	const char *filename;
193459751Speter
1935229272Sed	filename = strrchr(path, '/');
193691040Sarr	if (filename == NULL)
193791040Sarr		return path;
193891040Sarr	if (filename[1])
193991040Sarr		filename++;
194091040Sarr	return (filename);
194159751Speter}
194259751Speter
1943157144Sjkoshy#ifdef HWPMC_HOOKS
194459751Speter/*
1945157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1946157144Sjkoshy */
1947157144Sjkoshyvoid *
1948157144Sjkoshylinker_hwpmc_list_objects(void)
1949157144Sjkoshy{
1950195159Sattilio	linker_file_t lf;
1951195159Sattilio	struct pmckern_map_in *kobase;
1952195159Sattilio	int i, nmappings;
1953157144Sjkoshy
1954195159Sattilio	nmappings = 0;
1955254810Smarkj	sx_slock(&kld_sx);
1956195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link)
1957195159Sattilio		nmappings++;
1958157144Sjkoshy
1959195159Sattilio	/* Allocate nmappings + 1 entries. */
1960195159Sattilio	kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in),
1961184214Sdes	    M_LINKER, M_WAITOK | M_ZERO);
1962195159Sattilio	i = 0;
1963195159Sattilio	TAILQ_FOREACH(lf, &linker_files, link) {
1964157144Sjkoshy
1965195159Sattilio		/* Save the info for this linker file. */
1966195159Sattilio		kobase[i].pm_file = lf->filename;
1967195159Sattilio		kobase[i].pm_address = (uintptr_t)lf->address;
1968195159Sattilio		i++;
1969157144Sjkoshy	}
1970254810Smarkj	sx_sunlock(&kld_sx);
1971157144Sjkoshy
1972195159Sattilio	KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
1973157144Sjkoshy
1974157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1975195159Sattilio	KASSERT(kobase[i].pm_file == NULL,
1976157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1977157144Sjkoshy
1978195159Sattilio	return ((void *)kobase);
1979157144Sjkoshy}
1980157144Sjkoshy#endif
1981157144Sjkoshy
1982157144Sjkoshy/*
198391040Sarr * Find a file which contains given module and load it, if "parent" is not
198491040Sarr * NULL, register a reference to it.
198559751Speter */
1986159796Sjhbstatic int
198783321Speterlinker_load_module(const char *kldname, const char *modname,
198891040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
198991040Sarr    struct linker_file **lfpp)
199059751Speter{
199191040Sarr	linker_file_t lfdep;
199291040Sarr	const char *filename;
199391040Sarr	char *pathname;
199491040Sarr	int error;
199559751Speter
1996254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
199791040Sarr	if (modname == NULL) {
199891040Sarr		/*
199991040Sarr 		 * We have to load KLD
200091040Sarr 		 */
200191068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
200291068Sarr		    " is not NULL"));
2003355419Shselasky		/* check if root file system is not mounted */
2004355419Shselasky		if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL)
2005355419Shselasky			return (ENXIO);
200691040Sarr		pathname = linker_search_kld(kldname);
200791040Sarr	} else {
200891040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
200991040Sarr			return (EEXIST);
2010355419Shselasky		/* check if root file system is not mounted */
2011355419Shselasky		if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL)
2012355419Shselasky			return (ENXIO);
201394322Sbrian		if (kldname != NULL)
2014254396Smarkj			pathname = strdup(kldname, M_LINKER);
201594322Sbrian		else
201691040Sarr			/*
201791040Sarr			 * Need to find a KLD with required module
201891040Sarr			 */
201991040Sarr			pathname = linker_search_module(modname,
202091040Sarr			    strlen(modname), verinfo);
202191040Sarr	}
202291040Sarr	if (pathname == NULL)
202391040Sarr		return (ENOENT);
202491040Sarr
202583321Speter	/*
202691040Sarr	 * Can't load more than one file with the same basename XXX:
202791040Sarr	 * Actually it should be possible to have multiple KLDs with
202891040Sarr	 * the same basename but different path because they can
202991040Sarr	 * provide different versions of the same modules.
203083321Speter	 */
203191040Sarr	filename = linker_basename(pathname);
2032159792Sjhb	if (linker_find_file_by_name(filename))
203391040Sarr		error = EEXIST;
2034159792Sjhb	else do {
203591040Sarr		error = linker_load_file(pathname, &lfdep);
203691040Sarr		if (error)
203791040Sarr			break;
203891040Sarr		if (modname && verinfo &&
203991040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
2040132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
204191040Sarr			error = ENOENT;
204291040Sarr			break;
204391040Sarr		}
204491040Sarr		if (parent) {
204591040Sarr			error = linker_file_add_dependency(parent, lfdep);
204691040Sarr			if (error)
204791040Sarr				break;
204891040Sarr		}
204991040Sarr		if (lfpp)
205091040Sarr			*lfpp = lfdep;
205191040Sarr	} while (0);
2052159791Sjhb	free(pathname, M_LINKER);
205391040Sarr	return (error);
205459751Speter}
205559751Speter
205659751Speter/*
205791040Sarr * This routine is responsible for finding dependencies of userland initiated
205891040Sarr * kldload(2)'s of files.
205959751Speter */
206059751Speterint
206186469Siedowselinker_load_dependencies(linker_file_t lf)
206259751Speter{
206391040Sarr	linker_file_t lfdep;
206491040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
206591040Sarr	struct mod_metadata *mp, *nmp;
206691040Sarr	struct mod_depend *verinfo;
206791040Sarr	modlist_t mod;
206891040Sarr	const char *modname, *nmodname;
206992032Sdwmalone	int ver, error = 0, count;
207059751Speter
207191040Sarr	/*
2072302234Sbdrewery	 * All files are dependent on /kernel.
207391040Sarr	 */
2074254810Smarkj	sx_assert(&kld_sx, SA_XLOCKED);
207591040Sarr	if (linker_kernel_file) {
207691040Sarr		linker_kernel_file->refs++;
207791040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
207891040Sarr		if (error)
207991040Sarr			return (error);
208059751Speter	}
208191040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
208291040Sarr	    &count) != 0)
208391040Sarr		return (0);
208491040Sarr	for (mdp = start; mdp < stop; mdp++) {
2085109605Sjake		mp = *mdp;
208691040Sarr		if (mp->md_type != MDT_VERSION)
208791040Sarr			continue;
2088109605Sjake		modname = mp->md_cval;
2089109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
209091040Sarr		mod = modlist_lookup(modname, ver);
209191040Sarr		if (mod != NULL) {
209291040Sarr			printf("interface %s.%d already present in the KLD"
209391040Sarr			    " '%s'!\n", modname, ver,
209491040Sarr			    mod->container->filename);
209591040Sarr			return (EEXIST);
209691040Sarr		}
209791040Sarr	}
209874642Sbp
209991040Sarr	for (mdp = start; mdp < stop; mdp++) {
2100109605Sjake		mp = *mdp;
210191040Sarr		if (mp->md_type != MDT_DEPEND)
210291040Sarr			continue;
2103109605Sjake		modname = mp->md_cval;
2104109605Sjake		verinfo = mp->md_data;
210591040Sarr		nmodname = NULL;
210691040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
2107109605Sjake			nmp = *nmdp;
210891040Sarr			if (nmp->md_type != MDT_VERSION)
210991040Sarr				continue;
2110109605Sjake			nmodname = nmp->md_cval;
211192032Sdwmalone			if (strcmp(modname, nmodname) == 0)
211291040Sarr				break;
211391040Sarr		}
211491040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
211591040Sarr			continue;
211691040Sarr		mod = modlist_lookup2(modname, verinfo);
211791040Sarr		if (mod) {	/* woohoo, it's loaded already */
211891040Sarr			lfdep = mod->container;
211991040Sarr			lfdep->refs++;
212091040Sarr			error = linker_file_add_dependency(lf, lfdep);
212191040Sarr			if (error)
212291040Sarr				break;
212391040Sarr			continue;
212491040Sarr		}
212591040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
212691040Sarr		if (error) {
2127231931Sdelphij			printf("KLD %s: depends on %s - not available or"
2128195803Srpaulo			    " version mismatch\n", lf->filename, modname);
212991040Sarr			break;
213091040Sarr		}
213159751Speter	}
213259751Speter
213391040Sarr	if (error)
213491040Sarr		return (error);
213591040Sarr	linker_addmodules(lf, start, stop, 0);
213691040Sarr	return (error);
213759751Speter}
213885736Sgreen
213985736Sgreenstatic int
214085736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
214185736Sgreen{
214285736Sgreen	struct sysctl_req *req;
214385736Sgreen
214485736Sgreen	req = opaque;
214585736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
214685736Sgreen}
214785736Sgreen
214885736Sgreen/*
214985736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
215085736Sgreen * in the kernel.
215185736Sgreen */
215285736Sgreenstatic int
215385736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
215485736Sgreen{
215585736Sgreen	linker_file_t lf;
215685736Sgreen	int error;
215785736Sgreen
2158107089Srwatson#ifdef MAC
2159172930Srwatson	error = mac_kld_check_stat(req->td->td_ucred);
2160107089Srwatson	if (error)
2161107089Srwatson		return (error);
2162107089Srwatson#endif
2163126253Struckman	error = sysctl_wire_old_buffer(req, 0);
2164126253Struckman	if (error != 0)
2165126253Struckman		return (error);
2166254810Smarkj	sx_xlock(&kld_sx);
216785736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
216885736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
216985736Sgreen		    sysctl_kern_function_list_iterate, req);
217098452Sarr		if (error) {
2171254810Smarkj			sx_xunlock(&kld_sx);
217285736Sgreen			return (error);
217398452Sarr		}
217485736Sgreen	}
2175254810Smarkj	sx_xunlock(&kld_sx);
217685736Sgreen	return (SYSCTL_OUT(req, "", 1));
217785736Sgreen}
217885736Sgreen
2179217555SmdfSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLTYPE_OPAQUE | CTLFLAG_RD,
218091040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2181