kern_linker.c revision 159800
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 159800 2006-06-20 20:41:15Z jhb $");
29116182Sobrien
3040159Speter#include "opt_ddb.h"
31157144Sjkoshy#include "opt_hwpmc_hooks.h"
32107089Srwatson#include "opt_mac.h"
3340159Speter
3425537Sdfr#include <sys/param.h>
3525537Sdfr#include <sys/kernel.h>
3625537Sdfr#include <sys/systm.h>
3725537Sdfr#include <sys/malloc.h>
3825537Sdfr#include <sys/sysproto.h>
3925537Sdfr#include <sys/sysent.h>
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>
51159588Sjhb#include <sys/syscallsubr.h>
5240159Speter#include <sys/sysctl.h>
5325537Sdfr
5459603Sdfr#include "linker_if.h"
5559603Sdfr
56157144Sjkoshy#ifdef HWPMC_HOOKS
57157144Sjkoshy#include <sys/pmckern.h>
58157144Sjkoshy#endif
59157144Sjkoshy
6040961Speter#ifdef KLD_DEBUG
6140961Speterint kld_debug = 0;
6240961Speter#endif
6340961Speter
6491040Sarr/*
6591040Sarr * static char *linker_search_path(const char *name, struct mod_depend
6691040Sarr * *verinfo);
6791040Sarr */
6891040Sarrstatic const char 	*linker_basename(const char *path);
6959751Speter
70159800Sjhb/*
71159800Sjhb * Find a currently loaded file given its filename.
72159800Sjhb */
73159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
74159800Sjhb
75159800Sjhb/*
76159800Sjhb * Find a currently loaded file given its file id.
77159800Sjhb */
78159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
79159800Sjhb
8078161Speter/* Metadata from the static kernel */
8178161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
8278161Speter
8359751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
8459751Speter
8540906Speterlinker_file_t linker_kernel_file;
8631324Sbde
8798452Sarrstatic struct mtx kld_mtx;	/* kernel linker mutex */
8898452Sarr
8925537Sdfrstatic linker_class_list_t classes;
9050068Sgrogstatic linker_file_list_t linker_files;
9125537Sdfrstatic int next_file_id = 1;
9298452Sarrstatic int linker_no_more_classes = 0;
9325537Sdfr
9486553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
9591040Sarr	linker_file_t lftmp;						\
9686553Sarr									\
9786553Sarrretry:									\
9898452Sarr	mtx_lock(&kld_mtx);						\
9991040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
10091040Sarr		if (next_file_id == lftmp->id) {			\
10191040Sarr			next_file_id++;					\
10298452Sarr			mtx_unlock(&kld_mtx);				\
10391040Sarr			goto retry;					\
10491040Sarr		}							\
10591040Sarr	}								\
10691040Sarr	(a) = next_file_id;						\
10798452Sarr	mtx_unlock(&kld_mtx);	/* Hold for safe read of id variable */	\
10886553Sarr} while(0)
10986553Sarr
11086553Sarr
11159751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
11260938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
11359751Speterstruct modlist {
11491040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
11591040Sarr	linker_file_t   container;
11691040Sarr	const char 	*name;
11791040Sarr	int             version;
11859751Speter};
11991040Sarrtypedef struct modlist *modlist_t;
12091040Sarrstatic modlisthead_t found_modules;
12159751Speter
122159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
123159796Sjhb		    linker_file_t dep);
124159796Sjhbstatic int	linker_load_module(const char *kldname,
125159796Sjhb		    const char *modname, struct linker_file *parent,
126159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
127159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
12894321Sbrian
12959603Sdfrstatic char *
13059603Sdfrlinker_strdup(const char *str)
13159603Sdfr{
13291040Sarr	char *result;
13359603Sdfr
134111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
13591040Sarr		strcpy(result, str);
13691040Sarr	return (result);
13759603Sdfr}
13859603Sdfr
13925537Sdfrstatic void
14091040Sarrlinker_init(void *arg)
14125537Sdfr{
14291040Sarr
14398452Sarr	mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
14491040Sarr	TAILQ_INIT(&classes);
14591040Sarr	TAILQ_INIT(&linker_files);
14625537Sdfr}
14725537Sdfr
14891040SarrSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
14925537Sdfr
15098452Sarrstatic void
15198452Sarrlinker_stop_class_add(void *arg)
15298452Sarr{
15398452Sarr
15498452Sarr	linker_no_more_classes = 1;
15598452Sarr}
15698452Sarr
15798452SarrSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL)
15898452Sarr
15925537Sdfrint
16059603Sdfrlinker_add_class(linker_class_t lc)
16125537Sdfr{
16291040Sarr
16398452Sarr	/*
164144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
165144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
166144443Sjhb	 * ops from being freed.
16798452Sarr	 */
16898452Sarr	if (linker_no_more_classes == 1)
16998452Sarr		return (EPERM);
17091040Sarr	kobj_class_compile((kobj_class_t) lc);
171144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
17291040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
17391040Sarr	return (0);
17425537Sdfr}
17525537Sdfr
17625537Sdfrstatic void
17725537Sdfrlinker_file_sysinit(linker_file_t lf)
17825537Sdfr{
17991040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
18025537Sdfr
18191040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
18291040Sarr	    lf->filename));
18325537Sdfr
18491040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
18591040Sarr		return;
18691040Sarr	/*
18791040Sarr	 * Perform a bubble sort of the system initialization objects by
18891040Sarr	 * their subsystem (primary key) and order (secondary key).
18991040Sarr	 *
19091040Sarr	 * Since some things care about execution order, this is the operation
19191040Sarr	 * which ensures continued function.
19291040Sarr	 */
19391040Sarr	for (sipp = start; sipp < stop; sipp++) {
19491040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
19591040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
19691040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
19791040Sarr			    (*sipp)->order <= (*xipp)->order))
19891040Sarr				continue;	/* skip */
19991040Sarr			save = *sipp;
20091040Sarr			*sipp = *xipp;
20191040Sarr			*xipp = save;
20291040Sarr		}
20325537Sdfr	}
20425537Sdfr
20591040Sarr	/*
20691040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
20791040Sarr	 * Perform each task, and continue on to the next task.
20891040Sarr	 */
20991040Sarr	for (sipp = start; sipp < stop; sipp++) {
21091040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
21191040Sarr			continue;	/* skip dummy task(s) */
21225537Sdfr
21391040Sarr		/* Call function */
21491040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
21591040Sarr	}
21625537Sdfr}
21725537Sdfr
21841055Speterstatic void
21941055Speterlinker_file_sysuninit(linker_file_t lf)
22041055Speter{
22191040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
22241055Speter
22391040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
22491040Sarr	    lf->filename));
22541055Speter
22691068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
22791040Sarr	    NULL) != 0)
22891040Sarr		return;
22941055Speter
23091040Sarr	/*
23191040Sarr	 * Perform a reverse bubble sort of the system initialization objects
23291040Sarr	 * by their subsystem (primary key) and order (secondary key).
23391040Sarr	 *
23491040Sarr	 * Since some things care about execution order, this is the operation
23591040Sarr	 * which ensures continued function.
23691040Sarr	 */
23791040Sarr	for (sipp = start; sipp < stop; sipp++) {
23891040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
23991040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
24091040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
24191040Sarr			    (*sipp)->order >= (*xipp)->order))
24291040Sarr				continue;	/* skip */
24391040Sarr			save = *sipp;
24491040Sarr			*sipp = *xipp;
24591040Sarr			*xipp = save;
24691040Sarr		}
24741055Speter	}
24841055Speter
24991040Sarr	/*
25091040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
25191040Sarr	 * Perform each task, and continue on to the next task.
25291040Sarr	 */
25391040Sarr	for (sipp = start; sipp < stop; sipp++) {
25491040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
25591040Sarr			continue;	/* skip dummy task(s) */
25641055Speter
25791040Sarr		/* Call function */
25891040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
25991040Sarr	}
26041055Speter}
26141055Speter
26244078Sdfrstatic void
26344078Sdfrlinker_file_register_sysctls(linker_file_t lf)
26444078Sdfr{
26591040Sarr	struct sysctl_oid **start, **stop, **oidp;
26644078Sdfr
26791040Sarr	KLD_DPF(FILE,
26891040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
26991040Sarr	    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_register_oid(*oidp);
27644078Sdfr}
27744078Sdfr
27844078Sdfrstatic void
27944078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
28044078Sdfr{
28191040Sarr	struct sysctl_oid **start, **stop, **oidp;
28244078Sdfr
28391040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
28491040Sarr	    " for %s\n", lf->filename));
28544078Sdfr
28691040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
28791040Sarr		return;
28844078Sdfr
28991040Sarr	for (oidp = start; oidp < stop; oidp++)
29091040Sarr		sysctl_unregister_oid(*oidp);
29144078Sdfr}
29244078Sdfr
29359751Speterstatic int
29459751Speterlinker_file_register_modules(linker_file_t lf)
29559751Speter{
29691040Sarr	struct mod_metadata **start, **stop, **mdp;
29791040Sarr	const moduledata_t *moddata;
298146733Spjd	int first_error, error;
29959751Speter
30091040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
30191040Sarr	    " in %s\n", lf->filename));
30259751Speter
30391068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
30491040Sarr	    &stop, 0) != 0) {
30591040Sarr		/*
30691040Sarr		 * This fallback should be unnecessary, but if we get booted
30791040Sarr		 * from boot2 instead of loader and we are missing our
30891040Sarr		 * metadata then we have to try the best we can.
30991040Sarr		 */
31091040Sarr		if (lf == linker_kernel_file) {
31191040Sarr			start = SET_BEGIN(modmetadata_set);
31291040Sarr			stop = SET_LIMIT(modmetadata_set);
31391040Sarr		} else
31491040Sarr			return (0);
31578161Speter	}
316146733Spjd	first_error = 0;
31791040Sarr	for (mdp = start; mdp < stop; mdp++) {
31891040Sarr		if ((*mdp)->md_type != MDT_MODULE)
31991040Sarr			continue;
32091040Sarr		moddata = (*mdp)->md_data;
32191040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
32291040Sarr		    moddata->name, lf->filename));
32391040Sarr		error = module_register(moddata, lf);
324146730Spjd		if (error) {
32591068Sarr			printf("Module %s failed to register: %d\n",
32691040Sarr			    moddata->name, error);
327146733Spjd			if (first_error == 0)
328146733Spjd				first_error = error;
329146730Spjd		}
33059751Speter	}
331146733Spjd	return (first_error);
33259751Speter}
33359751Speter
33459751Speterstatic void
33559751Speterlinker_init_kernel_modules(void)
33659751Speter{
33791040Sarr
33891040Sarr	linker_file_register_modules(linker_kernel_file);
33959751Speter}
34059751Speter
34191040SarrSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 0)
34259751Speter
343101241Smuxstatic int
34491040Sarrlinker_load_file(const char *filename, linker_file_t *result)
34525537Sdfr{
34691040Sarr	linker_class_t lc;
34791040Sarr	linker_file_t lf;
348159585Sjhb	int foundfile, error;
34925537Sdfr
35091040Sarr	/* Refuse to load modules if securelevel raised */
35191040Sarr	if (securelevel > 0)
35291040Sarr		return (EPERM);
35362261Sarchie
35491040Sarr	lf = linker_find_file_by_name(filename);
35591040Sarr	if (lf) {
35691040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
35791040Sarr		    " incrementing refs\n", filename));
35891040Sarr		*result = lf;
35991040Sarr		lf->refs++;
360159585Sjhb		return (0);
36191040Sarr	}
36291040Sarr	foundfile = 0;
363159585Sjhb	error = 0;
36498452Sarr
36598452Sarr	/*
36698452Sarr	 * We do not need to protect (lock) classes here because there is
36798452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
36898452Sarr	 * and there is no class deregistration mechanism at this time.
36998452Sarr	 */
37091040Sarr	TAILQ_FOREACH(lc, &classes, link) {
37191040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
37291040Sarr		    filename));
37391040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
37491040Sarr		/*
37591040Sarr		 * If we got something other than ENOENT, then it exists but
37691040Sarr		 * we cannot load it for some other reason.
37791040Sarr		 */
37891040Sarr		if (error != ENOENT)
37991040Sarr			foundfile = 1;
38091040Sarr		if (lf) {
381146730Spjd			error = linker_file_register_modules(lf);
382146730Spjd			if (error == EEXIST) {
383146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
384159585Sjhb				return (error);
385146730Spjd			}
38691040Sarr			linker_file_register_sysctls(lf);
38791040Sarr			linker_file_sysinit(lf);
38891040Sarr			lf->flags |= LINKER_FILE_LINKED;
38991040Sarr			*result = lf;
390159585Sjhb			return (0);
39191040Sarr		}
39291040Sarr	}
39342755Speter	/*
39491040Sarr	 * Less than ideal, but tells the user whether it failed to load or
39591040Sarr	 * the module was not found.
39642755Speter	 */
397105337Ssam	if (foundfile) {
398105337Ssam		/*
399105337Ssam		 * Format not recognized or otherwise unloadable.
400105337Ssam		 * When loading a module that is statically built into
401105337Ssam		 * the kernel EEXIST percolates back up as the return
402105337Ssam		 * value.  Preserve this so that apps like sysinstall
403105337Ssam		 * can recognize this special case and not post bogus
404105337Ssam		 * dialog boxes.
405105337Ssam		 */
406105337Ssam		if (error != EEXIST)
407105337Ssam			error = ENOEXEC;
408105337Ssam	} else
40991068Sarr		error = ENOENT;		/* Nothing found */
41091040Sarr	return (error);
41125537Sdfr}
41225537Sdfr
41378413Sbrianint
41494321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
41594321Sbrian    linker_file_t *result)
41678413Sbrian{
41794321Sbrian	modlist_t mod;
41894321Sbrian
41994321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
42094321Sbrian		*result = mod->container;
42194321Sbrian		(*result)->refs++;
42294321Sbrian		return (0);
42394321Sbrian	}
42494321Sbrian
42594321Sbrian	return (linker_load_module(NULL, modname, NULL, verinfo, result));
42678413Sbrian}
42778413Sbrian
428159800Sjhbstatic linker_file_t
42991040Sarrlinker_find_file_by_name(const char *filename)
43025537Sdfr{
431159585Sjhb	linker_file_t lf;
43291040Sarr	char *koname;
43325537Sdfr
434111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
43591040Sarr	sprintf(koname, "%s.ko", filename);
43640861Speter
43798452Sarr	mtx_lock(&kld_mtx);
43891040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
43992032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
44091040Sarr			break;
44192032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
44291040Sarr			break;
44391040Sarr	}
44498452Sarr	mtx_unlock(&kld_mtx);
445159585Sjhb	free(koname, M_LINKER);
44691040Sarr	return (lf);
44725537Sdfr}
44825537Sdfr
449159800Sjhbstatic linker_file_t
45025537Sdfrlinker_find_file_by_id(int fileid)
45125537Sdfr{
452159585Sjhb	linker_file_t lf;
45398452Sarr
45498452Sarr	mtx_lock(&kld_mtx);
45591040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
45691040Sarr		if (lf->id == fileid)
45791040Sarr			break;
45898452Sarr	mtx_unlock(&kld_mtx);
45991040Sarr	return (lf);
46025537Sdfr}
46125537Sdfr
462159797Sjhbint
463159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
464159797Sjhb{
465159797Sjhb	linker_file_t lf;
466159797Sjhb	int retval = 0;
467159797Sjhb
468159797Sjhb	mtx_lock(&Giant);
469159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
470159797Sjhb		retval = predicate(lf, context);
471159797Sjhb		if (retval != 0)
472159797Sjhb			break;
473159797Sjhb	}
474159797Sjhb	mtx_unlock(&Giant);
475159797Sjhb	return (retval);
476159797Sjhb}
477159797Sjhb
47825537Sdfrlinker_file_t
47991040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
48025537Sdfr{
48191040Sarr	linker_file_t lf;
48291040Sarr	const char *filename;
48325537Sdfr
48491040Sarr	filename = linker_basename(pathname);
48540159Speter
48691040Sarr	KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
487111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
48891040Sarr	if (lf == NULL)
489159585Sjhb		return (NULL);
49091040Sarr	lf->refs = 1;
49191040Sarr	lf->userrefs = 0;
49291040Sarr	lf->flags = 0;
49391040Sarr	lf->filename = linker_strdup(filename);
49491040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
49591040Sarr	lf->ndeps = 0;
49691040Sarr	lf->deps = NULL;
49791040Sarr	STAILQ_INIT(&lf->common);
49891040Sarr	TAILQ_INIT(&lf->modules);
49998452Sarr	mtx_lock(&kld_mtx);
50091040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
50198452Sarr	mtx_unlock(&kld_mtx);
50291040Sarr	return (lf);
50325537Sdfr}
50425537Sdfr
50525537Sdfrint
506132117Sphklinker_file_unload(linker_file_t file, int flags)
50725537Sdfr{
50891040Sarr	module_t mod, next;
50991040Sarr	modlist_t ml, nextml;
51091040Sarr	struct common_symbol *cp;
51191040Sarr	int error, i;
51225537Sdfr
51391040Sarr	/* Refuse to unload modules if securelevel raised. */
51491040Sarr	if (securelevel > 0)
51591040Sarr		return (EPERM);
516107089Srwatson#ifdef MAC
517107089Srwatson	error = mac_check_kld_unload(curthread->td_ucred);
518107089Srwatson	if (error)
519107089Srwatson		return (error);
520107089Srwatson#endif
52125537Sdfr
52291040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
52391040Sarr
524159584Sjhb	/* Easy case of just dropping a reference. */
525159584Sjhb	if (file->refs > 1) {
526159584Sjhb		file->refs--;
527159584Sjhb		return (0);
528159584Sjhb	}
529159584Sjhb
530159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
531159584Sjhb	    " informing modules\n"));
532159584Sjhb
533159584Sjhb	/*
534159584Sjhb	 * Inform any modules associated with this file.
535159584Sjhb	 */
536159584Sjhb	MOD_XLOCK;
537159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
538159584Sjhb		next = module_getfnext(mod);
539159584Sjhb		MOD_XUNLOCK;
540159584Sjhb
54191040Sarr		/*
542159584Sjhb		 * Give the module a chance to veto the unload.
54391040Sarr		 */
544159584Sjhb		if ((error = module_unload(mod, flags)) != 0) {
545159584Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %p"
546159584Sjhb			    " vetoes unload\n", mod));
547159584Sjhb			return (error);
548159584Sjhb		}
54992547Sarr		MOD_XLOCK;
550159584Sjhb		module_release(mod);
551159584Sjhb	}
552159584Sjhb	MOD_XUNLOCK;
55391040Sarr
554159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
555128057Speadar		if (ml->container == file) {
55691040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
557128057Speadar			free(ml, M_LINKER);
558128057Speadar		}
55991040Sarr	}
56025537Sdfr
56191040Sarr	/*
56291040Sarr	 * Don't try to run SYSUNINITs if we are unloaded due to a
56391040Sarr	 * link error.
56491040Sarr	 */
56591040Sarr	if (file->flags & LINKER_FILE_LINKED) {
56691040Sarr		linker_file_sysuninit(file);
56791040Sarr		linker_file_unregister_sysctls(file);
56825537Sdfr	}
56998452Sarr	mtx_lock(&kld_mtx);
57091040Sarr	TAILQ_REMOVE(&linker_files, file, link);
57198452Sarr	mtx_unlock(&kld_mtx);
57225537Sdfr
57391040Sarr	if (file->deps) {
57491040Sarr		for (i = 0; i < file->ndeps; i++)
575132117Sphk			linker_file_unload(file->deps[i], flags);
57691040Sarr		free(file->deps, M_LINKER);
57791040Sarr		file->deps = NULL;
57859751Speter	}
57991040Sarr	for (cp = STAILQ_FIRST(&file->common); cp;
58091068Sarr	    cp = STAILQ_FIRST(&file->common)) {
58191040Sarr		STAILQ_REMOVE(&file->common, cp, common_symbol, link);
58291040Sarr		free(cp, M_LINKER);
58391040Sarr	}
58459751Speter
58591040Sarr	LINKER_UNLOAD(file);
58691040Sarr	if (file->filename) {
58791040Sarr		free(file->filename, M_LINKER);
58891040Sarr		file->filename = NULL;
58991040Sarr	}
59091040Sarr	kobj_delete((kobj_t) file, M_LINKER);
591159584Sjhb	return (0);
59225537Sdfr}
59325537Sdfr
594159796Sjhbstatic int
59586469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
59625537Sdfr{
59791040Sarr	linker_file_t *newdeps;
59825537Sdfr
59991040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
600111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
60191040Sarr	if (newdeps == NULL)
60291040Sarr		return (ENOMEM);
60325537Sdfr
60491040Sarr	if (file->deps) {
60591040Sarr		bcopy(file->deps, newdeps,
60691040Sarr		    file->ndeps * sizeof(linker_file_t *));
60791040Sarr		free(file->deps, M_LINKER);
60891040Sarr	}
60991040Sarr	file->deps = newdeps;
61091040Sarr	file->deps[file->ndeps] = dep;
61191040Sarr	file->ndeps++;
61291040Sarr	return (0);
61325537Sdfr}
61425537Sdfr
61578161Speter/*
61691040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
61791040Sarr * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void ***
61878161Speter */
61978161Speterint
62078161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
62191040Sarr    void *firstp, void *lastp, int *countp)
62278161Speter{
62378161Speter
62491040Sarr	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
62578161Speter}
62678161Speter
62725537Sdfrcaddr_t
62891040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
62925537Sdfr{
63091040Sarr	c_linker_sym_t sym;
63191040Sarr	linker_symval_t symval;
63291040Sarr	caddr_t address;
63391040Sarr	size_t common_size = 0;
63492032Sdwmalone	int i;
63525537Sdfr
636109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
63791040Sarr	    file, name, deps));
63825537Sdfr
63991040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
64091040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
64191040Sarr		if (symval.value == 0)
64291040Sarr			/*
64391040Sarr			 * For commons, first look them up in the
64491040Sarr			 * dependencies and only allocate space if not found
64591040Sarr			 * there.
64691040Sarr			 */
64791040Sarr			common_size = symval.size;
64891040Sarr		else {
64991040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
650109605Sjake			    ".value=%p\n", symval.value));
65191040Sarr			return (symval.value);
65291040Sarr		}
65340159Speter	}
65491040Sarr	if (deps) {
65591040Sarr		for (i = 0; i < file->ndeps; i++) {
65691040Sarr			address = linker_file_lookup_symbol(file->deps[i],
65791040Sarr			    name, 0);
65891040Sarr			if (address) {
65991040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
660109605Sjake				    " deps value=%p\n", address));
66191040Sarr				return (address);
66291040Sarr			}
66391040Sarr		}
66425537Sdfr	}
66591040Sarr	if (common_size > 0) {
66691040Sarr		/*
66791040Sarr		 * This is a common symbol which was not found in the
66891040Sarr		 * dependencies.  We maintain a simple common symbol table in
66991040Sarr		 * the file object.
67091040Sarr		 */
67191040Sarr		struct common_symbol *cp;
67242849Speter
67391040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
67492032Sdwmalone			if (strcmp(cp->name, name) == 0) {
67591040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
676109605Sjake				    " old common value=%p\n", cp->address));
67791040Sarr				return (cp->address);
67891040Sarr			}
67991040Sarr		}
68091040Sarr		/*
68191040Sarr		 * Round the symbol size up to align.
68291040Sarr		 */
68391040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
68491040Sarr		cp = malloc(sizeof(struct common_symbol)
68591040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
686111119Simp		    M_WAITOK | M_ZERO);
68791040Sarr		cp->address = (caddr_t)(cp + 1);
68891040Sarr		cp->name = cp->address + common_size;
68991040Sarr		strcpy(cp->name, name);
69091040Sarr		bzero(cp->address, common_size);
69191040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
69225537Sdfr
69391040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
694109605Sjake		    " value=%p\n", cp->address));
69591040Sarr		return (cp->address);
69640159Speter	}
69791040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
69891040Sarr	return (0);
69925537Sdfr}
70025537Sdfr
70140159Speter#ifdef DDB
70225537Sdfr/*
70391040Sarr * DDB Helpers.  DDB has to look across multiple files with their own symbol
70491040Sarr * tables and string tables.
70591040Sarr *
70691040Sarr * Note that we do not obey list locking protocols here.  We really don't need
70791040Sarr * DDB to hang because somebody's got the lock held.  We'll take the chance
70891040Sarr * that the files list is inconsistant instead.
70940159Speter */
71040159Speter
71140159Speterint
71243309Sdillonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
71340159Speter{
71491040Sarr	linker_file_t lf;
71540159Speter
71691040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
71791040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
71891040Sarr			return (0);
71991040Sarr	}
72091040Sarr	return (ENOENT);
72140159Speter}
72240159Speter
72340159Speterint
72443309Sdillonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
72540159Speter{
72691040Sarr	linker_file_t lf;
72791040Sarr	c_linker_sym_t best, es;
72891040Sarr	u_long diff, bestdiff, off;
72940159Speter
73091040Sarr	best = 0;
73191040Sarr	off = (uintptr_t)value;
73291040Sarr	bestdiff = off;
73391040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
73491040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
73591040Sarr			continue;
73691040Sarr		if (es != 0 && diff < bestdiff) {
73791040Sarr			best = es;
73891040Sarr			bestdiff = diff;
73991040Sarr		}
74091040Sarr		if (bestdiff == 0)
74191040Sarr			break;
74240159Speter	}
74391040Sarr	if (best) {
74491040Sarr		*sym = best;
74591040Sarr		*diffp = bestdiff;
74691040Sarr		return (0);
74791040Sarr	} else {
74891040Sarr		*sym = 0;
74991040Sarr		*diffp = off;
75091040Sarr		return (ENOENT);
75191040Sarr	}
75240159Speter}
75340159Speter
75440159Speterint
75543309Sdillonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
75640159Speter{
75791040Sarr	linker_file_t lf;
75840159Speter
75991040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
76091040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
76191040Sarr			return (0);
76291040Sarr	}
76391040Sarr	return (ENOENT);
76440159Speter}
76540159Speter#endif
76640159Speter
76740159Speter/*
76825537Sdfr * Syscalls.
76925537Sdfr */
77082749Sdillon/*
77182749Sdillon * MPSAFE
77282749Sdillon */
77325537Sdfrint
774159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
77525537Sdfr{
776157144Sjkoshy#ifdef HWPMC_HOOKS
777157144Sjkoshy	struct pmckern_map_in pkm;
778157144Sjkoshy#endif
779159588Sjhb	const char *kldname, *modname;
78091040Sarr	linker_file_t lf;
781159588Sjhb	int error;
78225537Sdfr
78393159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
784159588Sjhb		return (error);
78593159Sarr
78693593Sjhb	if ((error = suser(td)) != 0)
787159588Sjhb		return (error);
78825537Sdfr
78991040Sarr	/*
790159588Sjhb	 * If file does not contain qualified name or any dot in it
79191040Sarr	 * (kldname.ko, or kldname.ver.ko) treat it as interface
79291040Sarr	 * name.
79391040Sarr	 */
794159588Sjhb	if (index(file, '/') || index(file, '.')) {
795159588Sjhb		kldname = file;
79691040Sarr		modname = NULL;
79791040Sarr	} else {
79891040Sarr		kldname = NULL;
799159588Sjhb		modname = file;
80091040Sarr	}
801159588Sjhb
802159588Sjhb	mtx_lock(&Giant);
80391040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
80491040Sarr	if (error)
805159588Sjhb		goto unlock;
80642316Smsmith
807157144Sjkoshy#ifdef HWPMC_HOOKS
808157144Sjkoshy	pkm.pm_file = lf->filename;
809157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
810157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
811157144Sjkoshy#endif
81291040Sarr	lf->userrefs++;
813159588Sjhb	if (fileid != NULL)
814159588Sjhb		*fileid = lf->id;
815159588Sjhbunlock:
81691040Sarr	mtx_unlock(&Giant);
81791040Sarr	return (error);
81825537Sdfr}
81925537Sdfr
820159588Sjhbint
821159588Sjhbkldload(struct thread *td, struct kldload_args *uap)
822159588Sjhb{
823159588Sjhb	char *pathname = NULL;
824159596Smarcel	int error, fileid;
825159588Sjhb
826159588Sjhb	td->td_retval[0] = -1;
827159588Sjhb
828159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
829159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
830159596Smarcel	if (error == 0) {
831159596Smarcel		error = kern_kldload(td, pathname, &fileid);
832159596Smarcel		if (error == 0)
833159596Smarcel			td->td_retval[0] = fileid;
834159596Smarcel	}
835159588Sjhb	free(pathname, M_TEMP);
836159588Sjhb	return (error);
837159588Sjhb}
838159588Sjhb
83982749Sdillon/*
84082749Sdillon * MPSAFE
84182749Sdillon */
842159588Sjhbint
843132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
84425537Sdfr{
845157144Sjkoshy#ifdef HWPMC_HOOKS
846157144Sjkoshy	struct pmckern_map_out pkm;
847157144Sjkoshy#endif
84891040Sarr	linker_file_t lf;
84991040Sarr	int error = 0;
85025537Sdfr
85193159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
852159588Sjhb		return (error);
85393159Sarr
85493593Sjhb	if ((error = suser(td)) != 0)
855159588Sjhb		return (error);
85625537Sdfr
857159588Sjhb	mtx_lock(&Giant);
858132117Sphk	lf = linker_find_file_by_id(fileid);
85991040Sarr	if (lf) {
86091040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
86191040Sarr		if (lf->userrefs == 0) {
862132117Sphk			/*
863132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
864132117Sphk			 */
86591040Sarr			printf("kldunload: attempt to unload file that was"
86691040Sarr			    " loaded by the kernel\n");
867159588Sjhb			error = EBUSY;
868159588Sjhb		} else {
869157144Sjkoshy#ifdef HWPMC_HOOKS
870159588Sjhb			/* Save data needed by hwpmc(4) before unloading. */
871159588Sjhb			pkm.pm_address = (uintptr_t) lf->address;
872159588Sjhb			pkm.pm_size = lf->size;
873157144Sjkoshy#endif
874159588Sjhb			lf->userrefs--;
875159588Sjhb			error = linker_file_unload(lf, flags);
876159588Sjhb			if (error)
877159588Sjhb				lf->userrefs++;
878159588Sjhb		}
87991040Sarr	} else
88091040Sarr		error = ENOENT;
881157144Sjkoshy
882157144Sjkoshy#ifdef HWPMC_HOOKS
883157144Sjkoshy	if (error == 0)
884157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
885157144Sjkoshy#endif
88691068Sarr	mtx_unlock(&Giant);
88791068Sarr	return (error);
88825537Sdfr}
88925537Sdfr
89082749Sdillon/*
89182749Sdillon * MPSAFE
89282749Sdillon */
89325537Sdfrint
894132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
895132117Sphk{
896132117Sphk
897132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
898132117Sphk}
899132117Sphk
900132117Sphk/*
901132117Sphk * MPSAFE
902132117Sphk */
903132117Sphkint
904132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
905132117Sphk{
906132117Sphk
907132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
908132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
909132117Sphk		return (EINVAL);
910132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
911132117Sphk}
912132117Sphk
913132117Sphk/*
914132117Sphk * MPSAFE
915132117Sphk */
916132117Sphkint
91791040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
91825537Sdfr{
91991040Sarr	char *pathname;
92091040Sarr	const char *filename;
92191040Sarr	linker_file_t lf;
922159791Sjhb	int error;
92325537Sdfr
924107089Srwatson#ifdef MAC
925107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
926107089Srwatson	if (error)
927107089Srwatson		return (error);
928107089Srwatson#endif
929107089Srwatson
93091040Sarr	mtx_lock(&Giant);
93191040Sarr	td->td_retval[0] = -1;
93282749Sdillon
933111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
934107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
93591040Sarr		goto out;
93625537Sdfr
93791040Sarr	filename = linker_basename(pathname);
93891040Sarr	lf = linker_find_file_by_name(filename);
93991040Sarr	if (lf)
94091040Sarr		td->td_retval[0] = lf->id;
94191040Sarr	else
94291040Sarr		error = ENOENT;
94325537Sdfrout:
944159791Sjhb	free(pathname, M_TEMP);
94591040Sarr	mtx_unlock(&Giant);
94691040Sarr	return (error);
94725537Sdfr}
94825537Sdfr
94982749Sdillon/*
95082749Sdillon * MPSAFE
95182749Sdillon */
95225537Sdfrint
95391040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
95425537Sdfr{
95591040Sarr	linker_file_t lf;
95691040Sarr	int error = 0;
95725537Sdfr
958107089Srwatson#ifdef MAC
959107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
960107089Srwatson	if (error)
961107089Srwatson		return (error);
962107089Srwatson#endif
963107089Srwatson
96491040Sarr	mtx_lock(&Giant);
96582749Sdillon
966107849Salfred	if (uap->fileid == 0) {
96798452Sarr		mtx_lock(&kld_mtx);
96891040Sarr		if (TAILQ_FIRST(&linker_files))
96991040Sarr			td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
97091040Sarr		else
97191040Sarr			td->td_retval[0] = 0;
97298452Sarr		mtx_unlock(&kld_mtx);
97391040Sarr		goto out;
97491040Sarr	}
975107849Salfred	lf = linker_find_file_by_id(uap->fileid);
97691040Sarr	if (lf) {
97791040Sarr		if (TAILQ_NEXT(lf, link))
97891040Sarr			td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
97991040Sarr		else
98091040Sarr			td->td_retval[0] = 0;
98191040Sarr	} else
98291040Sarr		error = ENOENT;
98382749Sdillonout:
98491040Sarr	mtx_unlock(&Giant);
98591040Sarr	return (error);
98625537Sdfr}
98725537Sdfr
98882749Sdillon/*
98982749Sdillon * MPSAFE
99082749Sdillon */
99125537Sdfrint
99291040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
99325537Sdfr{
994159587Sjhb	struct kld_file_stat stat;
99591040Sarr	linker_file_t lf;
996159587Sjhb	int error, namelen;
99725537Sdfr
998159587Sjhb	/*
999159587Sjhb	 * Check the version of the user's structure.
1000159587Sjhb	 */
1001159587Sjhb	error = copyin(uap->stat, &stat, sizeof(struct kld_file_stat));
1002159587Sjhb	if (error)
1003159587Sjhb		return (error);
1004159587Sjhb	if (stat.version != sizeof(struct kld_file_stat))
1005159587Sjhb		return (EINVAL);
1006159587Sjhb
1007107089Srwatson#ifdef MAC
1008107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1009107089Srwatson	if (error)
1010107089Srwatson		return (error);
1011107089Srwatson#endif
1012107089Srwatson
101391040Sarr	mtx_lock(&Giant);
101482749Sdillon
1015107849Salfred	lf = linker_find_file_by_id(uap->fileid);
101691040Sarr	if (lf == NULL) {
1017159587Sjhb		mtx_unlock(&Giant);
1018159587Sjhb		return (ENOENT);
101991040Sarr	}
102025537Sdfr
102191040Sarr	namelen = strlen(lf->filename) + 1;
102291040Sarr	if (namelen > MAXPATHLEN)
102391040Sarr		namelen = MAXPATHLEN;
1024159587Sjhb	bcopy(lf->filename, &stat.name[0], namelen);
1025159587Sjhb	stat.refs = lf->refs;
1026159587Sjhb	stat.id = lf->id;
1027159587Sjhb	stat.address = lf->address;
1028159587Sjhb	stat.size = lf->size;
1029159587Sjhb	mtx_unlock(&Giant);
103025537Sdfr
103191040Sarr	td->td_retval[0] = 0;
1032159587Sjhb
1033159587Sjhb	return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat)));
103425537Sdfr}
103525537Sdfr
103682749Sdillon/*
103782749Sdillon * MPSAFE
103882749Sdillon */
103925537Sdfrint
104091040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
104125537Sdfr{
104291040Sarr	linker_file_t lf;
104391040Sarr	module_t mp;
104491040Sarr	int error = 0;
104525537Sdfr
1046107089Srwatson#ifdef MAC
1047107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1048107089Srwatson	if (error)
1049107089Srwatson		return (error);
1050107089Srwatson#endif
1051107089Srwatson
105291040Sarr	mtx_lock(&Giant);
1053107849Salfred	lf = linker_find_file_by_id(uap->fileid);
105491040Sarr	if (lf) {
105592547Sarr		MOD_SLOCK;
105691040Sarr		mp = TAILQ_FIRST(&lf->modules);
105791040Sarr		if (mp != NULL)
105891040Sarr			td->td_retval[0] = module_getid(mp);
105991040Sarr		else
106091040Sarr			td->td_retval[0] = 0;
106192547Sarr		MOD_SUNLOCK;
106291040Sarr	} else
106391040Sarr		error = ENOENT;
106491040Sarr	mtx_unlock(&Giant);
106591040Sarr	return (error);
106625537Sdfr}
106740159Speter
106882749Sdillon/*
106982749Sdillon * MPSAFE
107082749Sdillon */
107141090Speterint
107283366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
107341090Speter{
107491040Sarr	char *symstr = NULL;
107591040Sarr	c_linker_sym_t sym;
107691040Sarr	linker_symval_t symval;
107791040Sarr	linker_file_t lf;
107891040Sarr	struct kld_sym_lookup lookup;
107991040Sarr	int error = 0;
108041090Speter
1081107089Srwatson#ifdef MAC
1082107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1083107089Srwatson	if (error)
1084107089Srwatson		return (error);
1085107089Srwatson#endif
1086107089Srwatson
108791040Sarr	mtx_lock(&Giant);
108882749Sdillon
1089107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
109091040Sarr		goto out;
109191068Sarr	if (lookup.version != sizeof(lookup) ||
1092107849Salfred	    uap->cmd != KLDSYM_LOOKUP) {
109391040Sarr		error = EINVAL;
109491040Sarr		goto out;
109591040Sarr	}
1096111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
109791040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
109891040Sarr		goto out;
1099107849Salfred	if (uap->fileid != 0) {
1100107849Salfred		lf = linker_find_file_by_id(uap->fileid);
110191040Sarr		if (lf == NULL) {
110291040Sarr			error = ENOENT;
110391040Sarr			goto out;
110491040Sarr		}
110591040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
110691040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
110791040Sarr			lookup.symvalue = (uintptr_t) symval.value;
110891040Sarr			lookup.symsize = symval.size;
1109107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
111091040Sarr		} else
111191040Sarr			error = ENOENT;
111291040Sarr	} else {
111398452Sarr		mtx_lock(&kld_mtx);
111491040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
111591040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
111691040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
111791040Sarr				lookup.symvalue = (uintptr_t)symval.value;
111891040Sarr				lookup.symsize = symval.size;
1119107849Salfred				error = copyout(&lookup, uap->data,
112091040Sarr				    sizeof(lookup));
112191068Sarr				break;
112291040Sarr			}
112391040Sarr		}
112498452Sarr		mtx_unlock(&kld_mtx);
112591040Sarr		if (lf == NULL)
112691040Sarr			error = ENOENT;
112741090Speter	}
112841090Speterout:
112991040Sarr	if (symstr)
113091040Sarr		free(symstr, M_TEMP);
113191040Sarr	mtx_unlock(&Giant);
113291040Sarr	return (error);
113341090Speter}
113441090Speter
113540159Speter/*
113640159Speter * Preloaded module support
113740159Speter */
113840159Speter
113959751Speterstatic modlist_t
114074642Sbpmodlist_lookup(const char *name, int ver)
114159751Speter{
114291040Sarr	modlist_t mod;
114359751Speter
114491040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
114592032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
114692032Sdwmalone		    (ver == 0 || mod->version == ver))
114791040Sarr			return (mod);
114891040Sarr	}
114991040Sarr	return (NULL);
115059751Speter}
115159751Speter
115274642Sbpstatic modlist_t
115383321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
115483321Speter{
115591040Sarr	modlist_t mod, bestmod;
115692032Sdwmalone	int ver;
115783321Speter
115891040Sarr	if (verinfo == NULL)
115991040Sarr		return (modlist_lookup(name, 0));
116091040Sarr	bestmod = NULL;
1161159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
116292032Sdwmalone		if (strcmp(mod->name, name) != 0)
116391040Sarr			continue;
116491040Sarr		ver = mod->version;
116591040Sarr		if (ver == verinfo->md_ver_preferred)
116691040Sarr			return (mod);
116791040Sarr		if (ver >= verinfo->md_ver_minimum &&
116891068Sarr		    ver <= verinfo->md_ver_maximum &&
1169120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
117091040Sarr			bestmod = mod;
117191040Sarr	}
117291040Sarr	return (bestmod);
117383321Speter}
117483321Speter
117583321Speterstatic modlist_t
117678501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
117774642Sbp{
117891040Sarr	modlist_t mod;
117974642Sbp
118092705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
118191040Sarr	if (mod == NULL)
118291040Sarr		panic("no memory for module list");
118391040Sarr	mod->container = container;
118491040Sarr	mod->name = modname;
118591040Sarr	mod->version = version;
118691040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
118791040Sarr	return (mod);
118874642Sbp}
118974642Sbp
119040159Speterstatic void
119178161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
119291040Sarr    struct mod_metadata **stop, int preload)
119374642Sbp{
119491040Sarr	struct mod_metadata *mp, **mdp;
119591040Sarr	const char *modname;
119691040Sarr	int ver;
119774642Sbp
119891040Sarr	for (mdp = start; mdp < stop; mdp++) {
1199109605Sjake		mp = *mdp;
120091040Sarr		if (mp->md_type != MDT_VERSION)
120191040Sarr			continue;
1202109605Sjake		modname = mp->md_cval;
1203109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
120491040Sarr		if (modlist_lookup(modname, ver) != NULL) {
120591040Sarr			printf("module %s already present!\n", modname);
120691040Sarr			/* XXX what can we do? this is a build error. :-( */
120791040Sarr			continue;
120891040Sarr		}
120991040Sarr		modlist_newmodule(modname, ver, lf);
121074642Sbp	}
121174642Sbp}
121274642Sbp
121374642Sbpstatic void
121491040Sarrlinker_preload(void *arg)
121540159Speter{
121691040Sarr	caddr_t modptr;
121791040Sarr	const char *modname, *nmodname;
121891040Sarr	char *modtype;
121991040Sarr	linker_file_t lf;
122091040Sarr	linker_class_t lc;
122192032Sdwmalone	int error;
122291040Sarr	linker_file_list_t loaded_files;
122391040Sarr	linker_file_list_t depended_files;
122491040Sarr	struct mod_metadata *mp, *nmp;
122591040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
122691040Sarr	struct mod_depend *verinfo;
122791040Sarr	int nver;
122891040Sarr	int resolves;
122991040Sarr	modlist_t mod;
123091040Sarr	struct sysinit **si_start, **si_stop;
123140159Speter
123291040Sarr	TAILQ_INIT(&loaded_files);
123391040Sarr	TAILQ_INIT(&depended_files);
123491040Sarr	TAILQ_INIT(&found_modules);
123591040Sarr	error = 0;
123659751Speter
123791040Sarr	modptr = NULL;
123891040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
123991040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
124091040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
124191040Sarr		if (modname == NULL) {
124291040Sarr			printf("Preloaded module at %p does not have a"
124391040Sarr			    " name!\n", modptr);
124491040Sarr			continue;
124591040Sarr		}
124691040Sarr		if (modtype == NULL) {
124791040Sarr			printf("Preloaded module at %p does not have a type!\n",
124891040Sarr			    modptr);
124991040Sarr			continue;
125091040Sarr		}
1251131398Sjhb		if (bootverbose)
1252131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1253131398Sjhb			    modptr);
125440159Speter		lf = NULL;
125591040Sarr		TAILQ_FOREACH(lc, &classes, link) {
125691040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1257134364Siedowse			if (!error)
125891040Sarr				break;
1259134364Siedowse			lf = NULL;
126091040Sarr		}
126191040Sarr		if (lf)
126291040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
126340159Speter	}
126440159Speter
126591040Sarr	/*
126691040Sarr	 * First get a list of stuff in the kernel.
126791040Sarr	 */
126891040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
126991040Sarr	    &stop, NULL) == 0)
127091040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
127159751Speter
127259751Speter	/*
127391040Sarr	 * this is a once-off kinky bubble sort resolve relocation dependency
127491040Sarr	 * requirements
127559751Speter	 */
127691040Sarrrestart:
127791040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
127891040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
127991040Sarr		    &stop, NULL);
128091040Sarr		/*
128191040Sarr		 * First, look to see if we would successfully link with this
128291040Sarr		 * stuff.
128391040Sarr		 */
128491040Sarr		resolves = 1;	/* unless we know otherwise */
128591040Sarr		if (!error) {
128691040Sarr			for (mdp = start; mdp < stop; mdp++) {
1287109605Sjake				mp = *mdp;
128891040Sarr				if (mp->md_type != MDT_DEPEND)
128991040Sarr					continue;
1290109605Sjake				modname = mp->md_cval;
1291109605Sjake				verinfo = mp->md_data;
129291040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1293109605Sjake					nmp = *nmdp;
129491040Sarr					if (nmp->md_type != MDT_VERSION)
129591040Sarr						continue;
1296109605Sjake					nmodname = nmp->md_cval;
129792032Sdwmalone					if (strcmp(modname, nmodname) == 0)
129891040Sarr						break;
129991040Sarr				}
130091040Sarr				if (nmdp < stop)   /* it's a self reference */
130191040Sarr					continue;
130291040Sarr
130391040Sarr				/*
130491040Sarr				 * ok, the module isn't here yet, we
130591040Sarr				 * are not finished
130691040Sarr				 */
130791068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
130891040Sarr					resolves = 0;
130991040Sarr			}
131064143Speter		}
131191040Sarr		/*
131291040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
131391040Sarr		 * the modules inside and add it to the end of the link order
131491040Sarr		 * list.
131591040Sarr		 */
131691040Sarr		if (resolves) {
131791040Sarr			if (!error) {
131891040Sarr				for (mdp = start; mdp < stop; mdp++) {
1319109605Sjake					mp = *mdp;
132091040Sarr					if (mp->md_type != MDT_VERSION)
132191040Sarr						continue;
1322109605Sjake					modname = mp->md_cval;
1323109605Sjake					nver = ((struct mod_version *)
1324109605Sjake					    mp->md_data)->mv_version;
132591040Sarr					if (modlist_lookup(modname,
132691040Sarr					    nver) != NULL) {
132791040Sarr						printf("module %s already"
132891040Sarr						    " present!\n", modname);
1329132117Sphk						linker_file_unload(lf,
1330132117Sphk						    LINKER_UNLOAD_FORCE);
133191040Sarr						TAILQ_REMOVE(&loaded_files,
133291040Sarr						    lf, loaded);
133391040Sarr						/* we changed tailq next ptr */
133491068Sarr						goto restart;
133591040Sarr					}
133691040Sarr					modlist_newmodule(modname, nver, lf);
133791040Sarr				}
133891040Sarr			}
133991040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
134091040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
134191040Sarr			/*
134291040Sarr			 * Since we provided modules, we need to restart the
134391040Sarr			 * sort so that the previous files that depend on us
134491040Sarr			 * have a chance. Also, we've busted the tailq next
134591040Sarr			 * pointer with the REMOVE.
134691040Sarr			 */
134791040Sarr			goto restart;
134859751Speter		}
134959751Speter	}
135091040Sarr
135159751Speter	/*
135291040Sarr	 * At this point, we check to see what could not be resolved..
135359751Speter	 */
135491040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
135591040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1356132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
135791040Sarr		TAILQ_REMOVE(&loaded_files, lf, loaded);
135840159Speter	}
135959751Speter
136078161Speter	/*
136191040Sarr	 * We made it. Finish off the linking in the order we determined.
136278161Speter	 */
136391040Sarr	TAILQ_FOREACH(lf, &depended_files, loaded) {
136491040Sarr		if (linker_kernel_file) {
136591040Sarr			linker_kernel_file->refs++;
136691040Sarr			error = linker_file_add_dependency(lf,
136791040Sarr			    linker_kernel_file);
136891040Sarr			if (error)
136991040Sarr				panic("cannot add dependency");
137091040Sarr		}
137191040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
137291040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
137391040Sarr		    &stop, NULL);
137491040Sarr		if (!error) {
137591040Sarr			for (mdp = start; mdp < stop; mdp++) {
1376109605Sjake				mp = *mdp;
137791040Sarr				if (mp->md_type != MDT_DEPEND)
137891040Sarr					continue;
1379109605Sjake				modname = mp->md_cval;
1380109605Sjake				verinfo = mp->md_data;
138191040Sarr				mod = modlist_lookup2(modname, verinfo);
1382151484Sjdp				/* Don't count self-dependencies */
1383151484Sjdp				if (lf == mod->container)
1384151484Sjdp					continue;
138591040Sarr				mod->container->refs++;
138691040Sarr				error = linker_file_add_dependency(lf,
138791040Sarr				    mod->container);
138891040Sarr				if (error)
138991040Sarr					panic("cannot add dependency");
139091040Sarr			}
139191040Sarr		}
139291040Sarr		/*
139391040Sarr		 * Now do relocation etc using the symbol search paths
139491040Sarr		 * established by the dependencies
139591040Sarr		 */
139691040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
139791040Sarr		if (error) {
139891040Sarr			printf("KLD file %s - could not finalize loading\n",
139991040Sarr			    lf->filename);
1400132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
140191040Sarr			continue;
140291040Sarr		}
140391040Sarr		linker_file_register_modules(lf);
140491040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
140591040Sarr		    &si_stop, NULL) == 0)
140691040Sarr			sysinit_add(si_start, si_stop);
140791040Sarr		linker_file_register_sysctls(lf);
140891040Sarr		lf->flags |= LINKER_FILE_LINKED;
140959751Speter	}
141091040Sarr	/* woohoo! we made it! */
141140159Speter}
141240159Speter
141391040SarrSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0)
141440159Speter
141540159Speter/*
141640159Speter * Search for a not-loaded module by name.
141791040Sarr *
141840159Speter * Modules may be found in the following locations:
141991040Sarr *
142091040Sarr * - preloaded (result is just the module name) - on disk (result is full path
142191040Sarr * to module)
142291040Sarr *
142391040Sarr * If the module name is qualified in any way (contains path, etc.) the we
142491040Sarr * simply return a copy of it.
142591040Sarr *
142640159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
142740159Speter * character as a separator to be consistent with the bootloader.
142840159Speter */
142940159Speter
143083321Speterstatic char linker_hintfile[] = "linker.hints";
1431111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
143240159Speter
143340159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
143491040Sarr    sizeof(linker_path), "module load search path");
143540159Speter
143677843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
143770417Speter
143859751Speterstatic char *linker_ext_list[] = {
143983321Speter	"",
144059751Speter	".ko",
144159751Speter	NULL
144259751Speter};
144359751Speter
144483321Speter/*
144591040Sarr * Check if file actually exists either with or without extension listed in
144691040Sarr * the linker_ext_list. (probably should be generic for the rest of the
144791040Sarr * kernel)
144883321Speter */
144959751Speterstatic char *
145091040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
145191040Sarr    int namelen, struct vattr *vap)
145240159Speter{
145391040Sarr	struct nameidata nd;
145491040Sarr	struct thread *td = curthread;	/* XXX */
145591040Sarr	char *result, **cpp, *sep;
145691040Sarr	int error, len, extlen, reclen, flags;
145791040Sarr	enum vtype type;
145840159Speter
145991040Sarr	extlen = 0;
146091040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
146191040Sarr		len = strlen(*cpp);
146291040Sarr		if (len > extlen)
146391040Sarr			extlen = len;
146491040Sarr	}
146591040Sarr	extlen++;		/* trailing '\0' */
146691040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
146783321Speter
146891040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1469111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
147091040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
147191040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
147291040Sarr		    namelen, name, *cpp);
147391040Sarr		/*
147491040Sarr		 * Attempt to open the file, and return the path if
147591040Sarr		 * we succeed and it's a regular file.
147691040Sarr		 */
147791040Sarr		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
147891040Sarr		flags = FREAD;
1479118094Sphk		error = vn_open(&nd, &flags, 0, -1);
148091040Sarr		if (error == 0) {
148191040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
148291040Sarr			type = nd.ni_vp->v_type;
148391040Sarr			if (vap)
148491406Sjhb				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
148591040Sarr			VOP_UNLOCK(nd.ni_vp, 0, td);
148691406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
148791040Sarr			if (type == VREG)
148891040Sarr				return (result);
148991040Sarr		}
149083321Speter	}
149191040Sarr	free(result, M_LINKER);
149291040Sarr	return (NULL);
149383321Speter}
149483321Speter
149591040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
149683321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
149783321Speter
149883321Speter/*
149991040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
150091040Sarr * version specification is available, then try to find the best KLD.
150183321Speter * Otherwise just find the latest one.
150283321Speter */
150383321Speterstatic char *
150491040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
150591040Sarr    int modnamelen, struct mod_depend *verinfo)
150683321Speter{
150791040Sarr	struct thread *td = curthread;	/* XXX */
150891406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
150991040Sarr	struct nameidata nd;
151091040Sarr	struct vattr vattr, mattr;
151191040Sarr	u_char *hints = NULL;
151291040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
151391040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
151483321Speter
151591040Sarr	result = NULL;
151691040Sarr	bestver = found = 0;
151783321Speter
151891040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
151991040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
152091040Sarr	    strlen(sep) + 1;
1521111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
152291040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
152391040Sarr	    linker_hintfile);
152483321Speter
152591040Sarr	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
152691040Sarr	flags = FREAD;
1527118094Sphk	error = vn_open(&nd, &flags, 0, -1);
152891040Sarr	if (error)
152991040Sarr		goto bad;
153091040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
153191040Sarr	if (nd.ni_vp->v_type != VREG)
153291040Sarr		goto bad;
153391040Sarr	best = cp = NULL;
153491040Sarr	error = VOP_GETATTR(nd.ni_vp, &vattr, cred, td);
153591040Sarr	if (error)
153691040Sarr		goto bad;
153791040Sarr	/*
153891040Sarr	 * XXX: we need to limit this number to some reasonable value
153991040Sarr	 */
154091040Sarr	if (vattr.va_size > 100 * 1024) {
154191040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
154291040Sarr		goto bad;
154391040Sarr	}
1544111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
154591040Sarr	if (hints == NULL)
154691040Sarr		goto bad;
154791068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1548101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
154991040Sarr	if (error)
155091040Sarr		goto bad;
155199553Sjeff	VOP_UNLOCK(nd.ni_vp, 0, td);
155291040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
155391040Sarr	nd.ni_vp = NULL;
155491040Sarr	if (reclen != 0) {
155591040Sarr		printf("can't read %d\n", reclen);
155691040Sarr		goto bad;
155791040Sarr	}
155891040Sarr	intp = (int *)hints;
155983321Speter	ival = *intp++;
156091040Sarr	if (ival != LINKER_HINTS_VERSION) {
156191040Sarr		printf("hints file version mismatch %d\n", ival);
156291040Sarr		goto bad;
156383321Speter	}
156491040Sarr	bufend = hints + vattr.va_size;
156591040Sarr	recptr = (u_char *)intp;
156691040Sarr	clen = blen = 0;
156791040Sarr	while (recptr < bufend && !found) {
156891040Sarr		intp = (int *)recptr;
156991040Sarr		reclen = *intp++;
157091040Sarr		ival = *intp++;
157191040Sarr		cp = (char *)intp;
157291040Sarr		switch (ival) {
157391040Sarr		case MDT_VERSION:
157491040Sarr			clen = *cp++;
157591040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
157691040Sarr				break;
157791040Sarr			cp += clen;
157891040Sarr			INT_ALIGN(hints, cp);
157991040Sarr			ival = *(int *)cp;
158091040Sarr			cp += sizeof(int);
158191040Sarr			clen = *cp++;
158291040Sarr			if (verinfo == NULL ||
158391040Sarr			    ival == verinfo->md_ver_preferred) {
158491040Sarr				found = 1;
158591040Sarr				break;
158691040Sarr			}
158791040Sarr			if (ival >= verinfo->md_ver_minimum &&
158891040Sarr			    ival <= verinfo->md_ver_maximum &&
158991040Sarr			    ival > bestver) {
159091040Sarr				bestver = ival;
159191040Sarr				best = cp;
159291040Sarr				blen = clen;
159391040Sarr			}
159491040Sarr			break;
159591040Sarr		default:
159691040Sarr			break;
159791040Sarr		}
159891040Sarr		recptr += reclen + sizeof(int);
159991040Sarr	}
160083321Speter	/*
160191040Sarr	 * Finally check if KLD is in the place
160283321Speter	 */
160391040Sarr	if (found)
160491040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
160591040Sarr	else if (best)
160691040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
160791040Sarr
160891040Sarr	/*
160991040Sarr	 * KLD is newer than hints file. What we should do now?
161091040Sarr	 */
161191040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
161291040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
161391040Sarr		    " file\n", result);
161483321Speterbad:
1615105167Sphk	free(pathbuf, M_LINKER);
161691040Sarr	if (hints)
161791040Sarr		free(hints, M_TEMP);
161899553Sjeff	if (nd.ni_vp != NULL) {
161999553Sjeff		VOP_UNLOCK(nd.ni_vp, 0, td);
162091040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
162199553Sjeff	}
162291040Sarr	/*
162391040Sarr	 * If nothing found or hints is absent - fallback to the old
162491040Sarr	 * way by using "kldname[.ko]" as module name.
162591040Sarr	 */
162691040Sarr	if (!found && !bestver && result == NULL)
162791040Sarr		result = linker_lookup_file(path, pathlen, modname,
162891040Sarr		    modnamelen, NULL);
162991040Sarr	return (result);
163083321Speter}
163183321Speter
163283321Speter/*
163383321Speter * Lookup KLD which contains requested module in the all directories.
163483321Speter */
163583321Speterstatic char *
163683321Speterlinker_search_module(const char *modname, int modnamelen,
163791040Sarr    struct mod_depend *verinfo)
163883321Speter{
163991040Sarr	char *cp, *ep, *result;
164083321Speter
164191040Sarr	/*
164291040Sarr	 * traverse the linker path
164391040Sarr	 */
164491040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
164591040Sarr		/* find the end of this component */
164691040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
164791068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
164891068Sarr		    modnamelen, verinfo);
164991040Sarr		if (result != NULL)
165091040Sarr			return (result);
165191040Sarr		if (*ep == 0)
165291040Sarr			break;
165391040Sarr	}
165491040Sarr	return (NULL);
165583321Speter}
165683321Speter
165783321Speter/*
165883321Speter * Search for module in all directories listed in the linker_path.
165983321Speter */
166083321Speterstatic char *
166183321Speterlinker_search_kld(const char *name)
166283321Speter{
1663158972Sdelphij	char *cp, *ep, *result;
1664158972Sdelphij	int len;
166583321Speter
166691040Sarr	/* qualified at all? */
166791040Sarr	if (index(name, '/'))
166891040Sarr		return (linker_strdup(name));
166940159Speter
167091040Sarr	/* traverse the linker path */
167191040Sarr	len = strlen(name);
167291040Sarr	for (ep = linker_path; *ep; ep++) {
167391040Sarr		cp = ep;
167491040Sarr		/* find the end of this component */
167591040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
167691040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
167791040Sarr		if (result != NULL)
167891040Sarr			return (result);
167991040Sarr	}
168091040Sarr	return (NULL);
168140159Speter}
168259751Speter
168359751Speterstatic const char *
168491040Sarrlinker_basename(const char *path)
168559751Speter{
168691040Sarr	const char *filename;
168759751Speter
168891040Sarr	filename = rindex(path, '/');
168991040Sarr	if (filename == NULL)
169091040Sarr		return path;
169191040Sarr	if (filename[1])
169291040Sarr		filename++;
169391040Sarr	return (filename);
169459751Speter}
169559751Speter
1696157144Sjkoshy#ifdef HWPMC_HOOKS
1697157144Sjkoshy
1698159797Sjhbstruct hwpmc_context {
1699159797Sjhb	int	nobjects;
1700159797Sjhb	int	nmappings;
1701159797Sjhb	struct pmckern_map_in *kobase;
1702159797Sjhb};
1703159797Sjhb
1704159797Sjhbstatic int
1705159797Sjhblinker_hwpmc_list_object(linker_file_t lf, void *arg)
1706159797Sjhb{
1707159797Sjhb	struct hwpmc_context *hc;
1708159797Sjhb
1709159797Sjhb	hc = arg;
1710159797Sjhb
1711159797Sjhb	/* If we run out of mappings, fail. */
1712159797Sjhb	if (hc->nobjects >= hc->nmappings)
1713159797Sjhb		return (1);
1714159797Sjhb
1715159797Sjhb	/* Save the info for this linker file. */
1716159797Sjhb	hc->kobase[hc->nobjects].pm_file = lf->filename;
1717159797Sjhb	hc->kobase[hc->nobjects].pm_address = (uintptr_t)lf->address;
1718159797Sjhb	hc->nobjects++;
1719159797Sjhb	return (0);
1720159797Sjhb}
1721159797Sjhb
172259751Speter/*
1723157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1724157144Sjkoshy */
1725157144Sjkoshyvoid *
1726157144Sjkoshylinker_hwpmc_list_objects(void)
1727157144Sjkoshy{
1728159797Sjhb	struct hwpmc_context hc;
1729157144Sjkoshy
1730159797Sjhb	hc.nmappings = 15;	/* a reasonable default */
1731157144Sjkoshy
1732157144Sjkoshy retry:
1733157144Sjkoshy	/* allocate nmappings+1 entries */
1734159797Sjhb	MALLOC(hc.kobase, struct pmckern_map_in *,
1735159797Sjhb	    (hc.nmappings + 1) * sizeof(struct pmckern_map_in), M_LINKER,
1736157144Sjkoshy	    M_WAITOK | M_ZERO);
1737157144Sjkoshy
1738159797Sjhb	hc.nobjects = 0;
1739159797Sjhb	if (linker_file_foreach(linker_hwpmc_list_object, &hc) != 0) {
1740159797Sjhb		hc.nmappings = hc.nobjects;
1741159797Sjhb		FREE(hc.kobase, M_LINKER);
1742157144Sjkoshy		goto retry;
1743157144Sjkoshy	}
1744157144Sjkoshy
1745159797Sjhb	KASSERT(hc.nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
1746159797Sjhb		"objects?"));
1747157144Sjkoshy
1748157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1749159797Sjhb	KASSERT(hc.kobase[hc.nobjects].pm_file == NULL,
1750157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1751157144Sjkoshy
1752159797Sjhb	return ((void *)hc.kobase);
1753157144Sjkoshy}
1754157144Sjkoshy#endif
1755157144Sjkoshy
1756157144Sjkoshy/*
175791040Sarr * Find a file which contains given module and load it, if "parent" is not
175891040Sarr * NULL, register a reference to it.
175959751Speter */
1760159796Sjhbstatic int
176183321Speterlinker_load_module(const char *kldname, const char *modname,
176291040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
176391040Sarr    struct linker_file **lfpp)
176459751Speter{
176591040Sarr	linker_file_t lfdep;
176691040Sarr	const char *filename;
176791040Sarr	char *pathname;
176891040Sarr	int error;
176959751Speter
177091040Sarr	if (modname == NULL) {
177191040Sarr		/*
177291040Sarr 		 * We have to load KLD
177391040Sarr 		 */
177491068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
177591068Sarr		    " is not NULL"));
177691040Sarr		pathname = linker_search_kld(kldname);
177791040Sarr	} else {
177891040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
177991040Sarr			return (EEXIST);
178094322Sbrian		if (kldname != NULL)
178194322Sbrian			pathname = linker_strdup(kldname);
178295488Sbrian		else if (rootvnode == NULL)
178394322Sbrian			pathname = NULL;
178494322Sbrian		else
178591040Sarr			/*
178691040Sarr			 * Need to find a KLD with required module
178791040Sarr			 */
178891040Sarr			pathname = linker_search_module(modname,
178991040Sarr			    strlen(modname), verinfo);
179091040Sarr	}
179191040Sarr	if (pathname == NULL)
179291040Sarr		return (ENOENT);
179391040Sarr
179483321Speter	/*
179591040Sarr	 * Can't load more than one file with the same basename XXX:
179691040Sarr	 * Actually it should be possible to have multiple KLDs with
179791040Sarr	 * the same basename but different path because they can
179891040Sarr	 * provide different versions of the same modules.
179983321Speter	 */
180091040Sarr	filename = linker_basename(pathname);
1801159792Sjhb	if (linker_find_file_by_name(filename))
180291040Sarr		error = EEXIST;
1803159792Sjhb	else do {
180491040Sarr		error = linker_load_file(pathname, &lfdep);
180591040Sarr		if (error)
180691040Sarr			break;
180791040Sarr		if (modname && verinfo &&
180891040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
1809132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
181091040Sarr			error = ENOENT;
181191040Sarr			break;
181291040Sarr		}
181391040Sarr		if (parent) {
181491040Sarr			error = linker_file_add_dependency(parent, lfdep);
181591040Sarr			if (error)
181691040Sarr				break;
181791040Sarr		}
181891040Sarr		if (lfpp)
181991040Sarr			*lfpp = lfdep;
182091040Sarr	} while (0);
1821159791Sjhb	free(pathname, M_LINKER);
182291040Sarr	return (error);
182359751Speter}
182459751Speter
182559751Speter/*
182691040Sarr * This routine is responsible for finding dependencies of userland initiated
182791040Sarr * kldload(2)'s of files.
182859751Speter */
182959751Speterint
183086469Siedowselinker_load_dependencies(linker_file_t lf)
183159751Speter{
183291040Sarr	linker_file_t lfdep;
183391040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
183491040Sarr	struct mod_metadata *mp, *nmp;
183591040Sarr	struct mod_depend *verinfo;
183691040Sarr	modlist_t mod;
183791040Sarr	const char *modname, *nmodname;
183892032Sdwmalone	int ver, error = 0, count;
183959751Speter
184091040Sarr	/*
184191040Sarr	 * All files are dependant on /kernel.
184291040Sarr	 */
184391040Sarr	if (linker_kernel_file) {
184491040Sarr		linker_kernel_file->refs++;
184591040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
184691040Sarr		if (error)
184791040Sarr			return (error);
184859751Speter	}
184991040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
185091040Sarr	    &count) != 0)
185191040Sarr		return (0);
185291040Sarr	for (mdp = start; mdp < stop; mdp++) {
1853109605Sjake		mp = *mdp;
185491040Sarr		if (mp->md_type != MDT_VERSION)
185591040Sarr			continue;
1856109605Sjake		modname = mp->md_cval;
1857109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
185891040Sarr		mod = modlist_lookup(modname, ver);
185991040Sarr		if (mod != NULL) {
186091040Sarr			printf("interface %s.%d already present in the KLD"
186191040Sarr			    " '%s'!\n", modname, ver,
186291040Sarr			    mod->container->filename);
186391040Sarr			return (EEXIST);
186491040Sarr		}
186591040Sarr	}
186674642Sbp
186791040Sarr	for (mdp = start; mdp < stop; mdp++) {
1868109605Sjake		mp = *mdp;
186991040Sarr		if (mp->md_type != MDT_DEPEND)
187091040Sarr			continue;
1871109605Sjake		modname = mp->md_cval;
1872109605Sjake		verinfo = mp->md_data;
187391040Sarr		nmodname = NULL;
187491040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
1875109605Sjake			nmp = *nmdp;
187691040Sarr			if (nmp->md_type != MDT_VERSION)
187791040Sarr				continue;
1878109605Sjake			nmodname = nmp->md_cval;
187992032Sdwmalone			if (strcmp(modname, nmodname) == 0)
188091040Sarr				break;
188191040Sarr		}
188291040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
188391040Sarr			continue;
188491040Sarr		mod = modlist_lookup2(modname, verinfo);
188591040Sarr		if (mod) {	/* woohoo, it's loaded already */
188691040Sarr			lfdep = mod->container;
188791040Sarr			lfdep->refs++;
188891040Sarr			error = linker_file_add_dependency(lf, lfdep);
188991040Sarr			if (error)
189091040Sarr				break;
189191040Sarr			continue;
189291040Sarr		}
189391040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
189491040Sarr		if (error) {
189591040Sarr			printf("KLD %s: depends on %s - not available\n",
189691040Sarr			    lf->filename, modname);
189791040Sarr			break;
189891040Sarr		}
189959751Speter	}
190059751Speter
190191040Sarr	if (error)
190291040Sarr		return (error);
190391040Sarr	linker_addmodules(lf, start, stop, 0);
190491040Sarr	return (error);
190559751Speter}
190685736Sgreen
190785736Sgreenstatic int
190885736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
190985736Sgreen{
191085736Sgreen	struct sysctl_req *req;
191185736Sgreen
191285736Sgreen	req = opaque;
191385736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
191485736Sgreen}
191585736Sgreen
191685736Sgreen/*
191785736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
191885736Sgreen * in the kernel.
191985736Sgreen */
192085736Sgreenstatic int
192185736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
192285736Sgreen{
192385736Sgreen	linker_file_t lf;
192485736Sgreen	int error;
192585736Sgreen
1926107089Srwatson#ifdef MAC
1927107089Srwatson	error = mac_check_kld_stat(req->td->td_ucred);
1928107089Srwatson	if (error)
1929107089Srwatson		return (error);
1930107089Srwatson#endif
1931126253Struckman	error = sysctl_wire_old_buffer(req, 0);
1932126253Struckman	if (error != 0)
1933126253Struckman		return (error);
193498452Sarr	mtx_lock(&kld_mtx);
193585736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
193685736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
193785736Sgreen		    sysctl_kern_function_list_iterate, req);
193898452Sarr		if (error) {
193998452Sarr			mtx_unlock(&kld_mtx);
194085736Sgreen			return (error);
194198452Sarr		}
194285736Sgreen	}
194398452Sarr	mtx_unlock(&kld_mtx);
194485736Sgreen	return (SYSCTL_OUT(req, "", 1));
194585736Sgreen}
194685736Sgreen
194785736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
194891040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
1949