kern_linker.c revision 157144
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 157144 2006-03-26 12:20:54Z jkoshy $");
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>
4025537Sdfr#include <sys/proc.h>
4125537Sdfr#include <sys/lock.h>
4282749Sdillon#include <sys/mutex.h>
4392547Sarr#include <sys/sx.h>
44107089Srwatson#include <sys/mac.h>
4525537Sdfr#include <sys/module.h>
4625537Sdfr#include <sys/linker.h>
4740159Speter#include <sys/fcntl.h>
4840159Speter#include <sys/libkern.h>
4940159Speter#include <sys/namei.h>
5040159Speter#include <sys/vnode.h>
5140159Speter#include <sys/sysctl.h>
5225537Sdfr
5359603Sdfr#include "linker_if.h"
5459603Sdfr
55157144Sjkoshy#ifdef HWPMC_HOOKS
56157144Sjkoshy#include <sys/pmckern.h>
57157144Sjkoshy#endif
58157144Sjkoshy
5940961Speter#ifdef KLD_DEBUG
6040961Speterint kld_debug = 0;
6140961Speter#endif
6240961Speter
6391040Sarr/*
6491040Sarr * static char *linker_search_path(const char *name, struct mod_depend
6591040Sarr * *verinfo);
6691040Sarr */
6791040Sarrstatic const char 	*linker_basename(const char *path);
6859751Speter
6978161Speter/* Metadata from the static kernel */
7078161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
7178161Speter
7259751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
7359751Speter
7440906Speterlinker_file_t linker_kernel_file;
7531324Sbde
7698452Sarrstatic struct mtx kld_mtx;	/* kernel linker mutex */
7798452Sarr
7825537Sdfrstatic linker_class_list_t classes;
7950068Sgrogstatic linker_file_list_t linker_files;
8025537Sdfrstatic int next_file_id = 1;
8198452Sarrstatic int linker_no_more_classes = 0;
8225537Sdfr
8386553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
8491040Sarr	linker_file_t lftmp;						\
8586553Sarr									\
8686553Sarrretry:									\
8798452Sarr	mtx_lock(&kld_mtx);						\
8891040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
8991040Sarr		if (next_file_id == lftmp->id) {			\
9091040Sarr			next_file_id++;					\
9198452Sarr			mtx_unlock(&kld_mtx);				\
9291040Sarr			goto retry;					\
9391040Sarr		}							\
9491040Sarr	}								\
9591040Sarr	(a) = next_file_id;						\
9698452Sarr	mtx_unlock(&kld_mtx);	/* Hold for safe read of id variable */	\
9786553Sarr} while(0)
9886553Sarr
9986553Sarr
10059751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
10160938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
10259751Speterstruct modlist {
10391040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
10491040Sarr	linker_file_t   container;
10591040Sarr	const char 	*name;
10691040Sarr	int             version;
10759751Speter};
10891040Sarrtypedef struct modlist *modlist_t;
10991040Sarrstatic modlisthead_t found_modules;
11059751Speter
11194321Sbrianstatic modlist_t	modlist_lookup2(const char *name,
11294321Sbrian			    struct mod_depend *verinfo);
11394321Sbrian
11459603Sdfrstatic char *
11559603Sdfrlinker_strdup(const char *str)
11659603Sdfr{
11791040Sarr	char *result;
11859603Sdfr
119111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
12091040Sarr		strcpy(result, str);
12191040Sarr	return (result);
12259603Sdfr}
12359603Sdfr
12425537Sdfrstatic void
12591040Sarrlinker_init(void *arg)
12625537Sdfr{
12791040Sarr
12898452Sarr	mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
12991040Sarr	TAILQ_INIT(&classes);
13091040Sarr	TAILQ_INIT(&linker_files);
13125537Sdfr}
13225537Sdfr
13391040SarrSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
13425537Sdfr
13598452Sarrstatic void
13698452Sarrlinker_stop_class_add(void *arg)
13798452Sarr{
13898452Sarr
13998452Sarr	linker_no_more_classes = 1;
14098452Sarr}
14198452Sarr
14298452SarrSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL)
14398452Sarr
14425537Sdfrint
14559603Sdfrlinker_add_class(linker_class_t lc)
14625537Sdfr{
14791040Sarr
14898452Sarr	/*
149144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
150144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
151144443Sjhb	 * ops from being freed.
15298452Sarr	 */
15398452Sarr	if (linker_no_more_classes == 1)
15498452Sarr		return (EPERM);
15591040Sarr	kobj_class_compile((kobj_class_t) lc);
156144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
15791040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
15891040Sarr	return (0);
15925537Sdfr}
16025537Sdfr
16125537Sdfrstatic void
16225537Sdfrlinker_file_sysinit(linker_file_t lf)
16325537Sdfr{
16491040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
16525537Sdfr
16691040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
16791040Sarr	    lf->filename));
16825537Sdfr
16991040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
17091040Sarr		return;
17191040Sarr	/*
17291040Sarr	 * Perform a bubble sort of the system initialization objects by
17391040Sarr	 * their subsystem (primary key) and order (secondary key).
17491040Sarr	 *
17591040Sarr	 * Since some things care about execution order, this is the operation
17691040Sarr	 * which ensures continued function.
17791040Sarr	 */
17891040Sarr	for (sipp = start; sipp < stop; sipp++) {
17991040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
18091040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
18191040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
18291040Sarr			    (*sipp)->order <= (*xipp)->order))
18391040Sarr				continue;	/* skip */
18491040Sarr			save = *sipp;
18591040Sarr			*sipp = *xipp;
18691040Sarr			*xipp = save;
18791040Sarr		}
18825537Sdfr	}
18925537Sdfr
19091040Sarr	/*
19191040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
19291040Sarr	 * Perform each task, and continue on to the next task.
19391040Sarr	 */
19491040Sarr	for (sipp = start; sipp < stop; sipp++) {
19591040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
19691040Sarr			continue;	/* skip dummy task(s) */
19725537Sdfr
19891040Sarr		/* Call function */
19991040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
20091040Sarr	}
20125537Sdfr}
20225537Sdfr
20341055Speterstatic void
20441055Speterlinker_file_sysuninit(linker_file_t lf)
20541055Speter{
20691040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
20741055Speter
20891040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
20991040Sarr	    lf->filename));
21041055Speter
21191068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
21291040Sarr	    NULL) != 0)
21391040Sarr		return;
21441055Speter
21591040Sarr	/*
21691040Sarr	 * Perform a reverse bubble sort of the system initialization objects
21791040Sarr	 * by their subsystem (primary key) and order (secondary key).
21891040Sarr	 *
21991040Sarr	 * Since some things care about execution order, this is the operation
22091040Sarr	 * which ensures continued function.
22191040Sarr	 */
22291040Sarr	for (sipp = start; sipp < stop; sipp++) {
22391040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
22491040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
22591040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
22691040Sarr			    (*sipp)->order >= (*xipp)->order))
22791040Sarr				continue;	/* skip */
22891040Sarr			save = *sipp;
22991040Sarr			*sipp = *xipp;
23091040Sarr			*xipp = save;
23191040Sarr		}
23241055Speter	}
23341055Speter
23491040Sarr	/*
23591040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
23691040Sarr	 * Perform each task, and continue on to the next task.
23791040Sarr	 */
23891040Sarr	for (sipp = start; sipp < stop; sipp++) {
23991040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
24091040Sarr			continue;	/* skip dummy task(s) */
24141055Speter
24291040Sarr		/* Call function */
24391040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
24491040Sarr	}
24541055Speter}
24641055Speter
24744078Sdfrstatic void
24844078Sdfrlinker_file_register_sysctls(linker_file_t lf)
24944078Sdfr{
25091040Sarr	struct sysctl_oid **start, **stop, **oidp;
25144078Sdfr
25291040Sarr	KLD_DPF(FILE,
25391040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
25491040Sarr	    lf->filename));
25544078Sdfr
25691040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
25791040Sarr		return;
25844078Sdfr
25991040Sarr	for (oidp = start; oidp < stop; oidp++)
26091040Sarr		sysctl_register_oid(*oidp);
26144078Sdfr}
26244078Sdfr
26344078Sdfrstatic void
26444078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
26544078Sdfr{
26691040Sarr	struct sysctl_oid **start, **stop, **oidp;
26744078Sdfr
26891040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
26991040Sarr	    " for %s\n", lf->filename));
27044078Sdfr
27191040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
27291040Sarr		return;
27344078Sdfr
27491040Sarr	for (oidp = start; oidp < stop; oidp++)
27591040Sarr		sysctl_unregister_oid(*oidp);
27644078Sdfr}
27744078Sdfr
27859751Speterstatic int
27959751Speterlinker_file_register_modules(linker_file_t lf)
28059751Speter{
28191040Sarr	struct mod_metadata **start, **stop, **mdp;
28291040Sarr	const moduledata_t *moddata;
283146733Spjd	int first_error, error;
28459751Speter
28591040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
28691040Sarr	    " in %s\n", lf->filename));
28759751Speter
28891068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
28991040Sarr	    &stop, 0) != 0) {
29091040Sarr		/*
29191040Sarr		 * This fallback should be unnecessary, but if we get booted
29291040Sarr		 * from boot2 instead of loader and we are missing our
29391040Sarr		 * metadata then we have to try the best we can.
29491040Sarr		 */
29591040Sarr		if (lf == linker_kernel_file) {
29691040Sarr			start = SET_BEGIN(modmetadata_set);
29791040Sarr			stop = SET_LIMIT(modmetadata_set);
29891040Sarr		} else
29991040Sarr			return (0);
30078161Speter	}
301146733Spjd	first_error = 0;
30291040Sarr	for (mdp = start; mdp < stop; mdp++) {
30391040Sarr		if ((*mdp)->md_type != MDT_MODULE)
30491040Sarr			continue;
30591040Sarr		moddata = (*mdp)->md_data;
30691040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
30791040Sarr		    moddata->name, lf->filename));
30891040Sarr		error = module_register(moddata, lf);
309146730Spjd		if (error) {
31091068Sarr			printf("Module %s failed to register: %d\n",
31191040Sarr			    moddata->name, error);
312146733Spjd			if (first_error == 0)
313146733Spjd				first_error = error;
314146730Spjd		}
31559751Speter	}
316146733Spjd	return (first_error);
31759751Speter}
31859751Speter
31959751Speterstatic void
32059751Speterlinker_init_kernel_modules(void)
32159751Speter{
32291040Sarr
32391040Sarr	linker_file_register_modules(linker_kernel_file);
32459751Speter}
32559751Speter
32691040SarrSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 0)
32759751Speter
328101241Smuxstatic int
32991040Sarrlinker_load_file(const char *filename, linker_file_t *result)
33025537Sdfr{
33191040Sarr	linker_class_t lc;
33291040Sarr	linker_file_t lf;
33391040Sarr	int foundfile, error = 0;
33425537Sdfr
33591040Sarr	/* Refuse to load modules if securelevel raised */
33691040Sarr	if (securelevel > 0)
33791040Sarr		return (EPERM);
33862261Sarchie
33991040Sarr	lf = linker_find_file_by_name(filename);
34091040Sarr	if (lf) {
34191040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
34291040Sarr		    " incrementing refs\n", filename));
34391040Sarr		*result = lf;
34491040Sarr		lf->refs++;
34591040Sarr		goto out;
34691040Sarr	}
34791040Sarr	lf = NULL;
34891040Sarr	foundfile = 0;
34998452Sarr
35098452Sarr	/*
35198452Sarr	 * We do not need to protect (lock) classes here because there is
35298452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
35398452Sarr	 * and there is no class deregistration mechanism at this time.
35498452Sarr	 */
35591040Sarr	TAILQ_FOREACH(lc, &classes, link) {
35691040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
35791040Sarr		    filename));
35891040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
35991040Sarr		/*
36091040Sarr		 * If we got something other than ENOENT, then it exists but
36191040Sarr		 * we cannot load it for some other reason.
36291040Sarr		 */
36391040Sarr		if (error != ENOENT)
36491040Sarr			foundfile = 1;
36591040Sarr		if (lf) {
366146730Spjd			error = linker_file_register_modules(lf);
367146730Spjd			if (error == EEXIST) {
368146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
369146730Spjd				goto out;
370146730Spjd			}
37191040Sarr			linker_file_register_sysctls(lf);
37291040Sarr			linker_file_sysinit(lf);
37391040Sarr			lf->flags |= LINKER_FILE_LINKED;
37491040Sarr			*result = lf;
37591040Sarr			error = 0;
37691040Sarr			goto out;
37791040Sarr		}
37891040Sarr	}
37942755Speter	/*
38091040Sarr	 * Less than ideal, but tells the user whether it failed to load or
38191040Sarr	 * the module was not found.
38242755Speter	 */
383105337Ssam	if (foundfile) {
384105337Ssam		/*
385105337Ssam		 * Format not recognized or otherwise unloadable.
386105337Ssam		 * When loading a module that is statically built into
387105337Ssam		 * the kernel EEXIST percolates back up as the return
388105337Ssam		 * value.  Preserve this so that apps like sysinstall
389105337Ssam		 * can recognize this special case and not post bogus
390105337Ssam		 * dialog boxes.
391105337Ssam		 */
392105337Ssam		if (error != EEXIST)
393105337Ssam			error = ENOEXEC;
394105337Ssam	} else
39591068Sarr		error = ENOENT;		/* Nothing found */
39625537Sdfrout:
39791040Sarr	return (error);
39825537Sdfr}
39925537Sdfr
40078413Sbrianint
40194321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
40294321Sbrian    linker_file_t *result)
40378413Sbrian{
40494321Sbrian	modlist_t mod;
40594321Sbrian
40694321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
40794321Sbrian		*result = mod->container;
40894321Sbrian		(*result)->refs++;
40994321Sbrian		return (0);
41094321Sbrian	}
41194321Sbrian
41294321Sbrian	return (linker_load_module(NULL, modname, NULL, verinfo, result));
41378413Sbrian}
41478413Sbrian
41525537Sdfrlinker_file_t
41691040Sarrlinker_find_file_by_name(const char *filename)
41725537Sdfr{
41891040Sarr	linker_file_t lf = 0;
41991040Sarr	char *koname;
42025537Sdfr
421111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
42291040Sarr	if (koname == NULL)
42391040Sarr		goto out;
42491040Sarr	sprintf(koname, "%s.ko", filename);
42540861Speter
42698452Sarr	mtx_lock(&kld_mtx);
42791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
42892032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
42991040Sarr			break;
43092032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
43191040Sarr			break;
43291040Sarr	}
43398452Sarr	mtx_unlock(&kld_mtx);
43440861Speterout:
43591040Sarr	if (koname)
43691040Sarr		free(koname, M_LINKER);
43791040Sarr	return (lf);
43825537Sdfr}
43925537Sdfr
44025537Sdfrlinker_file_t
44125537Sdfrlinker_find_file_by_id(int fileid)
44225537Sdfr{
44391040Sarr	linker_file_t lf = 0;
44498452Sarr
44598452Sarr	mtx_lock(&kld_mtx);
44691040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
44791040Sarr		if (lf->id == fileid)
44891040Sarr			break;
44998452Sarr	mtx_unlock(&kld_mtx);
45091040Sarr	return (lf);
45125537Sdfr}
45225537Sdfr
45325537Sdfrlinker_file_t
45491040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
45525537Sdfr{
45691040Sarr	linker_file_t lf;
45791040Sarr	const char *filename;
45825537Sdfr
45991040Sarr	lf = NULL;
46091040Sarr	filename = linker_basename(pathname);
46140159Speter
46291040Sarr	KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
463111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
46491040Sarr	if (lf == NULL)
46591040Sarr		goto out;
46691040Sarr	lf->refs = 1;
46791040Sarr	lf->userrefs = 0;
46891040Sarr	lf->flags = 0;
46991040Sarr	lf->filename = linker_strdup(filename);
47091040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
47191040Sarr	lf->ndeps = 0;
47291040Sarr	lf->deps = NULL;
47391040Sarr	STAILQ_INIT(&lf->common);
47491040Sarr	TAILQ_INIT(&lf->modules);
47598452Sarr	mtx_lock(&kld_mtx);
47691040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
47798452Sarr	mtx_unlock(&kld_mtx);
47825537Sdfrout:
47991040Sarr	return (lf);
48025537Sdfr}
48125537Sdfr
48225537Sdfrint
483132117Sphklinker_file_unload(linker_file_t file, int flags)
48425537Sdfr{
48591040Sarr	module_t mod, next;
48691040Sarr	modlist_t ml, nextml;
48791040Sarr	struct common_symbol *cp;
48891040Sarr	int error, i;
48925537Sdfr
49091040Sarr	error = 0;
49162261Sarchie
49291040Sarr	/* Refuse to unload modules if securelevel raised. */
49391040Sarr	if (securelevel > 0)
49491040Sarr		return (EPERM);
495107089Srwatson#ifdef MAC
496107089Srwatson	error = mac_check_kld_unload(curthread->td_ucred);
497107089Srwatson	if (error)
498107089Srwatson		return (error);
499107089Srwatson#endif
50025537Sdfr
50191040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
50291040Sarr	if (file->refs == 1) {
50391040Sarr		KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
50491040Sarr		    " informing modules\n"));
50591040Sarr
50691040Sarr		/*
50791040Sarr		 * Inform any modules associated with this file.
50891040Sarr		 */
50992547Sarr		MOD_XLOCK;
51091040Sarr		for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
51191040Sarr			next = module_getfnext(mod);
51292547Sarr			MOD_XUNLOCK;
51391040Sarr
51491040Sarr			/*
51591040Sarr			 * Give the module a chance to veto the unload.
51691040Sarr			 */
517132117Sphk			if ((error = module_unload(mod, flags)) != 0) {
518109605Sjake				KLD_DPF(FILE, ("linker_file_unload: module %p"
51991040Sarr				    " vetoes unload\n", mod));
52091040Sarr				goto out;
52192547Sarr			} else
52292547Sarr				MOD_XLOCK;
52391040Sarr			module_release(mod);
52491040Sarr		}
52592547Sarr		MOD_XUNLOCK;
52691040Sarr	}
52791040Sarr	file->refs--;
52891040Sarr	if (file->refs > 0) {
52925537Sdfr		goto out;
53091040Sarr	}
53191040Sarr	for (ml = TAILQ_FIRST(&found_modules); ml; ml = nextml) {
53291040Sarr		nextml = TAILQ_NEXT(ml, link);
533128057Speadar		if (ml->container == file) {
53491040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
535128057Speadar			free(ml, M_LINKER);
536128057Speadar		}
53791040Sarr	}
53825537Sdfr
53991040Sarr	/*
54091040Sarr	 * Don't try to run SYSUNINITs if we are unloaded due to a
54191040Sarr	 * link error.
54291040Sarr	 */
54391040Sarr	if (file->flags & LINKER_FILE_LINKED) {
54491040Sarr		linker_file_sysuninit(file);
54591040Sarr		linker_file_unregister_sysctls(file);
54625537Sdfr	}
54798452Sarr	mtx_lock(&kld_mtx);
54891040Sarr	TAILQ_REMOVE(&linker_files, file, link);
54998452Sarr	mtx_unlock(&kld_mtx);
55025537Sdfr
55191040Sarr	if (file->deps) {
55291040Sarr		for (i = 0; i < file->ndeps; i++)
553132117Sphk			linker_file_unload(file->deps[i], flags);
55491040Sarr		free(file->deps, M_LINKER);
55591040Sarr		file->deps = NULL;
55659751Speter	}
55791040Sarr	for (cp = STAILQ_FIRST(&file->common); cp;
55891068Sarr	    cp = STAILQ_FIRST(&file->common)) {
55991040Sarr		STAILQ_REMOVE(&file->common, cp, common_symbol, link);
56091040Sarr		free(cp, M_LINKER);
56191040Sarr	}
56259751Speter
56391040Sarr	LINKER_UNLOAD(file);
56491040Sarr	if (file->filename) {
56591040Sarr		free(file->filename, M_LINKER);
56691040Sarr		file->filename = NULL;
56791040Sarr	}
56891040Sarr	kobj_delete((kobj_t) file, M_LINKER);
56925537Sdfrout:
57091040Sarr	return (error);
57125537Sdfr}
57225537Sdfr
57325537Sdfrint
57486469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
57525537Sdfr{
57691040Sarr	linker_file_t *newdeps;
57725537Sdfr
57891040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
579111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
58091040Sarr	if (newdeps == NULL)
58191040Sarr		return (ENOMEM);
58225537Sdfr
58391040Sarr	if (file->deps) {
58491040Sarr		bcopy(file->deps, newdeps,
58591040Sarr		    file->ndeps * sizeof(linker_file_t *));
58691040Sarr		free(file->deps, M_LINKER);
58791040Sarr	}
58891040Sarr	file->deps = newdeps;
58991040Sarr	file->deps[file->ndeps] = dep;
59091040Sarr	file->ndeps++;
59191040Sarr	return (0);
59225537Sdfr}
59325537Sdfr
59478161Speter/*
59591040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
59691040Sarr * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void ***
59778161Speter */
59878161Speterint
59978161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
60091040Sarr    void *firstp, void *lastp, int *countp)
60178161Speter{
60278161Speter
60391040Sarr	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
60478161Speter}
60578161Speter
60625537Sdfrcaddr_t
60791040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
60825537Sdfr{
60991040Sarr	c_linker_sym_t sym;
61091040Sarr	linker_symval_t symval;
61191040Sarr	caddr_t address;
61291040Sarr	size_t common_size = 0;
61392032Sdwmalone	int i;
61425537Sdfr
615109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
61691040Sarr	    file, name, deps));
61725537Sdfr
61891040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
61991040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
62091040Sarr		if (symval.value == 0)
62191040Sarr			/*
62291040Sarr			 * For commons, first look them up in the
62391040Sarr			 * dependencies and only allocate space if not found
62491040Sarr			 * there.
62591040Sarr			 */
62691040Sarr			common_size = symval.size;
62791040Sarr		else {
62891040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
629109605Sjake			    ".value=%p\n", symval.value));
63091040Sarr			return (symval.value);
63191040Sarr		}
63240159Speter	}
63391040Sarr	if (deps) {
63491040Sarr		for (i = 0; i < file->ndeps; i++) {
63591040Sarr			address = linker_file_lookup_symbol(file->deps[i],
63691040Sarr			    name, 0);
63791040Sarr			if (address) {
63891040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
639109605Sjake				    " deps value=%p\n", address));
64091040Sarr				return (address);
64191040Sarr			}
64291040Sarr		}
64325537Sdfr	}
64491040Sarr	if (common_size > 0) {
64591040Sarr		/*
64691040Sarr		 * This is a common symbol which was not found in the
64791040Sarr		 * dependencies.  We maintain a simple common symbol table in
64891040Sarr		 * the file object.
64991040Sarr		 */
65091040Sarr		struct common_symbol *cp;
65142849Speter
65291040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
65392032Sdwmalone			if (strcmp(cp->name, name) == 0) {
65491040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
655109605Sjake				    " old common value=%p\n", cp->address));
65691040Sarr				return (cp->address);
65791040Sarr			}
65891040Sarr		}
65991040Sarr		/*
66091040Sarr		 * Round the symbol size up to align.
66191040Sarr		 */
66291040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
66391040Sarr		cp = malloc(sizeof(struct common_symbol)
66491040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
665111119Simp		    M_WAITOK | M_ZERO);
66691040Sarr		if (cp == NULL) {
66791040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
66891040Sarr			return (0);
66991040Sarr		}
67091040Sarr		cp->address = (caddr_t)(cp + 1);
67191040Sarr		cp->name = cp->address + common_size;
67291040Sarr		strcpy(cp->name, name);
67391040Sarr		bzero(cp->address, common_size);
67491040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
67525537Sdfr
67691040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
677109605Sjake		    " value=%p\n", cp->address));
67891040Sarr		return (cp->address);
67940159Speter	}
68091040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
68191040Sarr	return (0);
68225537Sdfr}
68325537Sdfr
68440159Speter#ifdef DDB
68525537Sdfr/*
68691040Sarr * DDB Helpers.  DDB has to look across multiple files with their own symbol
68791040Sarr * tables and string tables.
68891040Sarr *
68991040Sarr * Note that we do not obey list locking protocols here.  We really don't need
69091040Sarr * DDB to hang because somebody's got the lock held.  We'll take the chance
69191040Sarr * that the files list is inconsistant instead.
69240159Speter */
69340159Speter
69440159Speterint
69543309Sdillonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
69640159Speter{
69791040Sarr	linker_file_t lf;
69840159Speter
69991040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
70091040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
70191040Sarr			return (0);
70291040Sarr	}
70391040Sarr	return (ENOENT);
70440159Speter}
70540159Speter
70640159Speterint
70743309Sdillonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
70840159Speter{
70991040Sarr	linker_file_t lf;
71091040Sarr	c_linker_sym_t best, es;
71191040Sarr	u_long diff, bestdiff, off;
71240159Speter
71391040Sarr	best = 0;
71491040Sarr	off = (uintptr_t)value;
71591040Sarr	bestdiff = off;
71691040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
71791040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
71891040Sarr			continue;
71991040Sarr		if (es != 0 && diff < bestdiff) {
72091040Sarr			best = es;
72191040Sarr			bestdiff = diff;
72291040Sarr		}
72391040Sarr		if (bestdiff == 0)
72491040Sarr			break;
72540159Speter	}
72691040Sarr	if (best) {
72791040Sarr		*sym = best;
72891040Sarr		*diffp = bestdiff;
72991040Sarr		return (0);
73091040Sarr	} else {
73191040Sarr		*sym = 0;
73291040Sarr		*diffp = off;
73391040Sarr		return (ENOENT);
73491040Sarr	}
73540159Speter}
73640159Speter
73740159Speterint
73843309Sdillonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
73940159Speter{
74091040Sarr	linker_file_t lf;
74140159Speter
74291040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
74391040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
74491040Sarr			return (0);
74591040Sarr	}
74691040Sarr	return (ENOENT);
74740159Speter}
74840159Speter#endif
74940159Speter
75040159Speter/*
75125537Sdfr * Syscalls.
75225537Sdfr */
75382749Sdillon/*
75482749Sdillon * MPSAFE
75582749Sdillon */
75625537Sdfrint
75791040Sarrkldload(struct thread *td, struct kldload_args *uap)
75825537Sdfr{
759157144Sjkoshy#ifdef HWPMC_HOOKS
760157144Sjkoshy	struct pmckern_map_in pkm;
761157144Sjkoshy#endif
76291040Sarr	char *kldname, *modname;
76391040Sarr	char *pathname = NULL;
76491040Sarr	linker_file_t lf;
76591040Sarr	int error = 0;
76625537Sdfr
76791040Sarr	td->td_retval[0] = -1;
76825537Sdfr
76991040Sarr	mtx_lock(&Giant);
77082749Sdillon
77193159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
77293159Sarr		goto out;
77393159Sarr
77493593Sjhb	if ((error = suser(td)) != 0)
77591040Sarr		goto out;
77625537Sdfr
777111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
778107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
77991040Sarr		goto out;
78025537Sdfr
78191040Sarr	/*
78291040Sarr	 * If path do not contain qualified name or any dot in it
78391040Sarr	 * (kldname.ko, or kldname.ver.ko) treat it as interface
78491040Sarr	 * name.
78591040Sarr	 */
78691040Sarr	if (index(pathname, '/') || index(pathname, '.')) {
78791040Sarr		kldname = pathname;
78891040Sarr		modname = NULL;
78991040Sarr	} else {
79091040Sarr		kldname = NULL;
79191040Sarr		modname = pathname;
79291040Sarr	}
79391040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
79491040Sarr	if (error)
79591040Sarr		goto out;
79642316Smsmith
797157144Sjkoshy#ifdef HWPMC_HOOKS
798157144Sjkoshy	pkm.pm_file = lf->filename;
799157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
800157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
801157144Sjkoshy#endif
80291040Sarr	lf->userrefs++;
80391040Sarr	td->td_retval[0] = lf->id;
80425537Sdfrout:
80591040Sarr	if (pathname)
80691040Sarr		free(pathname, M_TEMP);
80791040Sarr	mtx_unlock(&Giant);
80891040Sarr	return (error);
80925537Sdfr}
81025537Sdfr
81182749Sdillon/*
81282749Sdillon * MPSAFE
81382749Sdillon */
814132117Sphkstatic int
815132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
81625537Sdfr{
817157144Sjkoshy#ifdef HWPMC_HOOKS
818157144Sjkoshy	struct pmckern_map_out pkm;
819157144Sjkoshy#endif
82091040Sarr	linker_file_t lf;
82191040Sarr	int error = 0;
82225537Sdfr
82391040Sarr	mtx_lock(&Giant);
82482749Sdillon
82593159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
82693159Sarr		goto out;
82793159Sarr
82893593Sjhb	if ((error = suser(td)) != 0)
82991040Sarr		goto out;
83025537Sdfr
831132117Sphk	lf = linker_find_file_by_id(fileid);
83291040Sarr	if (lf) {
83391040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
83491040Sarr		if (lf->userrefs == 0) {
835132117Sphk			/*
836132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
837132117Sphk			 */
83891040Sarr			printf("kldunload: attempt to unload file that was"
83991040Sarr			    " loaded by the kernel\n");
84091040Sarr			error = EBUSY;
84191040Sarr			goto out;
84291040Sarr		}
84391068Sarr		lf->userrefs--;
844157144Sjkoshy#ifdef HWPMC_HOOKS
845157144Sjkoshy		/* Save data needed by hwpmc(4) before unloading the kld. */
846157144Sjkoshy		pkm.pm_address = (uintptr_t) lf->address;
847157144Sjkoshy		pkm.pm_size = lf->size;
848157144Sjkoshy#endif
849132117Sphk		error = linker_file_unload(lf, flags);
85091040Sarr		if (error)
85191040Sarr			lf->userrefs++;
85291040Sarr	} else
85391040Sarr		error = ENOENT;
854157144Sjkoshy
855157144Sjkoshy#ifdef HWPMC_HOOKS
856157144Sjkoshy	if (error == 0)
857157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
858157144Sjkoshy#endif
85925537Sdfrout:
86091068Sarr	mtx_unlock(&Giant);
86191068Sarr	return (error);
86225537Sdfr}
86325537Sdfr
86482749Sdillon/*
86582749Sdillon * MPSAFE
86682749Sdillon */
86725537Sdfrint
868132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
869132117Sphk{
870132117Sphk
871132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
872132117Sphk}
873132117Sphk
874132117Sphk/*
875132117Sphk * MPSAFE
876132117Sphk */
877132117Sphkint
878132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
879132117Sphk{
880132117Sphk
881132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
882132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
883132117Sphk		return (EINVAL);
884132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
885132117Sphk}
886132117Sphk
887132117Sphk/*
888132117Sphk * MPSAFE
889132117Sphk */
890132117Sphkint
89191040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
89225537Sdfr{
89391040Sarr	char *pathname;
89491040Sarr	const char *filename;
89591040Sarr	linker_file_t lf;
89691040Sarr	int error = 0;
89725537Sdfr
898107089Srwatson#ifdef MAC
899107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
900107089Srwatson	if (error)
901107089Srwatson		return (error);
902107089Srwatson#endif
903107089Srwatson
90491040Sarr	mtx_lock(&Giant);
90591040Sarr	td->td_retval[0] = -1;
90682749Sdillon
907111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
908107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
90991040Sarr		goto out;
91025537Sdfr
91191040Sarr	filename = linker_basename(pathname);
91291040Sarr	lf = linker_find_file_by_name(filename);
91391040Sarr	if (lf)
91491040Sarr		td->td_retval[0] = lf->id;
91591040Sarr	else
91691040Sarr		error = ENOENT;
91725537Sdfrout:
91891040Sarr	if (pathname)
91991040Sarr		free(pathname, M_TEMP);
92091040Sarr	mtx_unlock(&Giant);
92191040Sarr	return (error);
92225537Sdfr}
92325537Sdfr
92482749Sdillon/*
92582749Sdillon * MPSAFE
92682749Sdillon */
92725537Sdfrint
92891040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
92925537Sdfr{
93091040Sarr	linker_file_t lf;
93191040Sarr	int error = 0;
93225537Sdfr
933107089Srwatson#ifdef MAC
934107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
935107089Srwatson	if (error)
936107089Srwatson		return (error);
937107089Srwatson#endif
938107089Srwatson
93991040Sarr	mtx_lock(&Giant);
94082749Sdillon
941107849Salfred	if (uap->fileid == 0) {
94298452Sarr		mtx_lock(&kld_mtx);
94391040Sarr		if (TAILQ_FIRST(&linker_files))
94491040Sarr			td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
94591040Sarr		else
94691040Sarr			td->td_retval[0] = 0;
94798452Sarr		mtx_unlock(&kld_mtx);
94891040Sarr		goto out;
94991040Sarr	}
950107849Salfred	lf = linker_find_file_by_id(uap->fileid);
95191040Sarr	if (lf) {
95291040Sarr		if (TAILQ_NEXT(lf, link))
95391040Sarr			td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
95491040Sarr		else
95591040Sarr			td->td_retval[0] = 0;
95691040Sarr	} else
95791040Sarr		error = ENOENT;
95882749Sdillonout:
95991040Sarr	mtx_unlock(&Giant);
96091040Sarr	return (error);
96125537Sdfr}
96225537Sdfr
96382749Sdillon/*
96482749Sdillon * MPSAFE
96582749Sdillon */
96625537Sdfrint
96791040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
96825537Sdfr{
96991040Sarr	linker_file_t lf;
97091040Sarr	int error = 0;
97191040Sarr	int namelen, version;
97291040Sarr	struct kld_file_stat *stat;
97325537Sdfr
974107089Srwatson#ifdef MAC
975107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
976107089Srwatson	if (error)
977107089Srwatson		return (error);
978107089Srwatson#endif
979107089Srwatson
98091040Sarr	mtx_lock(&Giant);
98182749Sdillon
982107849Salfred	lf = linker_find_file_by_id(uap->fileid);
98391040Sarr	if (lf == NULL) {
98491040Sarr		error = ENOENT;
98591040Sarr		goto out;
98691040Sarr	}
987107849Salfred	stat = uap->stat;
98825537Sdfr
98991040Sarr	/*
99091040Sarr	 * Check the version of the user's structure.
99191040Sarr	 */
99291040Sarr	if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
99391040Sarr		goto out;
99491040Sarr	if (version != sizeof(struct kld_file_stat)) {
99591040Sarr		error = EINVAL;
99691040Sarr		goto out;
99791040Sarr	}
99891040Sarr	namelen = strlen(lf->filename) + 1;
99991040Sarr	if (namelen > MAXPATHLEN)
100091040Sarr		namelen = MAXPATHLEN;
100191040Sarr	if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0)
100291040Sarr		goto out;
100391040Sarr	if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0)
100491040Sarr		goto out;
100591040Sarr	if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0)
100691040Sarr		goto out;
100791040Sarr	if ((error = copyout(&lf->address, &stat->address,
100891040Sarr	    sizeof(caddr_t))) != 0)
100991040Sarr		goto out;
101091040Sarr	if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0)
101191040Sarr		goto out;
101225537Sdfr
101391040Sarr	td->td_retval[0] = 0;
101425537Sdfrout:
101591040Sarr	mtx_unlock(&Giant);
101691040Sarr	return (error);
101725537Sdfr}
101825537Sdfr
101982749Sdillon/*
102082749Sdillon * MPSAFE
102182749Sdillon */
102225537Sdfrint
102391040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
102425537Sdfr{
102591040Sarr	linker_file_t lf;
102691040Sarr	module_t mp;
102791040Sarr	int error = 0;
102825537Sdfr
1029107089Srwatson#ifdef MAC
1030107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1031107089Srwatson	if (error)
1032107089Srwatson		return (error);
1033107089Srwatson#endif
1034107089Srwatson
103591040Sarr	mtx_lock(&Giant);
1036107849Salfred	lf = linker_find_file_by_id(uap->fileid);
103791040Sarr	if (lf) {
103892547Sarr		MOD_SLOCK;
103991040Sarr		mp = TAILQ_FIRST(&lf->modules);
104091040Sarr		if (mp != NULL)
104191040Sarr			td->td_retval[0] = module_getid(mp);
104291040Sarr		else
104391040Sarr			td->td_retval[0] = 0;
104492547Sarr		MOD_SUNLOCK;
104591040Sarr	} else
104691040Sarr		error = ENOENT;
104791040Sarr	mtx_unlock(&Giant);
104891040Sarr	return (error);
104925537Sdfr}
105040159Speter
105182749Sdillon/*
105282749Sdillon * MPSAFE
105382749Sdillon */
105441090Speterint
105583366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
105641090Speter{
105791040Sarr	char *symstr = NULL;
105891040Sarr	c_linker_sym_t sym;
105991040Sarr	linker_symval_t symval;
106091040Sarr	linker_file_t lf;
106191040Sarr	struct kld_sym_lookup lookup;
106291040Sarr	int error = 0;
106341090Speter
1064107089Srwatson#ifdef MAC
1065107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1066107089Srwatson	if (error)
1067107089Srwatson		return (error);
1068107089Srwatson#endif
1069107089Srwatson
107091040Sarr	mtx_lock(&Giant);
107182749Sdillon
1072107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
107391040Sarr		goto out;
107491068Sarr	if (lookup.version != sizeof(lookup) ||
1075107849Salfred	    uap->cmd != KLDSYM_LOOKUP) {
107691040Sarr		error = EINVAL;
107791040Sarr		goto out;
107891040Sarr	}
1079111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
108091040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
108191040Sarr		goto out;
1082107849Salfred	if (uap->fileid != 0) {
1083107849Salfred		lf = linker_find_file_by_id(uap->fileid);
108491040Sarr		if (lf == NULL) {
108591040Sarr			error = ENOENT;
108691040Sarr			goto out;
108791040Sarr		}
108891040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
108991040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
109091040Sarr			lookup.symvalue = (uintptr_t) symval.value;
109191040Sarr			lookup.symsize = symval.size;
1092107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
109391040Sarr		} else
109491040Sarr			error = ENOENT;
109591040Sarr	} else {
109698452Sarr		mtx_lock(&kld_mtx);
109791040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
109891040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
109991040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
110091040Sarr				lookup.symvalue = (uintptr_t)symval.value;
110191040Sarr				lookup.symsize = symval.size;
1102107849Salfred				error = copyout(&lookup, uap->data,
110391040Sarr				    sizeof(lookup));
110491068Sarr				break;
110591040Sarr			}
110691040Sarr		}
110798452Sarr		mtx_unlock(&kld_mtx);
110891040Sarr		if (lf == NULL)
110991040Sarr			error = ENOENT;
111041090Speter	}
111141090Speterout:
111291040Sarr	if (symstr)
111391040Sarr		free(symstr, M_TEMP);
111491040Sarr	mtx_unlock(&Giant);
111591040Sarr	return (error);
111641090Speter}
111741090Speter
111840159Speter/*
111940159Speter * Preloaded module support
112040159Speter */
112140159Speter
112259751Speterstatic modlist_t
112374642Sbpmodlist_lookup(const char *name, int ver)
112459751Speter{
112591040Sarr	modlist_t mod;
112659751Speter
112791040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
112892032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
112992032Sdwmalone		    (ver == 0 || mod->version == ver))
113091040Sarr			return (mod);
113191040Sarr	}
113291040Sarr	return (NULL);
113359751Speter}
113459751Speter
113574642Sbpstatic modlist_t
113683321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
113783321Speter{
113891040Sarr	modlist_t mod, bestmod;
113992032Sdwmalone	int ver;
114083321Speter
114191040Sarr	if (verinfo == NULL)
114291040Sarr		return (modlist_lookup(name, 0));
114391040Sarr	bestmod = NULL;
114491040Sarr	for (mod = TAILQ_FIRST(&found_modules); mod;
114591040Sarr	    mod = TAILQ_NEXT(mod, link)) {
114692032Sdwmalone		if (strcmp(mod->name, name) != 0)
114791040Sarr			continue;
114891040Sarr		ver = mod->version;
114991040Sarr		if (ver == verinfo->md_ver_preferred)
115091040Sarr			return (mod);
115191040Sarr		if (ver >= verinfo->md_ver_minimum &&
115291068Sarr		    ver <= verinfo->md_ver_maximum &&
1153120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
115491040Sarr			bestmod = mod;
115591040Sarr	}
115691040Sarr	return (bestmod);
115783321Speter}
115883321Speter
115983321Speterstatic modlist_t
116078501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
116174642Sbp{
116291040Sarr	modlist_t mod;
116374642Sbp
116492705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
116591040Sarr	if (mod == NULL)
116691040Sarr		panic("no memory for module list");
116791040Sarr	mod->container = container;
116891040Sarr	mod->name = modname;
116991040Sarr	mod->version = version;
117091040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
117191040Sarr	return (mod);
117274642Sbp}
117374642Sbp
117440159Speterstatic void
117578161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
117691040Sarr    struct mod_metadata **stop, int preload)
117774642Sbp{
117891040Sarr	struct mod_metadata *mp, **mdp;
117991040Sarr	const char *modname;
118091040Sarr	int ver;
118174642Sbp
118291040Sarr	for (mdp = start; mdp < stop; mdp++) {
1183109605Sjake		mp = *mdp;
118491040Sarr		if (mp->md_type != MDT_VERSION)
118591040Sarr			continue;
1186109605Sjake		modname = mp->md_cval;
1187109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
118891040Sarr		if (modlist_lookup(modname, ver) != NULL) {
118991040Sarr			printf("module %s already present!\n", modname);
119091040Sarr			/* XXX what can we do? this is a build error. :-( */
119191040Sarr			continue;
119291040Sarr		}
119391040Sarr		modlist_newmodule(modname, ver, lf);
119474642Sbp	}
119574642Sbp}
119674642Sbp
119774642Sbpstatic void
119891040Sarrlinker_preload(void *arg)
119940159Speter{
120091040Sarr	caddr_t modptr;
120191040Sarr	const char *modname, *nmodname;
120291040Sarr	char *modtype;
120391040Sarr	linker_file_t lf;
120491040Sarr	linker_class_t lc;
120592032Sdwmalone	int error;
120691040Sarr	linker_file_list_t loaded_files;
120791040Sarr	linker_file_list_t depended_files;
120891040Sarr	struct mod_metadata *mp, *nmp;
120991040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
121091040Sarr	struct mod_depend *verinfo;
121191040Sarr	int nver;
121291040Sarr	int resolves;
121391040Sarr	modlist_t mod;
121491040Sarr	struct sysinit **si_start, **si_stop;
121540159Speter
121691040Sarr	TAILQ_INIT(&loaded_files);
121791040Sarr	TAILQ_INIT(&depended_files);
121891040Sarr	TAILQ_INIT(&found_modules);
121991040Sarr	error = 0;
122059751Speter
122191040Sarr	modptr = NULL;
122291040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
122391040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
122491040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
122591040Sarr		if (modname == NULL) {
122691040Sarr			printf("Preloaded module at %p does not have a"
122791040Sarr			    " name!\n", modptr);
122891040Sarr			continue;
122991040Sarr		}
123091040Sarr		if (modtype == NULL) {
123191040Sarr			printf("Preloaded module at %p does not have a type!\n",
123291040Sarr			    modptr);
123391040Sarr			continue;
123491040Sarr		}
1235131398Sjhb		if (bootverbose)
1236131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1237131398Sjhb			    modptr);
123840159Speter		lf = NULL;
123991040Sarr		TAILQ_FOREACH(lc, &classes, link) {
124091040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1241134364Siedowse			if (!error)
124291040Sarr				break;
1243134364Siedowse			lf = NULL;
124491040Sarr		}
124591040Sarr		if (lf)
124691040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
124740159Speter	}
124840159Speter
124991040Sarr	/*
125091040Sarr	 * First get a list of stuff in the kernel.
125191040Sarr	 */
125291040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
125391040Sarr	    &stop, NULL) == 0)
125491040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
125559751Speter
125659751Speter	/*
125791040Sarr	 * this is a once-off kinky bubble sort resolve relocation dependency
125891040Sarr	 * requirements
125959751Speter	 */
126091040Sarrrestart:
126191040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
126291040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
126391040Sarr		    &stop, NULL);
126491040Sarr		/*
126591040Sarr		 * First, look to see if we would successfully link with this
126691040Sarr		 * stuff.
126791040Sarr		 */
126891040Sarr		resolves = 1;	/* unless we know otherwise */
126991040Sarr		if (!error) {
127091040Sarr			for (mdp = start; mdp < stop; mdp++) {
1271109605Sjake				mp = *mdp;
127291040Sarr				if (mp->md_type != MDT_DEPEND)
127391040Sarr					continue;
1274109605Sjake				modname = mp->md_cval;
1275109605Sjake				verinfo = mp->md_data;
127691040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1277109605Sjake					nmp = *nmdp;
127891040Sarr					if (nmp->md_type != MDT_VERSION)
127991040Sarr						continue;
1280109605Sjake					nmodname = nmp->md_cval;
128192032Sdwmalone					if (strcmp(modname, nmodname) == 0)
128291040Sarr						break;
128391040Sarr				}
128491040Sarr				if (nmdp < stop)   /* it's a self reference */
128591040Sarr					continue;
128691040Sarr
128791040Sarr				/*
128891040Sarr				 * ok, the module isn't here yet, we
128991040Sarr				 * are not finished
129091040Sarr				 */
129191068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
129291040Sarr					resolves = 0;
129391040Sarr			}
129464143Speter		}
129591040Sarr		/*
129691040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
129791040Sarr		 * the modules inside and add it to the end of the link order
129891040Sarr		 * list.
129991040Sarr		 */
130091040Sarr		if (resolves) {
130191040Sarr			if (!error) {
130291040Sarr				for (mdp = start; mdp < stop; mdp++) {
1303109605Sjake					mp = *mdp;
130491040Sarr					if (mp->md_type != MDT_VERSION)
130591040Sarr						continue;
1306109605Sjake					modname = mp->md_cval;
1307109605Sjake					nver = ((struct mod_version *)
1308109605Sjake					    mp->md_data)->mv_version;
130991040Sarr					if (modlist_lookup(modname,
131091040Sarr					    nver) != NULL) {
131191040Sarr						printf("module %s already"
131291040Sarr						    " present!\n", modname);
1313132117Sphk						linker_file_unload(lf,
1314132117Sphk						    LINKER_UNLOAD_FORCE);
131591040Sarr						TAILQ_REMOVE(&loaded_files,
131691040Sarr						    lf, loaded);
131791040Sarr						/* we changed tailq next ptr */
131891068Sarr						goto restart;
131991040Sarr					}
132091040Sarr					modlist_newmodule(modname, nver, lf);
132191040Sarr				}
132291040Sarr			}
132391040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
132491040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
132591040Sarr			/*
132691040Sarr			 * Since we provided modules, we need to restart the
132791040Sarr			 * sort so that the previous files that depend on us
132891040Sarr			 * have a chance. Also, we've busted the tailq next
132991040Sarr			 * pointer with the REMOVE.
133091040Sarr			 */
133191040Sarr			goto restart;
133259751Speter		}
133359751Speter	}
133491040Sarr
133559751Speter	/*
133691040Sarr	 * At this point, we check to see what could not be resolved..
133759751Speter	 */
133891040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
133991040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1340132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
134191040Sarr		TAILQ_REMOVE(&loaded_files, lf, loaded);
134240159Speter	}
134359751Speter
134478161Speter	/*
134591040Sarr	 * We made it. Finish off the linking in the order we determined.
134678161Speter	 */
134791040Sarr	TAILQ_FOREACH(lf, &depended_files, loaded) {
134891040Sarr		if (linker_kernel_file) {
134991040Sarr			linker_kernel_file->refs++;
135091040Sarr			error = linker_file_add_dependency(lf,
135191040Sarr			    linker_kernel_file);
135291040Sarr			if (error)
135391040Sarr				panic("cannot add dependency");
135491040Sarr		}
135591040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
135691040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
135791040Sarr		    &stop, NULL);
135891040Sarr		if (!error) {
135991040Sarr			for (mdp = start; mdp < stop; mdp++) {
1360109605Sjake				mp = *mdp;
136191040Sarr				if (mp->md_type != MDT_DEPEND)
136291040Sarr					continue;
1363109605Sjake				modname = mp->md_cval;
1364109605Sjake				verinfo = mp->md_data;
136591040Sarr				mod = modlist_lookup2(modname, verinfo);
1366151484Sjdp				/* Don't count self-dependencies */
1367151484Sjdp				if (lf == mod->container)
1368151484Sjdp					continue;
136991040Sarr				mod->container->refs++;
137091040Sarr				error = linker_file_add_dependency(lf,
137191040Sarr				    mod->container);
137291040Sarr				if (error)
137391040Sarr					panic("cannot add dependency");
137491040Sarr			}
137591040Sarr		}
137691040Sarr		/*
137791040Sarr		 * Now do relocation etc using the symbol search paths
137891040Sarr		 * established by the dependencies
137991040Sarr		 */
138091040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
138191040Sarr		if (error) {
138291040Sarr			printf("KLD file %s - could not finalize loading\n",
138391040Sarr			    lf->filename);
1384132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
138591040Sarr			continue;
138691040Sarr		}
138791040Sarr		linker_file_register_modules(lf);
138891040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
138991040Sarr		    &si_stop, NULL) == 0)
139091040Sarr			sysinit_add(si_start, si_stop);
139191040Sarr		linker_file_register_sysctls(lf);
139291040Sarr		lf->flags |= LINKER_FILE_LINKED;
139359751Speter	}
139491040Sarr	/* woohoo! we made it! */
139540159Speter}
139640159Speter
139791040SarrSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0)
139840159Speter
139940159Speter/*
140040159Speter * Search for a not-loaded module by name.
140191040Sarr *
140240159Speter * Modules may be found in the following locations:
140391040Sarr *
140491040Sarr * - preloaded (result is just the module name) - on disk (result is full path
140591040Sarr * to module)
140691040Sarr *
140791040Sarr * If the module name is qualified in any way (contains path, etc.) the we
140891040Sarr * simply return a copy of it.
140991040Sarr *
141040159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
141140159Speter * character as a separator to be consistent with the bootloader.
141240159Speter */
141340159Speter
141483321Speterstatic char linker_hintfile[] = "linker.hints";
1415111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
141640159Speter
141740159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
141891040Sarr    sizeof(linker_path), "module load search path");
141940159Speter
142077843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
142170417Speter
142259751Speterstatic char *linker_ext_list[] = {
142383321Speter	"",
142459751Speter	".ko",
142559751Speter	NULL
142659751Speter};
142759751Speter
142883321Speter/*
142991040Sarr * Check if file actually exists either with or without extension listed in
143091040Sarr * the linker_ext_list. (probably should be generic for the rest of the
143191040Sarr * kernel)
143283321Speter */
143359751Speterstatic char *
143491040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
143591040Sarr    int namelen, struct vattr *vap)
143640159Speter{
143791040Sarr	struct nameidata nd;
143891040Sarr	struct thread *td = curthread;	/* XXX */
143991040Sarr	char *result, **cpp, *sep;
144091040Sarr	int error, len, extlen, reclen, flags;
144191040Sarr	enum vtype type;
144240159Speter
144391040Sarr	extlen = 0;
144491040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
144591040Sarr		len = strlen(*cpp);
144691040Sarr		if (len > extlen)
144791040Sarr			extlen = len;
144891040Sarr	}
144991040Sarr	extlen++;		/* trailing '\0' */
145091040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
145183321Speter
145291040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1453111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
145491040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
145591040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
145691040Sarr		    namelen, name, *cpp);
145791040Sarr		/*
145891040Sarr		 * Attempt to open the file, and return the path if
145991040Sarr		 * we succeed and it's a regular file.
146091040Sarr		 */
146191040Sarr		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
146291040Sarr		flags = FREAD;
1463118094Sphk		error = vn_open(&nd, &flags, 0, -1);
146491040Sarr		if (error == 0) {
146591040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
146691040Sarr			type = nd.ni_vp->v_type;
146791040Sarr			if (vap)
146891406Sjhb				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
146991040Sarr			VOP_UNLOCK(nd.ni_vp, 0, td);
147091406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
147191040Sarr			if (type == VREG)
147291040Sarr				return (result);
147391040Sarr		}
147483321Speter	}
147591040Sarr	free(result, M_LINKER);
147691040Sarr	return (NULL);
147783321Speter}
147883321Speter
147991040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
148083321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
148183321Speter
148283321Speter/*
148391040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
148491040Sarr * version specification is available, then try to find the best KLD.
148583321Speter * Otherwise just find the latest one.
148683321Speter */
148783321Speterstatic char *
148891040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
148991040Sarr    int modnamelen, struct mod_depend *verinfo)
149083321Speter{
149191040Sarr	struct thread *td = curthread;	/* XXX */
149291406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
149391040Sarr	struct nameidata nd;
149491040Sarr	struct vattr vattr, mattr;
149591040Sarr	u_char *hints = NULL;
149691040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
149791040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
149883321Speter
149991040Sarr	result = NULL;
150091040Sarr	bestver = found = 0;
150183321Speter
150291040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
150391040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
150491040Sarr	    strlen(sep) + 1;
1505111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
150691040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
150791040Sarr	    linker_hintfile);
150883321Speter
150991040Sarr	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
151091040Sarr	flags = FREAD;
1511118094Sphk	error = vn_open(&nd, &flags, 0, -1);
151291040Sarr	if (error)
151391040Sarr		goto bad;
151491040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
151591040Sarr	if (nd.ni_vp->v_type != VREG)
151691040Sarr		goto bad;
151791040Sarr	best = cp = NULL;
151891040Sarr	error = VOP_GETATTR(nd.ni_vp, &vattr, cred, td);
151991040Sarr	if (error)
152091040Sarr		goto bad;
152191040Sarr	/*
152291040Sarr	 * XXX: we need to limit this number to some reasonable value
152391040Sarr	 */
152491040Sarr	if (vattr.va_size > 100 * 1024) {
152591040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
152691040Sarr		goto bad;
152791040Sarr	}
1528111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
152991040Sarr	if (hints == NULL)
153091040Sarr		goto bad;
153191068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1532101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
153391040Sarr	if (error)
153491040Sarr		goto bad;
153599553Sjeff	VOP_UNLOCK(nd.ni_vp, 0, td);
153691040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
153791040Sarr	nd.ni_vp = NULL;
153891040Sarr	if (reclen != 0) {
153991040Sarr		printf("can't read %d\n", reclen);
154091040Sarr		goto bad;
154191040Sarr	}
154291040Sarr	intp = (int *)hints;
154383321Speter	ival = *intp++;
154491040Sarr	if (ival != LINKER_HINTS_VERSION) {
154591040Sarr		printf("hints file version mismatch %d\n", ival);
154691040Sarr		goto bad;
154783321Speter	}
154891040Sarr	bufend = hints + vattr.va_size;
154991040Sarr	recptr = (u_char *)intp;
155091040Sarr	clen = blen = 0;
155191040Sarr	while (recptr < bufend && !found) {
155291040Sarr		intp = (int *)recptr;
155391040Sarr		reclen = *intp++;
155491040Sarr		ival = *intp++;
155591040Sarr		cp = (char *)intp;
155691040Sarr		switch (ival) {
155791040Sarr		case MDT_VERSION:
155891040Sarr			clen = *cp++;
155991040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
156091040Sarr				break;
156191040Sarr			cp += clen;
156291040Sarr			INT_ALIGN(hints, cp);
156391040Sarr			ival = *(int *)cp;
156491040Sarr			cp += sizeof(int);
156591040Sarr			clen = *cp++;
156691040Sarr			if (verinfo == NULL ||
156791040Sarr			    ival == verinfo->md_ver_preferred) {
156891040Sarr				found = 1;
156991040Sarr				break;
157091040Sarr			}
157191040Sarr			if (ival >= verinfo->md_ver_minimum &&
157291040Sarr			    ival <= verinfo->md_ver_maximum &&
157391040Sarr			    ival > bestver) {
157491040Sarr				bestver = ival;
157591040Sarr				best = cp;
157691040Sarr				blen = clen;
157791040Sarr			}
157891040Sarr			break;
157991040Sarr		default:
158091040Sarr			break;
158191040Sarr		}
158291040Sarr		recptr += reclen + sizeof(int);
158391040Sarr	}
158483321Speter	/*
158591040Sarr	 * Finally check if KLD is in the place
158683321Speter	 */
158791040Sarr	if (found)
158891040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
158991040Sarr	else if (best)
159091040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
159191040Sarr
159291040Sarr	/*
159391040Sarr	 * KLD is newer than hints file. What we should do now?
159491040Sarr	 */
159591040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
159691040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
159791040Sarr		    " file\n", result);
159883321Speterbad:
1599105167Sphk	free(pathbuf, M_LINKER);
160091040Sarr	if (hints)
160191040Sarr		free(hints, M_TEMP);
160299553Sjeff	if (nd.ni_vp != NULL) {
160399553Sjeff		VOP_UNLOCK(nd.ni_vp, 0, td);
160491040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
160599553Sjeff	}
160691040Sarr	/*
160791040Sarr	 * If nothing found or hints is absent - fallback to the old
160891040Sarr	 * way by using "kldname[.ko]" as module name.
160991040Sarr	 */
161091040Sarr	if (!found && !bestver && result == NULL)
161191040Sarr		result = linker_lookup_file(path, pathlen, modname,
161291040Sarr		    modnamelen, NULL);
161391040Sarr	return (result);
161483321Speter}
161583321Speter
161683321Speter/*
161783321Speter * Lookup KLD which contains requested module in the all directories.
161883321Speter */
161983321Speterstatic char *
162083321Speterlinker_search_module(const char *modname, int modnamelen,
162191040Sarr    struct mod_depend *verinfo)
162283321Speter{
162391040Sarr	char *cp, *ep, *result;
162483321Speter
162591040Sarr	/*
162691040Sarr	 * traverse the linker path
162791040Sarr	 */
162891040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
162991040Sarr		/* find the end of this component */
163091040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
163191068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
163291068Sarr		    modnamelen, verinfo);
163391040Sarr		if (result != NULL)
163491040Sarr			return (result);
163591040Sarr		if (*ep == 0)
163691040Sarr			break;
163791040Sarr	}
163891040Sarr	return (NULL);
163983321Speter}
164083321Speter
164183321Speter/*
164283321Speter * Search for module in all directories listed in the linker_path.
164383321Speter */
164483321Speterstatic char *
164583321Speterlinker_search_kld(const char *name)
164683321Speter{
164791040Sarr	char *cp, *ep, *result, **cpp;
164891040Sarr	int extlen, len;
164983321Speter
165091040Sarr	/* qualified at all? */
165191040Sarr	if (index(name, '/'))
165291040Sarr		return (linker_strdup(name));
165340159Speter
165491040Sarr	extlen = 0;
165591040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
165691040Sarr		len = strlen(*cpp);
165791040Sarr		if (len > extlen)
165891040Sarr			extlen = len;
165991040Sarr	}
166091040Sarr	extlen++;		/* trailing '\0' */
166159751Speter
166291040Sarr	/* traverse the linker path */
166391040Sarr	len = strlen(name);
166491040Sarr	for (ep = linker_path; *ep; ep++) {
166591040Sarr		cp = ep;
166691040Sarr		/* find the end of this component */
166791040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
166891040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
166991040Sarr		if (result != NULL)
167091040Sarr			return (result);
167191040Sarr	}
167291040Sarr	return (NULL);
167340159Speter}
167459751Speter
167559751Speterstatic const char *
167691040Sarrlinker_basename(const char *path)
167759751Speter{
167891040Sarr	const char *filename;
167959751Speter
168091040Sarr	filename = rindex(path, '/');
168191040Sarr	if (filename == NULL)
168291040Sarr		return path;
168391040Sarr	if (filename[1])
168491040Sarr		filename++;
168591040Sarr	return (filename);
168659751Speter}
168759751Speter
1688157144Sjkoshy#ifdef HWPMC_HOOKS
1689157144Sjkoshy
169059751Speter/*
1691157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1692157144Sjkoshy */
1693157144Sjkoshyvoid *
1694157144Sjkoshylinker_hwpmc_list_objects(void)
1695157144Sjkoshy{
1696157144Sjkoshy	int nobjects, nmappings;
1697157144Sjkoshy	linker_file_t lf;
1698157144Sjkoshy	struct pmckern_map_in *ko, *kobase;
1699157144Sjkoshy
1700157144Sjkoshy	nmappings = 15;	/* a reasonable default */
1701157144Sjkoshy
1702157144Sjkoshy retry:
1703157144Sjkoshy	/* allocate nmappings+1 entries */
1704157144Sjkoshy	MALLOC(kobase, struct pmckern_map_in *,
1705157144Sjkoshy	    (nmappings + 1) * sizeof(struct pmckern_map_in), M_LINKER,
1706157144Sjkoshy	    M_WAITOK | M_ZERO);
1707157144Sjkoshy
1708157144Sjkoshy	nobjects = 0;
1709157144Sjkoshy	mtx_lock(&kld_mtx);
1710157144Sjkoshy	TAILQ_FOREACH(lf, &linker_files, link)
1711157144Sjkoshy		nobjects++;
1712157144Sjkoshy
1713157144Sjkoshy	KASSERT(nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
1714157144Sjkoshy		"objects?"));
1715157144Sjkoshy
1716157144Sjkoshy	if (nobjects > nmappings) {
1717157144Sjkoshy		nmappings = nobjects;
1718157144Sjkoshy		FREE(kobase, M_LINKER);
1719157144Sjkoshy		mtx_unlock(&kld_mtx);
1720157144Sjkoshy		goto retry;
1721157144Sjkoshy	}
1722157144Sjkoshy
1723157144Sjkoshy	ko = kobase;
1724157144Sjkoshy	TAILQ_FOREACH(lf, &linker_files, link) {
1725157144Sjkoshy		ko->pm_file = lf->filename;
1726157144Sjkoshy		ko->pm_address = (uintptr_t) lf->address;
1727157144Sjkoshy		ko++;
1728157144Sjkoshy	}
1729157144Sjkoshy
1730157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1731157144Sjkoshy	KASSERT(ko->pm_file == NULL,
1732157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1733157144Sjkoshy
1734157144Sjkoshy	mtx_unlock(&kld_mtx);
1735157144Sjkoshy
1736157144Sjkoshy	return ((void *) kobase);
1737157144Sjkoshy}
1738157144Sjkoshy#endif
1739157144Sjkoshy
1740157144Sjkoshy/*
174191040Sarr * Find a file which contains given module and load it, if "parent" is not
174291040Sarr * NULL, register a reference to it.
174359751Speter */
1744101241Smuxint
174583321Speterlinker_load_module(const char *kldname, const char *modname,
174691040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
174791040Sarr    struct linker_file **lfpp)
174859751Speter{
174991040Sarr	linker_file_t lfdep;
175091040Sarr	const char *filename;
175191040Sarr	char *pathname;
175291040Sarr	int error;
175359751Speter
175491040Sarr	if (modname == NULL) {
175591040Sarr		/*
175691040Sarr 		 * We have to load KLD
175791040Sarr 		 */
175891068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
175991068Sarr		    " is not NULL"));
176091040Sarr		pathname = linker_search_kld(kldname);
176191040Sarr	} else {
176291040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
176391040Sarr			return (EEXIST);
176494322Sbrian		if (kldname != NULL)
176594322Sbrian			pathname = linker_strdup(kldname);
176695488Sbrian		else if (rootvnode == NULL)
176794322Sbrian			pathname = NULL;
176894322Sbrian		else
176991040Sarr			/*
177091040Sarr			 * Need to find a KLD with required module
177191040Sarr			 */
177291040Sarr			pathname = linker_search_module(modname,
177391040Sarr			    strlen(modname), verinfo);
177491040Sarr	}
177591040Sarr	if (pathname == NULL)
177691040Sarr		return (ENOENT);
177791040Sarr
177883321Speter	/*
177991040Sarr	 * Can't load more than one file with the same basename XXX:
178091040Sarr	 * Actually it should be possible to have multiple KLDs with
178191040Sarr	 * the same basename but different path because they can
178291040Sarr	 * provide different versions of the same modules.
178383321Speter	 */
178491040Sarr	filename = linker_basename(pathname);
178591040Sarr	if (linker_find_file_by_name(filename)) {
178691040Sarr		error = EEXIST;
178791040Sarr		goto out;
178883321Speter	}
178991040Sarr	do {
179091040Sarr		error = linker_load_file(pathname, &lfdep);
179191040Sarr		if (error)
179291040Sarr			break;
179391040Sarr		if (modname && verinfo &&
179491040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
1795132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
179691040Sarr			error = ENOENT;
179791040Sarr			break;
179891040Sarr		}
179991040Sarr		if (parent) {
180091040Sarr			error = linker_file_add_dependency(parent, lfdep);
180191040Sarr			if (error)
180291040Sarr				break;
180391040Sarr		}
180491040Sarr		if (lfpp)
180591040Sarr			*lfpp = lfdep;
180691040Sarr	} while (0);
180759751Speterout:
180891040Sarr	if (pathname)
180991040Sarr		free(pathname, M_LINKER);
181091040Sarr	return (error);
181159751Speter}
181259751Speter
181359751Speter/*
181491040Sarr * This routine is responsible for finding dependencies of userland initiated
181591040Sarr * kldload(2)'s of files.
181659751Speter */
181759751Speterint
181886469Siedowselinker_load_dependencies(linker_file_t lf)
181959751Speter{
182091040Sarr	linker_file_t lfdep;
182191040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
182291040Sarr	struct mod_metadata *mp, *nmp;
182391040Sarr	struct mod_depend *verinfo;
182491040Sarr	modlist_t mod;
182591040Sarr	const char *modname, *nmodname;
182692032Sdwmalone	int ver, error = 0, count;
182759751Speter
182891040Sarr	/*
182991040Sarr	 * All files are dependant on /kernel.
183091040Sarr	 */
183191040Sarr	if (linker_kernel_file) {
183291040Sarr		linker_kernel_file->refs++;
183391040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
183491040Sarr		if (error)
183591040Sarr			return (error);
183659751Speter	}
183791040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
183891040Sarr	    &count) != 0)
183991040Sarr		return (0);
184091040Sarr	for (mdp = start; mdp < stop; mdp++) {
1841109605Sjake		mp = *mdp;
184291040Sarr		if (mp->md_type != MDT_VERSION)
184391040Sarr			continue;
1844109605Sjake		modname = mp->md_cval;
1845109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
184691040Sarr		mod = modlist_lookup(modname, ver);
184791040Sarr		if (mod != NULL) {
184891040Sarr			printf("interface %s.%d already present in the KLD"
184991040Sarr			    " '%s'!\n", modname, ver,
185091040Sarr			    mod->container->filename);
185191040Sarr			return (EEXIST);
185291040Sarr		}
185391040Sarr	}
185474642Sbp
185591040Sarr	for (mdp = start; mdp < stop; mdp++) {
1856109605Sjake		mp = *mdp;
185791040Sarr		if (mp->md_type != MDT_DEPEND)
185891040Sarr			continue;
1859109605Sjake		modname = mp->md_cval;
1860109605Sjake		verinfo = mp->md_data;
186191040Sarr		nmodname = NULL;
186291040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
1863109605Sjake			nmp = *nmdp;
186491040Sarr			if (nmp->md_type != MDT_VERSION)
186591040Sarr				continue;
1866109605Sjake			nmodname = nmp->md_cval;
186792032Sdwmalone			if (strcmp(modname, nmodname) == 0)
186891040Sarr				break;
186991040Sarr		}
187091040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
187191040Sarr			continue;
187291040Sarr		mod = modlist_lookup2(modname, verinfo);
187391040Sarr		if (mod) {	/* woohoo, it's loaded already */
187491040Sarr			lfdep = mod->container;
187591040Sarr			lfdep->refs++;
187691040Sarr			error = linker_file_add_dependency(lf, lfdep);
187791040Sarr			if (error)
187891040Sarr				break;
187991040Sarr			continue;
188091040Sarr		}
188191040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
188291040Sarr		if (error) {
188391040Sarr			printf("KLD %s: depends on %s - not available\n",
188491040Sarr			    lf->filename, modname);
188591040Sarr			break;
188691040Sarr		}
188759751Speter	}
188859751Speter
188991040Sarr	if (error)
189091040Sarr		return (error);
189191040Sarr	linker_addmodules(lf, start, stop, 0);
189291040Sarr	return (error);
189359751Speter}
189485736Sgreen
189585736Sgreenstatic int
189685736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
189785736Sgreen{
189885736Sgreen	struct sysctl_req *req;
189985736Sgreen
190085736Sgreen	req = opaque;
190185736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
190285736Sgreen}
190385736Sgreen
190485736Sgreen/*
190585736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
190685736Sgreen * in the kernel.
190785736Sgreen */
190885736Sgreenstatic int
190985736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
191085736Sgreen{
191185736Sgreen	linker_file_t lf;
191285736Sgreen	int error;
191385736Sgreen
1914107089Srwatson#ifdef MAC
1915107089Srwatson	error = mac_check_kld_stat(req->td->td_ucred);
1916107089Srwatson	if (error)
1917107089Srwatson		return (error);
1918107089Srwatson#endif
1919126253Struckman	error = sysctl_wire_old_buffer(req, 0);
1920126253Struckman	if (error != 0)
1921126253Struckman		return (error);
192298452Sarr	mtx_lock(&kld_mtx);
192385736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
192485736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
192585736Sgreen		    sysctl_kern_function_list_iterate, req);
192698452Sarr		if (error) {
192798452Sarr			mtx_unlock(&kld_mtx);
192885736Sgreen			return (error);
192998452Sarr		}
193085736Sgreen	}
193198452Sarr	mtx_unlock(&kld_mtx);
193285736Sgreen	return (SYSCTL_OUT(req, "", 1));
193385736Sgreen}
193485736Sgreen
193585736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
193691040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
1937