kern_linker.c revision 159808
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 159808 2006-06-20 21:31:38Z 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>
46159808Sjhb#include <sys/mount.h>
4725537Sdfr#include <sys/linker.h>
4840159Speter#include <sys/fcntl.h>
4940159Speter#include <sys/libkern.h>
5040159Speter#include <sys/namei.h>
5140159Speter#include <sys/vnode.h>
52159588Sjhb#include <sys/syscallsubr.h>
5340159Speter#include <sys/sysctl.h>
5425537Sdfr
5559603Sdfr#include "linker_if.h"
5659603Sdfr
57157144Sjkoshy#ifdef HWPMC_HOOKS
58157144Sjkoshy#include <sys/pmckern.h>
59157144Sjkoshy#endif
60157144Sjkoshy
6140961Speter#ifdef KLD_DEBUG
6240961Speterint kld_debug = 0;
6340961Speter#endif
6440961Speter
6591040Sarr/*
6691040Sarr * static char *linker_search_path(const char *name, struct mod_depend
6791040Sarr * *verinfo);
6891040Sarr */
6991040Sarrstatic const char 	*linker_basename(const char *path);
7059751Speter
71159800Sjhb/*
72159800Sjhb * Find a currently loaded file given its filename.
73159800Sjhb */
74159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename);
75159800Sjhb
76159800Sjhb/*
77159800Sjhb * Find a currently loaded file given its file id.
78159800Sjhb */
79159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid);
80159800Sjhb
8178161Speter/* Metadata from the static kernel */
8278161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata);
8378161Speter
8459751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
8559751Speter
8640906Speterlinker_file_t linker_kernel_file;
8731324Sbde
8898452Sarrstatic struct mtx kld_mtx;	/* kernel linker mutex */
8998452Sarr
9025537Sdfrstatic linker_class_list_t classes;
9150068Sgrogstatic linker_file_list_t linker_files;
9225537Sdfrstatic int next_file_id = 1;
9398452Sarrstatic int linker_no_more_classes = 0;
9425537Sdfr
9586553Sarr#define	LINKER_GET_NEXT_FILE_ID(a) do {					\
9691040Sarr	linker_file_t lftmp;						\
9786553Sarr									\
9886553Sarrretry:									\
9998452Sarr	mtx_lock(&kld_mtx);						\
10091040Sarr	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
10191040Sarr		if (next_file_id == lftmp->id) {			\
10291040Sarr			next_file_id++;					\
10398452Sarr			mtx_unlock(&kld_mtx);				\
10491040Sarr			goto retry;					\
10591040Sarr		}							\
10691040Sarr	}								\
10791040Sarr	(a) = next_file_id;						\
10898452Sarr	mtx_unlock(&kld_mtx);	/* Hold for safe read of id variable */	\
10986553Sarr} while(0)
11086553Sarr
11186553Sarr
11259751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */
11360938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t;
11459751Speterstruct modlist {
11591040Sarr	TAILQ_ENTRY(modlist) link;	/* chain together all modules */
11691040Sarr	linker_file_t   container;
11791040Sarr	const char 	*name;
11891040Sarr	int             version;
11959751Speter};
12091040Sarrtypedef struct modlist *modlist_t;
12191040Sarrstatic modlisthead_t found_modules;
12259751Speter
123159796Sjhbstatic int	linker_file_add_dependency(linker_file_t file,
124159796Sjhb		    linker_file_t dep);
125159796Sjhbstatic int	linker_load_module(const char *kldname,
126159796Sjhb		    const char *modname, struct linker_file *parent,
127159796Sjhb		    struct mod_depend *verinfo, struct linker_file **lfpp);
128159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
12994321Sbrian
13059603Sdfrstatic char *
13159603Sdfrlinker_strdup(const char *str)
13259603Sdfr{
13391040Sarr	char *result;
13459603Sdfr
135111119Simp	if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
13691040Sarr		strcpy(result, str);
13791040Sarr	return (result);
13859603Sdfr}
13959603Sdfr
14025537Sdfrstatic void
14191040Sarrlinker_init(void *arg)
14225537Sdfr{
14391040Sarr
14498452Sarr	mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
14591040Sarr	TAILQ_INIT(&classes);
14691040Sarr	TAILQ_INIT(&linker_files);
14725537Sdfr}
14825537Sdfr
14991040SarrSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
15025537Sdfr
15198452Sarrstatic void
15298452Sarrlinker_stop_class_add(void *arg)
15398452Sarr{
15498452Sarr
15598452Sarr	linker_no_more_classes = 1;
15698452Sarr}
15798452Sarr
15898452SarrSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL)
15998452Sarr
16025537Sdfrint
16159603Sdfrlinker_add_class(linker_class_t lc)
16225537Sdfr{
16391040Sarr
16498452Sarr	/*
165144443Sjhb	 * We disallow any class registration past SI_ORDER_ANY
166144443Sjhb	 * of SI_SUB_KLD.  We bump the reference count to keep the
167144443Sjhb	 * ops from being freed.
16898452Sarr	 */
16998452Sarr	if (linker_no_more_classes == 1)
17098452Sarr		return (EPERM);
17191040Sarr	kobj_class_compile((kobj_class_t) lc);
172144443Sjhb	((kobj_class_t)lc)->refs++;	/* XXX: kobj_mtx */
17391040Sarr	TAILQ_INSERT_TAIL(&classes, lc, link);
17491040Sarr	return (0);
17525537Sdfr}
17625537Sdfr
17725537Sdfrstatic void
17825537Sdfrlinker_file_sysinit(linker_file_t lf)
17925537Sdfr{
18091040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
18125537Sdfr
18291040Sarr	KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
18391040Sarr	    lf->filename));
18425537Sdfr
18591040Sarr	if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
18691040Sarr		return;
18791040Sarr	/*
18891040Sarr	 * Perform a bubble sort of the system initialization objects by
18991040Sarr	 * their subsystem (primary key) and order (secondary key).
19091040Sarr	 *
19191040Sarr	 * Since some things care about execution order, this is the operation
19291040Sarr	 * which ensures continued function.
19391040Sarr	 */
19491040Sarr	for (sipp = start; sipp < stop; sipp++) {
19591040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
19691040Sarr			if ((*sipp)->subsystem < (*xipp)->subsystem ||
19791040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
19891040Sarr			    (*sipp)->order <= (*xipp)->order))
19991040Sarr				continue;	/* skip */
20091040Sarr			save = *sipp;
20191040Sarr			*sipp = *xipp;
20291040Sarr			*xipp = save;
20391040Sarr		}
20425537Sdfr	}
20525537Sdfr
20691040Sarr	/*
20791040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
20891040Sarr	 * Perform each task, and continue on to the next task.
20991040Sarr	 */
21091040Sarr	for (sipp = start; sipp < stop; sipp++) {
21191040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
21291040Sarr			continue;	/* skip dummy task(s) */
21325537Sdfr
21491040Sarr		/* Call function */
21591040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
21691040Sarr	}
21725537Sdfr}
21825537Sdfr
21941055Speterstatic void
22041055Speterlinker_file_sysuninit(linker_file_t lf)
22141055Speter{
22291040Sarr	struct sysinit **start, **stop, **sipp, **xipp, *save;
22341055Speter
22491040Sarr	KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
22591040Sarr	    lf->filename));
22641055Speter
22791068Sarr	if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
22891040Sarr	    NULL) != 0)
22991040Sarr		return;
23041055Speter
23191040Sarr	/*
23291040Sarr	 * Perform a reverse bubble sort of the system initialization objects
23391040Sarr	 * by their subsystem (primary key) and order (secondary key).
23491040Sarr	 *
23591040Sarr	 * Since some things care about execution order, this is the operation
23691040Sarr	 * which ensures continued function.
23791040Sarr	 */
23891040Sarr	for (sipp = start; sipp < stop; sipp++) {
23991040Sarr		for (xipp = sipp + 1; xipp < stop; xipp++) {
24091040Sarr			if ((*sipp)->subsystem > (*xipp)->subsystem ||
24191040Sarr			    ((*sipp)->subsystem == (*xipp)->subsystem &&
24291040Sarr			    (*sipp)->order >= (*xipp)->order))
24391040Sarr				continue;	/* skip */
24491040Sarr			save = *sipp;
24591040Sarr			*sipp = *xipp;
24691040Sarr			*xipp = save;
24791040Sarr		}
24841055Speter	}
24941055Speter
25091040Sarr	/*
25191040Sarr	 * Traverse the (now) ordered list of system initialization tasks.
25291040Sarr	 * Perform each task, and continue on to the next task.
25391040Sarr	 */
25491040Sarr	for (sipp = start; sipp < stop; sipp++) {
25591040Sarr		if ((*sipp)->subsystem == SI_SUB_DUMMY)
25691040Sarr			continue;	/* skip dummy task(s) */
25741055Speter
25891040Sarr		/* Call function */
25991040Sarr		(*((*sipp)->func)) ((*sipp)->udata);
26091040Sarr	}
26141055Speter}
26241055Speter
26344078Sdfrstatic void
26444078Sdfrlinker_file_register_sysctls(linker_file_t lf)
26544078Sdfr{
26691040Sarr	struct sysctl_oid **start, **stop, **oidp;
26744078Sdfr
26891040Sarr	KLD_DPF(FILE,
26991040Sarr	    ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
27091040Sarr	    lf->filename));
27144078Sdfr
27291040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
27391040Sarr		return;
27444078Sdfr
27591040Sarr	for (oidp = start; oidp < stop; oidp++)
27691040Sarr		sysctl_register_oid(*oidp);
27744078Sdfr}
27844078Sdfr
27944078Sdfrstatic void
28044078Sdfrlinker_file_unregister_sysctls(linker_file_t lf)
28144078Sdfr{
28291040Sarr	struct sysctl_oid **start, **stop, **oidp;
28344078Sdfr
28491040Sarr	KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
28591040Sarr	    " for %s\n", lf->filename));
28644078Sdfr
28791040Sarr	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
28891040Sarr		return;
28944078Sdfr
29091040Sarr	for (oidp = start; oidp < stop; oidp++)
29191040Sarr		sysctl_unregister_oid(*oidp);
29244078Sdfr}
29344078Sdfr
29459751Speterstatic int
29559751Speterlinker_file_register_modules(linker_file_t lf)
29659751Speter{
29791040Sarr	struct mod_metadata **start, **stop, **mdp;
29891040Sarr	const moduledata_t *moddata;
299146733Spjd	int first_error, error;
30059751Speter
30191040Sarr	KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
30291040Sarr	    " in %s\n", lf->filename));
30359751Speter
30491068Sarr	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
30591040Sarr	    &stop, 0) != 0) {
30691040Sarr		/*
30791040Sarr		 * This fallback should be unnecessary, but if we get booted
30891040Sarr		 * from boot2 instead of loader and we are missing our
30991040Sarr		 * metadata then we have to try the best we can.
31091040Sarr		 */
31191040Sarr		if (lf == linker_kernel_file) {
31291040Sarr			start = SET_BEGIN(modmetadata_set);
31391040Sarr			stop = SET_LIMIT(modmetadata_set);
31491040Sarr		} else
31591040Sarr			return (0);
31678161Speter	}
317146733Spjd	first_error = 0;
31891040Sarr	for (mdp = start; mdp < stop; mdp++) {
31991040Sarr		if ((*mdp)->md_type != MDT_MODULE)
32091040Sarr			continue;
32191040Sarr		moddata = (*mdp)->md_data;
32291040Sarr		KLD_DPF(FILE, ("Registering module %s in %s\n",
32391040Sarr		    moddata->name, lf->filename));
32491040Sarr		error = module_register(moddata, lf);
325146730Spjd		if (error) {
32691068Sarr			printf("Module %s failed to register: %d\n",
32791040Sarr			    moddata->name, error);
328146733Spjd			if (first_error == 0)
329146733Spjd				first_error = error;
330146730Spjd		}
33159751Speter	}
332146733Spjd	return (first_error);
33359751Speter}
33459751Speter
33559751Speterstatic void
33659751Speterlinker_init_kernel_modules(void)
33759751Speter{
33891040Sarr
33991040Sarr	linker_file_register_modules(linker_kernel_file);
34059751Speter}
34159751Speter
34291040SarrSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 0)
34359751Speter
344101241Smuxstatic int
34591040Sarrlinker_load_file(const char *filename, linker_file_t *result)
34625537Sdfr{
34791040Sarr	linker_class_t lc;
34891040Sarr	linker_file_t lf;
349159585Sjhb	int foundfile, error;
35025537Sdfr
35191040Sarr	/* Refuse to load modules if securelevel raised */
35291040Sarr	if (securelevel > 0)
35391040Sarr		return (EPERM);
35462261Sarchie
35591040Sarr	lf = linker_find_file_by_name(filename);
35691040Sarr	if (lf) {
35791040Sarr		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
35891040Sarr		    " incrementing refs\n", filename));
35991040Sarr		*result = lf;
36091040Sarr		lf->refs++;
361159585Sjhb		return (0);
36291040Sarr	}
36391040Sarr	foundfile = 0;
364159585Sjhb	error = 0;
36598452Sarr
36698452Sarr	/*
36798452Sarr	 * We do not need to protect (lock) classes here because there is
36898452Sarr	 * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY)
36998452Sarr	 * and there is no class deregistration mechanism at this time.
37098452Sarr	 */
37191040Sarr	TAILQ_FOREACH(lc, &classes, link) {
37291040Sarr		KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
37391040Sarr		    filename));
37491040Sarr		error = LINKER_LOAD_FILE(lc, filename, &lf);
37591040Sarr		/*
37691040Sarr		 * If we got something other than ENOENT, then it exists but
37791040Sarr		 * we cannot load it for some other reason.
37891040Sarr		 */
37991040Sarr		if (error != ENOENT)
38091040Sarr			foundfile = 1;
38191040Sarr		if (lf) {
382146730Spjd			error = linker_file_register_modules(lf);
383146730Spjd			if (error == EEXIST) {
384146730Spjd				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
385159585Sjhb				return (error);
386146730Spjd			}
38791040Sarr			linker_file_register_sysctls(lf);
38891040Sarr			linker_file_sysinit(lf);
38991040Sarr			lf->flags |= LINKER_FILE_LINKED;
39091040Sarr			*result = lf;
391159585Sjhb			return (0);
39291040Sarr		}
39391040Sarr	}
39442755Speter	/*
39591040Sarr	 * Less than ideal, but tells the user whether it failed to load or
39691040Sarr	 * the module was not found.
39742755Speter	 */
398105337Ssam	if (foundfile) {
399105337Ssam		/*
400105337Ssam		 * Format not recognized or otherwise unloadable.
401105337Ssam		 * When loading a module that is statically built into
402105337Ssam		 * the kernel EEXIST percolates back up as the return
403105337Ssam		 * value.  Preserve this so that apps like sysinstall
404105337Ssam		 * can recognize this special case and not post bogus
405105337Ssam		 * dialog boxes.
406105337Ssam		 */
407105337Ssam		if (error != EEXIST)
408105337Ssam			error = ENOEXEC;
409105337Ssam	} else
41091068Sarr		error = ENOENT;		/* Nothing found */
41191040Sarr	return (error);
41225537Sdfr}
41325537Sdfr
41478413Sbrianint
41594321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo,
41694321Sbrian    linker_file_t *result)
41778413Sbrian{
41894321Sbrian	modlist_t mod;
419159804Sjhb	int error;
42094321Sbrian
421159804Sjhb	mtx_lock(&Giant);
42294321Sbrian	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
42394321Sbrian		*result = mod->container;
42494321Sbrian		(*result)->refs++;
425159804Sjhb		mtx_unlock(&Giant);
42694321Sbrian		return (0);
42794321Sbrian	}
42894321Sbrian
429159804Sjhb	error = linker_load_module(NULL, modname, NULL, verinfo, result);
430159804Sjhb	mtx_unlock(&Giant);
431159804Sjhb	return (error);
43278413Sbrian}
43378413Sbrian
434159804Sjhbint
435159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo,
436159804Sjhb    linker_file_t lf)
437159804Sjhb{
438159804Sjhb	modlist_t mod;
439159804Sjhb	int error;
440159804Sjhb
441159804Sjhb	mtx_lock(&Giant);
442159804Sjhb	if (lf == NULL) {
443159804Sjhb		KASSERT(modname != NULL,
444159804Sjhb		    ("linker_release_module: no file or name"));
445159804Sjhb		mod = modlist_lookup2(modname, verinfo);
446159804Sjhb		if (mod == NULL) {
447159804Sjhb			mtx_unlock(&Giant);
448159804Sjhb			return (ESRCH);
449159804Sjhb		}
450159804Sjhb		lf = mod->container;
451159804Sjhb	} else
452159804Sjhb		KASSERT(modname == NULL && verinfo == NULL,
453159804Sjhb		    ("linker_release_module: both file and name"));
454159804Sjhb	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
455159804Sjhb	mtx_unlock(&Giant);
456159804Sjhb	return (error);
457159804Sjhb}
458159804Sjhb
459159800Sjhbstatic linker_file_t
46091040Sarrlinker_find_file_by_name(const char *filename)
46125537Sdfr{
462159585Sjhb	linker_file_t lf;
46391040Sarr	char *koname;
46425537Sdfr
465111119Simp	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
46691040Sarr	sprintf(koname, "%s.ko", filename);
46740861Speter
46898452Sarr	mtx_lock(&kld_mtx);
46991040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
47092032Sdwmalone		if (strcmp(lf->filename, koname) == 0)
47191040Sarr			break;
47292032Sdwmalone		if (strcmp(lf->filename, filename) == 0)
47391040Sarr			break;
47491040Sarr	}
47598452Sarr	mtx_unlock(&kld_mtx);
476159585Sjhb	free(koname, M_LINKER);
47791040Sarr	return (lf);
47825537Sdfr}
47925537Sdfr
480159800Sjhbstatic linker_file_t
48125537Sdfrlinker_find_file_by_id(int fileid)
48225537Sdfr{
483159585Sjhb	linker_file_t lf;
48498452Sarr
48598452Sarr	mtx_lock(&kld_mtx);
48691040Sarr	TAILQ_FOREACH(lf, &linker_files, link)
48791040Sarr		if (lf->id == fileid)
48891040Sarr			break;
48998452Sarr	mtx_unlock(&kld_mtx);
49091040Sarr	return (lf);
49125537Sdfr}
49225537Sdfr
493159797Sjhbint
494159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context)
495159797Sjhb{
496159797Sjhb	linker_file_t lf;
497159797Sjhb	int retval = 0;
498159797Sjhb
499159797Sjhb	mtx_lock(&Giant);
500159797Sjhb	TAILQ_FOREACH(lf, &linker_files, link) {
501159797Sjhb		retval = predicate(lf, context);
502159797Sjhb		if (retval != 0)
503159797Sjhb			break;
504159797Sjhb	}
505159797Sjhb	mtx_unlock(&Giant);
506159797Sjhb	return (retval);
507159797Sjhb}
508159797Sjhb
50925537Sdfrlinker_file_t
51091040Sarrlinker_make_file(const char *pathname, linker_class_t lc)
51125537Sdfr{
51291040Sarr	linker_file_t lf;
51391040Sarr	const char *filename;
51425537Sdfr
51591040Sarr	filename = linker_basename(pathname);
51640159Speter
51791040Sarr	KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
518111119Simp	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
51991040Sarr	if (lf == NULL)
520159585Sjhb		return (NULL);
52191040Sarr	lf->refs = 1;
52291040Sarr	lf->userrefs = 0;
52391040Sarr	lf->flags = 0;
52491040Sarr	lf->filename = linker_strdup(filename);
52591040Sarr	LINKER_GET_NEXT_FILE_ID(lf->id);
52691040Sarr	lf->ndeps = 0;
52791040Sarr	lf->deps = NULL;
52891040Sarr	STAILQ_INIT(&lf->common);
52991040Sarr	TAILQ_INIT(&lf->modules);
53098452Sarr	mtx_lock(&kld_mtx);
53191040Sarr	TAILQ_INSERT_TAIL(&linker_files, lf, link);
53298452Sarr	mtx_unlock(&kld_mtx);
53391040Sarr	return (lf);
53425537Sdfr}
53525537Sdfr
53625537Sdfrint
537132117Sphklinker_file_unload(linker_file_t file, int flags)
53825537Sdfr{
53991040Sarr	module_t mod, next;
54091040Sarr	modlist_t ml, nextml;
54191040Sarr	struct common_symbol *cp;
54291040Sarr	int error, i;
54325537Sdfr
54491040Sarr	/* Refuse to unload modules if securelevel raised. */
54591040Sarr	if (securelevel > 0)
54691040Sarr		return (EPERM);
547107089Srwatson#ifdef MAC
548107089Srwatson	error = mac_check_kld_unload(curthread->td_ucred);
549107089Srwatson	if (error)
550107089Srwatson		return (error);
551107089Srwatson#endif
55225537Sdfr
55391040Sarr	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
55491040Sarr
555159584Sjhb	/* Easy case of just dropping a reference. */
556159584Sjhb	if (file->refs > 1) {
557159584Sjhb		file->refs--;
558159584Sjhb		return (0);
559159584Sjhb	}
560159584Sjhb
561159584Sjhb	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
562159584Sjhb	    " informing modules\n"));
563159584Sjhb
564159584Sjhb	/*
565159584Sjhb	 * Inform any modules associated with this file.
566159584Sjhb	 */
567159584Sjhb	MOD_XLOCK;
568159584Sjhb	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
569159584Sjhb		next = module_getfnext(mod);
570159584Sjhb		MOD_XUNLOCK;
571159584Sjhb
57291040Sarr		/*
573159584Sjhb		 * Give the module a chance to veto the unload.
57491040Sarr		 */
575159584Sjhb		if ((error = module_unload(mod, flags)) != 0) {
576159584Sjhb			KLD_DPF(FILE, ("linker_file_unload: module %p"
577159584Sjhb			    " vetoes unload\n", mod));
578159584Sjhb			return (error);
579159584Sjhb		}
58092547Sarr		MOD_XLOCK;
581159584Sjhb		module_release(mod);
582159584Sjhb	}
583159584Sjhb	MOD_XUNLOCK;
58491040Sarr
585159586Sjhb	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
586128057Speadar		if (ml->container == file) {
58791040Sarr			TAILQ_REMOVE(&found_modules, ml, link);
588128057Speadar			free(ml, M_LINKER);
589128057Speadar		}
59091040Sarr	}
59125537Sdfr
59291040Sarr	/*
59391040Sarr	 * Don't try to run SYSUNINITs if we are unloaded due to a
59491040Sarr	 * link error.
59591040Sarr	 */
59691040Sarr	if (file->flags & LINKER_FILE_LINKED) {
59791040Sarr		linker_file_sysuninit(file);
59891040Sarr		linker_file_unregister_sysctls(file);
59925537Sdfr	}
60098452Sarr	mtx_lock(&kld_mtx);
60191040Sarr	TAILQ_REMOVE(&linker_files, file, link);
60298452Sarr	mtx_unlock(&kld_mtx);
60325537Sdfr
60491040Sarr	if (file->deps) {
60591040Sarr		for (i = 0; i < file->ndeps; i++)
606132117Sphk			linker_file_unload(file->deps[i], flags);
60791040Sarr		free(file->deps, M_LINKER);
60891040Sarr		file->deps = NULL;
60959751Speter	}
61091040Sarr	for (cp = STAILQ_FIRST(&file->common); cp;
61191068Sarr	    cp = STAILQ_FIRST(&file->common)) {
61291040Sarr		STAILQ_REMOVE(&file->common, cp, common_symbol, link);
61391040Sarr		free(cp, M_LINKER);
61491040Sarr	}
61559751Speter
61691040Sarr	LINKER_UNLOAD(file);
61791040Sarr	if (file->filename) {
61891040Sarr		free(file->filename, M_LINKER);
61991040Sarr		file->filename = NULL;
62091040Sarr	}
62191040Sarr	kobj_delete((kobj_t) file, M_LINKER);
622159584Sjhb	return (0);
62325537Sdfr}
62425537Sdfr
625159796Sjhbstatic int
62686469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep)
62725537Sdfr{
62891040Sarr	linker_file_t *newdeps;
62925537Sdfr
63091040Sarr	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
631111119Simp	    M_LINKER, M_WAITOK | M_ZERO);
63291040Sarr	if (newdeps == NULL)
63391040Sarr		return (ENOMEM);
63425537Sdfr
63591040Sarr	if (file->deps) {
63691040Sarr		bcopy(file->deps, newdeps,
63791040Sarr		    file->ndeps * sizeof(linker_file_t *));
63891040Sarr		free(file->deps, M_LINKER);
63991040Sarr	}
64091040Sarr	file->deps = newdeps;
64191040Sarr	file->deps[file->ndeps] = dep;
64291040Sarr	file->ndeps++;
64391040Sarr	return (0);
64425537Sdfr}
64525537Sdfr
64678161Speter/*
64791040Sarr * Locate a linker set and its contents.  This is a helper function to avoid
64891040Sarr * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void ***
64978161Speter */
65078161Speterint
65178161Speterlinker_file_lookup_set(linker_file_t file, const char *name,
65291040Sarr    void *firstp, void *lastp, int *countp)
65378161Speter{
65478161Speter
65591040Sarr	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
65678161Speter}
65778161Speter
65825537Sdfrcaddr_t
65991040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
66025537Sdfr{
66191040Sarr	c_linker_sym_t sym;
66291040Sarr	linker_symval_t symval;
66391040Sarr	caddr_t address;
66491040Sarr	size_t common_size = 0;
66592032Sdwmalone	int i;
66625537Sdfr
667109605Sjake	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
66891040Sarr	    file, name, deps));
66925537Sdfr
67091040Sarr	if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
67191040Sarr		LINKER_SYMBOL_VALUES(file, sym, &symval);
67291040Sarr		if (symval.value == 0)
67391040Sarr			/*
67491040Sarr			 * For commons, first look them up in the
67591040Sarr			 * dependencies and only allocate space if not found
67691040Sarr			 * there.
67791040Sarr			 */
67891040Sarr			common_size = symval.size;
67991040Sarr		else {
68091040Sarr			KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
681109605Sjake			    ".value=%p\n", symval.value));
68291040Sarr			return (symval.value);
68391040Sarr		}
68440159Speter	}
68591040Sarr	if (deps) {
68691040Sarr		for (i = 0; i < file->ndeps; i++) {
68791040Sarr			address = linker_file_lookup_symbol(file->deps[i],
68891040Sarr			    name, 0);
68991040Sarr			if (address) {
69091040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
691109605Sjake				    " deps value=%p\n", address));
69291040Sarr				return (address);
69391040Sarr			}
69491040Sarr		}
69525537Sdfr	}
69691040Sarr	if (common_size > 0) {
69791040Sarr		/*
69891040Sarr		 * This is a common symbol which was not found in the
69991040Sarr		 * dependencies.  We maintain a simple common symbol table in
70091040Sarr		 * the file object.
70191040Sarr		 */
70291040Sarr		struct common_symbol *cp;
70342849Speter
70491040Sarr		STAILQ_FOREACH(cp, &file->common, link) {
70592032Sdwmalone			if (strcmp(cp->name, name) == 0) {
70691040Sarr				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
707109605Sjake				    " old common value=%p\n", cp->address));
70891040Sarr				return (cp->address);
70991040Sarr			}
71091040Sarr		}
71191040Sarr		/*
71291040Sarr		 * Round the symbol size up to align.
71391040Sarr		 */
71491040Sarr		common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
71591040Sarr		cp = malloc(sizeof(struct common_symbol)
71691040Sarr		    + common_size + strlen(name) + 1, M_LINKER,
717111119Simp		    M_WAITOK | M_ZERO);
71891040Sarr		cp->address = (caddr_t)(cp + 1);
71991040Sarr		cp->name = cp->address + common_size;
72091040Sarr		strcpy(cp->name, name);
72191040Sarr		bzero(cp->address, common_size);
72291040Sarr		STAILQ_INSERT_TAIL(&file->common, cp, link);
72325537Sdfr
72491040Sarr		KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
725109605Sjake		    " value=%p\n", cp->address));
72691040Sarr		return (cp->address);
72740159Speter	}
72891040Sarr	KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
72991040Sarr	return (0);
73025537Sdfr}
73125537Sdfr
73240159Speter#ifdef DDB
73325537Sdfr/*
73491040Sarr * DDB Helpers.  DDB has to look across multiple files with their own symbol
73591040Sarr * tables and string tables.
73691040Sarr *
73791040Sarr * Note that we do not obey list locking protocols here.  We really don't need
73891040Sarr * DDB to hang because somebody's got the lock held.  We'll take the chance
73991040Sarr * that the files list is inconsistant instead.
74040159Speter */
74140159Speter
74240159Speterint
74343309Sdillonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
74440159Speter{
74591040Sarr	linker_file_t lf;
74640159Speter
74791040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
74891040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
74991040Sarr			return (0);
75091040Sarr	}
75191040Sarr	return (ENOENT);
75240159Speter}
75340159Speter
75440159Speterint
75543309Sdillonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
75640159Speter{
75791040Sarr	linker_file_t lf;
75891040Sarr	c_linker_sym_t best, es;
75991040Sarr	u_long diff, bestdiff, off;
76040159Speter
76191040Sarr	best = 0;
76291040Sarr	off = (uintptr_t)value;
76391040Sarr	bestdiff = off;
76491040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
76591040Sarr		if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
76691040Sarr			continue;
76791040Sarr		if (es != 0 && diff < bestdiff) {
76891040Sarr			best = es;
76991040Sarr			bestdiff = diff;
77091040Sarr		}
77191040Sarr		if (bestdiff == 0)
77291040Sarr			break;
77340159Speter	}
77491040Sarr	if (best) {
77591040Sarr		*sym = best;
77691040Sarr		*diffp = bestdiff;
77791040Sarr		return (0);
77891040Sarr	} else {
77991040Sarr		*sym = 0;
78091040Sarr		*diffp = off;
78191040Sarr		return (ENOENT);
78291040Sarr	}
78340159Speter}
78440159Speter
78540159Speterint
78643309Sdillonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
78740159Speter{
78891040Sarr	linker_file_t lf;
78940159Speter
79091040Sarr	TAILQ_FOREACH(lf, &linker_files, link) {
79191040Sarr		if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
79291040Sarr			return (0);
79391040Sarr	}
79491040Sarr	return (ENOENT);
79540159Speter}
79640159Speter#endif
79740159Speter
79840159Speter/*
79925537Sdfr * Syscalls.
80025537Sdfr */
80182749Sdillon/*
80282749Sdillon * MPSAFE
80382749Sdillon */
80425537Sdfrint
805159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid)
80625537Sdfr{
807157144Sjkoshy#ifdef HWPMC_HOOKS
808157144Sjkoshy	struct pmckern_map_in pkm;
809157144Sjkoshy#endif
810159588Sjhb	const char *kldname, *modname;
81191040Sarr	linker_file_t lf;
812159588Sjhb	int error;
81325537Sdfr
81493159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
815159588Sjhb		return (error);
81693159Sarr
81793593Sjhb	if ((error = suser(td)) != 0)
818159588Sjhb		return (error);
81925537Sdfr
82091040Sarr	/*
821159588Sjhb	 * If file does not contain qualified name or any dot in it
82291040Sarr	 * (kldname.ko, or kldname.ver.ko) treat it as interface
82391040Sarr	 * name.
82491040Sarr	 */
825159588Sjhb	if (index(file, '/') || index(file, '.')) {
826159588Sjhb		kldname = file;
82791040Sarr		modname = NULL;
82891040Sarr	} else {
82991040Sarr		kldname = NULL;
830159588Sjhb		modname = file;
83191040Sarr	}
832159588Sjhb
833159588Sjhb	mtx_lock(&Giant);
83491040Sarr	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
83591040Sarr	if (error)
836159588Sjhb		goto unlock;
83742316Smsmith
838157144Sjkoshy#ifdef HWPMC_HOOKS
839157144Sjkoshy	pkm.pm_file = lf->filename;
840157144Sjkoshy	pkm.pm_address = (uintptr_t) lf->address;
841157144Sjkoshy	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
842157144Sjkoshy#endif
84391040Sarr	lf->userrefs++;
844159588Sjhb	if (fileid != NULL)
845159588Sjhb		*fileid = lf->id;
846159588Sjhbunlock:
84791040Sarr	mtx_unlock(&Giant);
84891040Sarr	return (error);
84925537Sdfr}
85025537Sdfr
851159588Sjhbint
852159588Sjhbkldload(struct thread *td, struct kldload_args *uap)
853159588Sjhb{
854159588Sjhb	char *pathname = NULL;
855159596Smarcel	int error, fileid;
856159588Sjhb
857159588Sjhb	td->td_retval[0] = -1;
858159588Sjhb
859159588Sjhb	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
860159588Sjhb	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
861159596Smarcel	if (error == 0) {
862159596Smarcel		error = kern_kldload(td, pathname, &fileid);
863159596Smarcel		if (error == 0)
864159596Smarcel			td->td_retval[0] = fileid;
865159596Smarcel	}
866159588Sjhb	free(pathname, M_TEMP);
867159588Sjhb	return (error);
868159588Sjhb}
869159588Sjhb
87082749Sdillon/*
87182749Sdillon * MPSAFE
87282749Sdillon */
873159588Sjhbint
874132117Sphkkern_kldunload(struct thread *td, int fileid, int flags)
87525537Sdfr{
876157144Sjkoshy#ifdef HWPMC_HOOKS
877157144Sjkoshy	struct pmckern_map_out pkm;
878157144Sjkoshy#endif
87991040Sarr	linker_file_t lf;
88091040Sarr	int error = 0;
88125537Sdfr
88293159Sarr	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
883159588Sjhb		return (error);
88493159Sarr
88593593Sjhb	if ((error = suser(td)) != 0)
886159588Sjhb		return (error);
88725537Sdfr
888159588Sjhb	mtx_lock(&Giant);
889132117Sphk	lf = linker_find_file_by_id(fileid);
89091040Sarr	if (lf) {
89191040Sarr		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
89291040Sarr		if (lf->userrefs == 0) {
893132117Sphk			/*
894132117Sphk			 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
895132117Sphk			 */
89691040Sarr			printf("kldunload: attempt to unload file that was"
89791040Sarr			    " loaded by the kernel\n");
898159588Sjhb			error = EBUSY;
899159588Sjhb		} else {
900157144Sjkoshy#ifdef HWPMC_HOOKS
901159588Sjhb			/* Save data needed by hwpmc(4) before unloading. */
902159588Sjhb			pkm.pm_address = (uintptr_t) lf->address;
903159588Sjhb			pkm.pm_size = lf->size;
904157144Sjkoshy#endif
905159588Sjhb			lf->userrefs--;
906159588Sjhb			error = linker_file_unload(lf, flags);
907159588Sjhb			if (error)
908159588Sjhb				lf->userrefs++;
909159588Sjhb		}
91091040Sarr	} else
91191040Sarr		error = ENOENT;
912157144Sjkoshy
913157144Sjkoshy#ifdef HWPMC_HOOKS
914157144Sjkoshy	if (error == 0)
915157144Sjkoshy		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
916157144Sjkoshy#endif
91791068Sarr	mtx_unlock(&Giant);
91891068Sarr	return (error);
91925537Sdfr}
92025537Sdfr
92182749Sdillon/*
92282749Sdillon * MPSAFE
92382749Sdillon */
92425537Sdfrint
925132117Sphkkldunload(struct thread *td, struct kldunload_args *uap)
926132117Sphk{
927132117Sphk
928132117Sphk	return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
929132117Sphk}
930132117Sphk
931132117Sphk/*
932132117Sphk * MPSAFE
933132117Sphk */
934132117Sphkint
935132117Sphkkldunloadf(struct thread *td, struct kldunloadf_args *uap)
936132117Sphk{
937132117Sphk
938132117Sphk	if (uap->flags != LINKER_UNLOAD_NORMAL &&
939132117Sphk	    uap->flags != LINKER_UNLOAD_FORCE)
940132117Sphk		return (EINVAL);
941132117Sphk	return (kern_kldunload(td, uap->fileid, uap->flags));
942132117Sphk}
943132117Sphk
944132117Sphk/*
945132117Sphk * MPSAFE
946132117Sphk */
947132117Sphkint
94891040Sarrkldfind(struct thread *td, struct kldfind_args *uap)
94925537Sdfr{
95091040Sarr	char *pathname;
95191040Sarr	const char *filename;
95291040Sarr	linker_file_t lf;
953159791Sjhb	int error;
95425537Sdfr
955107089Srwatson#ifdef MAC
956107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
957107089Srwatson	if (error)
958107089Srwatson		return (error);
959107089Srwatson#endif
960107089Srwatson
96191040Sarr	mtx_lock(&Giant);
96291040Sarr	td->td_retval[0] = -1;
96382749Sdillon
964111119Simp	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
965107855Salfred	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
96691040Sarr		goto out;
96725537Sdfr
96891040Sarr	filename = linker_basename(pathname);
96991040Sarr	lf = linker_find_file_by_name(filename);
97091040Sarr	if (lf)
97191040Sarr		td->td_retval[0] = lf->id;
97291040Sarr	else
97391040Sarr		error = ENOENT;
97425537Sdfrout:
975159791Sjhb	free(pathname, M_TEMP);
97691040Sarr	mtx_unlock(&Giant);
97791040Sarr	return (error);
97825537Sdfr}
97925537Sdfr
98082749Sdillon/*
98182749Sdillon * MPSAFE
98282749Sdillon */
98325537Sdfrint
98491040Sarrkldnext(struct thread *td, struct kldnext_args *uap)
98525537Sdfr{
98691040Sarr	linker_file_t lf;
98791040Sarr	int error = 0;
98825537Sdfr
989107089Srwatson#ifdef MAC
990107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
991107089Srwatson	if (error)
992107089Srwatson		return (error);
993107089Srwatson#endif
994107089Srwatson
99591040Sarr	mtx_lock(&Giant);
99682749Sdillon
997107849Salfred	if (uap->fileid == 0) {
99898452Sarr		mtx_lock(&kld_mtx);
99991040Sarr		if (TAILQ_FIRST(&linker_files))
100091040Sarr			td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
100191040Sarr		else
100291040Sarr			td->td_retval[0] = 0;
100398452Sarr		mtx_unlock(&kld_mtx);
100491040Sarr		goto out;
100591040Sarr	}
1006107849Salfred	lf = linker_find_file_by_id(uap->fileid);
100791040Sarr	if (lf) {
100891040Sarr		if (TAILQ_NEXT(lf, link))
100991040Sarr			td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
101091040Sarr		else
101191040Sarr			td->td_retval[0] = 0;
101291040Sarr	} else
101391040Sarr		error = ENOENT;
101482749Sdillonout:
101591040Sarr	mtx_unlock(&Giant);
101691040Sarr	return (error);
101725537Sdfr}
101825537Sdfr
101982749Sdillon/*
102082749Sdillon * MPSAFE
102182749Sdillon */
102225537Sdfrint
102391040Sarrkldstat(struct thread *td, struct kldstat_args *uap)
102425537Sdfr{
1025159587Sjhb	struct kld_file_stat stat;
102691040Sarr	linker_file_t lf;
1027159587Sjhb	int error, namelen;
102825537Sdfr
1029159587Sjhb	/*
1030159587Sjhb	 * Check the version of the user's structure.
1031159587Sjhb	 */
1032159587Sjhb	error = copyin(uap->stat, &stat, sizeof(struct kld_file_stat));
1033159587Sjhb	if (error)
1034159587Sjhb		return (error);
1035159587Sjhb	if (stat.version != sizeof(struct kld_file_stat))
1036159587Sjhb		return (EINVAL);
1037159587Sjhb
1038107089Srwatson#ifdef MAC
1039107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1040107089Srwatson	if (error)
1041107089Srwatson		return (error);
1042107089Srwatson#endif
1043107089Srwatson
104491040Sarr	mtx_lock(&Giant);
104582749Sdillon
1046107849Salfred	lf = linker_find_file_by_id(uap->fileid);
104791040Sarr	if (lf == NULL) {
1048159587Sjhb		mtx_unlock(&Giant);
1049159587Sjhb		return (ENOENT);
105091040Sarr	}
105125537Sdfr
105291040Sarr	namelen = strlen(lf->filename) + 1;
105391040Sarr	if (namelen > MAXPATHLEN)
105491040Sarr		namelen = MAXPATHLEN;
1055159587Sjhb	bcopy(lf->filename, &stat.name[0], namelen);
1056159587Sjhb	stat.refs = lf->refs;
1057159587Sjhb	stat.id = lf->id;
1058159587Sjhb	stat.address = lf->address;
1059159587Sjhb	stat.size = lf->size;
1060159587Sjhb	mtx_unlock(&Giant);
106125537Sdfr
106291040Sarr	td->td_retval[0] = 0;
1063159587Sjhb
1064159587Sjhb	return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat)));
106525537Sdfr}
106625537Sdfr
106782749Sdillon/*
106882749Sdillon * MPSAFE
106982749Sdillon */
107025537Sdfrint
107191040Sarrkldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
107225537Sdfr{
107391040Sarr	linker_file_t lf;
107491040Sarr	module_t mp;
107591040Sarr	int error = 0;
107625537Sdfr
1077107089Srwatson#ifdef MAC
1078107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1079107089Srwatson	if (error)
1080107089Srwatson		return (error);
1081107089Srwatson#endif
1082107089Srwatson
108391040Sarr	mtx_lock(&Giant);
1084107849Salfred	lf = linker_find_file_by_id(uap->fileid);
108591040Sarr	if (lf) {
108692547Sarr		MOD_SLOCK;
108791040Sarr		mp = TAILQ_FIRST(&lf->modules);
108891040Sarr		if (mp != NULL)
108991040Sarr			td->td_retval[0] = module_getid(mp);
109091040Sarr		else
109191040Sarr			td->td_retval[0] = 0;
109292547Sarr		MOD_SUNLOCK;
109391040Sarr	} else
109491040Sarr		error = ENOENT;
109591040Sarr	mtx_unlock(&Giant);
109691040Sarr	return (error);
109725537Sdfr}
109840159Speter
109982749Sdillon/*
110082749Sdillon * MPSAFE
110182749Sdillon */
110241090Speterint
110383366Sjuliankldsym(struct thread *td, struct kldsym_args *uap)
110441090Speter{
110591040Sarr	char *symstr = NULL;
110691040Sarr	c_linker_sym_t sym;
110791040Sarr	linker_symval_t symval;
110891040Sarr	linker_file_t lf;
110991040Sarr	struct kld_sym_lookup lookup;
111091040Sarr	int error = 0;
111141090Speter
1112107089Srwatson#ifdef MAC
1113107089Srwatson	error = mac_check_kld_stat(td->td_ucred);
1114107089Srwatson	if (error)
1115107089Srwatson		return (error);
1116107089Srwatson#endif
1117107089Srwatson
111891040Sarr	mtx_lock(&Giant);
111982749Sdillon
1120107849Salfred	if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
112191040Sarr		goto out;
112291068Sarr	if (lookup.version != sizeof(lookup) ||
1123107849Salfred	    uap->cmd != KLDSYM_LOOKUP) {
112491040Sarr		error = EINVAL;
112591040Sarr		goto out;
112691040Sarr	}
1127111119Simp	symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
112891040Sarr	if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
112991040Sarr		goto out;
1130107849Salfred	if (uap->fileid != 0) {
1131107849Salfred		lf = linker_find_file_by_id(uap->fileid);
113291040Sarr		if (lf == NULL) {
113391040Sarr			error = ENOENT;
113491040Sarr			goto out;
113591040Sarr		}
113691040Sarr		if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
113791040Sarr		    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
113891040Sarr			lookup.symvalue = (uintptr_t) symval.value;
113991040Sarr			lookup.symsize = symval.size;
1140107855Salfred			error = copyout(&lookup, uap->data, sizeof(lookup));
114191040Sarr		} else
114291040Sarr			error = ENOENT;
114391040Sarr	} else {
114498452Sarr		mtx_lock(&kld_mtx);
114591040Sarr		TAILQ_FOREACH(lf, &linker_files, link) {
114691040Sarr			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
114791040Sarr			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
114891040Sarr				lookup.symvalue = (uintptr_t)symval.value;
114991040Sarr				lookup.symsize = symval.size;
1150107849Salfred				error = copyout(&lookup, uap->data,
115191040Sarr				    sizeof(lookup));
115291068Sarr				break;
115391040Sarr			}
115491040Sarr		}
115598452Sarr		mtx_unlock(&kld_mtx);
115691040Sarr		if (lf == NULL)
115791040Sarr			error = ENOENT;
115841090Speter	}
115941090Speterout:
116091040Sarr	if (symstr)
116191040Sarr		free(symstr, M_TEMP);
116291040Sarr	mtx_unlock(&Giant);
116391040Sarr	return (error);
116441090Speter}
116541090Speter
116640159Speter/*
116740159Speter * Preloaded module support
116840159Speter */
116940159Speter
117059751Speterstatic modlist_t
117174642Sbpmodlist_lookup(const char *name, int ver)
117259751Speter{
117391040Sarr	modlist_t mod;
117459751Speter
117591040Sarr	TAILQ_FOREACH(mod, &found_modules, link) {
117692032Sdwmalone		if (strcmp(mod->name, name) == 0 &&
117792032Sdwmalone		    (ver == 0 || mod->version == ver))
117891040Sarr			return (mod);
117991040Sarr	}
118091040Sarr	return (NULL);
118159751Speter}
118259751Speter
118374642Sbpstatic modlist_t
118483321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo)
118583321Speter{
118691040Sarr	modlist_t mod, bestmod;
118792032Sdwmalone	int ver;
118883321Speter
118991040Sarr	if (verinfo == NULL)
119091040Sarr		return (modlist_lookup(name, 0));
119191040Sarr	bestmod = NULL;
1192159586Sjhb	TAILQ_FOREACH(mod, &found_modules, link) {
119392032Sdwmalone		if (strcmp(mod->name, name) != 0)
119491040Sarr			continue;
119591040Sarr		ver = mod->version;
119691040Sarr		if (ver == verinfo->md_ver_preferred)
119791040Sarr			return (mod);
119891040Sarr		if (ver >= verinfo->md_ver_minimum &&
119991068Sarr		    ver <= verinfo->md_ver_maximum &&
1200120382Sfjoe		    (bestmod == NULL || ver > bestmod->version))
120191040Sarr			bestmod = mod;
120291040Sarr	}
120391040Sarr	return (bestmod);
120483321Speter}
120583321Speter
120683321Speterstatic modlist_t
120778501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container)
120874642Sbp{
120991040Sarr	modlist_t mod;
121074642Sbp
121192705Sarr	mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
121291040Sarr	if (mod == NULL)
121391040Sarr		panic("no memory for module list");
121491040Sarr	mod->container = container;
121591040Sarr	mod->name = modname;
121691040Sarr	mod->version = version;
121791040Sarr	TAILQ_INSERT_TAIL(&found_modules, mod, link);
121891040Sarr	return (mod);
121974642Sbp}
122074642Sbp
122140159Speterstatic void
122278161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start,
122391040Sarr    struct mod_metadata **stop, int preload)
122474642Sbp{
122591040Sarr	struct mod_metadata *mp, **mdp;
122691040Sarr	const char *modname;
122791040Sarr	int ver;
122874642Sbp
122991040Sarr	for (mdp = start; mdp < stop; mdp++) {
1230109605Sjake		mp = *mdp;
123191040Sarr		if (mp->md_type != MDT_VERSION)
123291040Sarr			continue;
1233109605Sjake		modname = mp->md_cval;
1234109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
123591040Sarr		if (modlist_lookup(modname, ver) != NULL) {
123691040Sarr			printf("module %s already present!\n", modname);
123791040Sarr			/* XXX what can we do? this is a build error. :-( */
123891040Sarr			continue;
123991040Sarr		}
124091040Sarr		modlist_newmodule(modname, ver, lf);
124174642Sbp	}
124274642Sbp}
124374642Sbp
124474642Sbpstatic void
124591040Sarrlinker_preload(void *arg)
124640159Speter{
124791040Sarr	caddr_t modptr;
124891040Sarr	const char *modname, *nmodname;
124991040Sarr	char *modtype;
125091040Sarr	linker_file_t lf;
125191040Sarr	linker_class_t lc;
125292032Sdwmalone	int error;
125391040Sarr	linker_file_list_t loaded_files;
125491040Sarr	linker_file_list_t depended_files;
125591040Sarr	struct mod_metadata *mp, *nmp;
125691040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
125791040Sarr	struct mod_depend *verinfo;
125891040Sarr	int nver;
125991040Sarr	int resolves;
126091040Sarr	modlist_t mod;
126191040Sarr	struct sysinit **si_start, **si_stop;
126240159Speter
126391040Sarr	TAILQ_INIT(&loaded_files);
126491040Sarr	TAILQ_INIT(&depended_files);
126591040Sarr	TAILQ_INIT(&found_modules);
126691040Sarr	error = 0;
126759751Speter
126891040Sarr	modptr = NULL;
126991040Sarr	while ((modptr = preload_search_next_name(modptr)) != NULL) {
127091040Sarr		modname = (char *)preload_search_info(modptr, MODINFO_NAME);
127191040Sarr		modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
127291040Sarr		if (modname == NULL) {
127391040Sarr			printf("Preloaded module at %p does not have a"
127491040Sarr			    " name!\n", modptr);
127591040Sarr			continue;
127691040Sarr		}
127791040Sarr		if (modtype == NULL) {
127891040Sarr			printf("Preloaded module at %p does not have a type!\n",
127991040Sarr			    modptr);
128091040Sarr			continue;
128191040Sarr		}
1282131398Sjhb		if (bootverbose)
1283131398Sjhb			printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1284131398Sjhb			    modptr);
128540159Speter		lf = NULL;
128691040Sarr		TAILQ_FOREACH(lc, &classes, link) {
128791040Sarr			error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1288134364Siedowse			if (!error)
128991040Sarr				break;
1290134364Siedowse			lf = NULL;
129191040Sarr		}
129291040Sarr		if (lf)
129391040Sarr			TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
129440159Speter	}
129540159Speter
129691040Sarr	/*
129791040Sarr	 * First get a list of stuff in the kernel.
129891040Sarr	 */
129991040Sarr	if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
130091040Sarr	    &stop, NULL) == 0)
130191040Sarr		linker_addmodules(linker_kernel_file, start, stop, 1);
130259751Speter
130359751Speter	/*
130491040Sarr	 * this is a once-off kinky bubble sort resolve relocation dependency
130591040Sarr	 * requirements
130659751Speter	 */
130791040Sarrrestart:
130891040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
130991040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
131091040Sarr		    &stop, NULL);
131191040Sarr		/*
131291040Sarr		 * First, look to see if we would successfully link with this
131391040Sarr		 * stuff.
131491040Sarr		 */
131591040Sarr		resolves = 1;	/* unless we know otherwise */
131691040Sarr		if (!error) {
131791040Sarr			for (mdp = start; mdp < stop; mdp++) {
1318109605Sjake				mp = *mdp;
131991040Sarr				if (mp->md_type != MDT_DEPEND)
132091040Sarr					continue;
1321109605Sjake				modname = mp->md_cval;
1322109605Sjake				verinfo = mp->md_data;
132391040Sarr				for (nmdp = start; nmdp < stop; nmdp++) {
1324109605Sjake					nmp = *nmdp;
132591040Sarr					if (nmp->md_type != MDT_VERSION)
132691040Sarr						continue;
1327109605Sjake					nmodname = nmp->md_cval;
132892032Sdwmalone					if (strcmp(modname, nmodname) == 0)
132991040Sarr						break;
133091040Sarr				}
133191040Sarr				if (nmdp < stop)   /* it's a self reference */
133291040Sarr					continue;
133391040Sarr
133491040Sarr				/*
133591040Sarr				 * ok, the module isn't here yet, we
133691040Sarr				 * are not finished
133791040Sarr				 */
133891068Sarr				if (modlist_lookup2(modname, verinfo) == NULL)
133991040Sarr					resolves = 0;
134091040Sarr			}
134164143Speter		}
134291040Sarr		/*
134391040Sarr		 * OK, if we found our modules, we can link.  So, "provide"
134491040Sarr		 * the modules inside and add it to the end of the link order
134591040Sarr		 * list.
134691040Sarr		 */
134791040Sarr		if (resolves) {
134891040Sarr			if (!error) {
134991040Sarr				for (mdp = start; mdp < stop; mdp++) {
1350109605Sjake					mp = *mdp;
135191040Sarr					if (mp->md_type != MDT_VERSION)
135291040Sarr						continue;
1353109605Sjake					modname = mp->md_cval;
1354109605Sjake					nver = ((struct mod_version *)
1355109605Sjake					    mp->md_data)->mv_version;
135691040Sarr					if (modlist_lookup(modname,
135791040Sarr					    nver) != NULL) {
135891040Sarr						printf("module %s already"
135991040Sarr						    " present!\n", modname);
1360132117Sphk						linker_file_unload(lf,
1361132117Sphk						    LINKER_UNLOAD_FORCE);
136291040Sarr						TAILQ_REMOVE(&loaded_files,
136391040Sarr						    lf, loaded);
136491040Sarr						/* we changed tailq next ptr */
136591068Sarr						goto restart;
136691040Sarr					}
136791040Sarr					modlist_newmodule(modname, nver, lf);
136891040Sarr				}
136991040Sarr			}
137091040Sarr			TAILQ_REMOVE(&loaded_files, lf, loaded);
137191040Sarr			TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
137291040Sarr			/*
137391040Sarr			 * Since we provided modules, we need to restart the
137491040Sarr			 * sort so that the previous files that depend on us
137591040Sarr			 * have a chance. Also, we've busted the tailq next
137691040Sarr			 * pointer with the REMOVE.
137791040Sarr			 */
137891040Sarr			goto restart;
137959751Speter		}
138059751Speter	}
138191040Sarr
138259751Speter	/*
138391040Sarr	 * At this point, we check to see what could not be resolved..
138459751Speter	 */
138591040Sarr	TAILQ_FOREACH(lf, &loaded_files, loaded) {
138691040Sarr		printf("KLD file %s is missing dependencies\n", lf->filename);
1387132117Sphk		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
138891040Sarr		TAILQ_REMOVE(&loaded_files, lf, loaded);
138940159Speter	}
139059751Speter
139178161Speter	/*
139291040Sarr	 * We made it. Finish off the linking in the order we determined.
139378161Speter	 */
139491040Sarr	TAILQ_FOREACH(lf, &depended_files, loaded) {
139591040Sarr		if (linker_kernel_file) {
139691040Sarr			linker_kernel_file->refs++;
139791040Sarr			error = linker_file_add_dependency(lf,
139891040Sarr			    linker_kernel_file);
139991040Sarr			if (error)
140091040Sarr				panic("cannot add dependency");
140191040Sarr		}
140291040Sarr		lf->userrefs++;	/* so we can (try to) kldunload it */
140391040Sarr		error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
140491040Sarr		    &stop, NULL);
140591040Sarr		if (!error) {
140691040Sarr			for (mdp = start; mdp < stop; mdp++) {
1407109605Sjake				mp = *mdp;
140891040Sarr				if (mp->md_type != MDT_DEPEND)
140991040Sarr					continue;
1410109605Sjake				modname = mp->md_cval;
1411109605Sjake				verinfo = mp->md_data;
141291040Sarr				mod = modlist_lookup2(modname, verinfo);
1413151484Sjdp				/* Don't count self-dependencies */
1414151484Sjdp				if (lf == mod->container)
1415151484Sjdp					continue;
141691040Sarr				mod->container->refs++;
141791040Sarr				error = linker_file_add_dependency(lf,
141891040Sarr				    mod->container);
141991040Sarr				if (error)
142091040Sarr					panic("cannot add dependency");
142191040Sarr			}
142291040Sarr		}
142391040Sarr		/*
142491040Sarr		 * Now do relocation etc using the symbol search paths
142591040Sarr		 * established by the dependencies
142691040Sarr		 */
142791040Sarr		error = LINKER_LINK_PRELOAD_FINISH(lf);
142891040Sarr		if (error) {
142991040Sarr			printf("KLD file %s - could not finalize loading\n",
143091040Sarr			    lf->filename);
1431132117Sphk			linker_file_unload(lf, LINKER_UNLOAD_FORCE);
143291040Sarr			continue;
143391040Sarr		}
143491040Sarr		linker_file_register_modules(lf);
143591040Sarr		if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
143691040Sarr		    &si_stop, NULL) == 0)
143791040Sarr			sysinit_add(si_start, si_stop);
143891040Sarr		linker_file_register_sysctls(lf);
143991040Sarr		lf->flags |= LINKER_FILE_LINKED;
144059751Speter	}
144191040Sarr	/* woohoo! we made it! */
144240159Speter}
144340159Speter
144491040SarrSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0)
144540159Speter
144640159Speter/*
144740159Speter * Search for a not-loaded module by name.
144891040Sarr *
144940159Speter * Modules may be found in the following locations:
145091040Sarr *
145191040Sarr * - preloaded (result is just the module name) - on disk (result is full path
145291040Sarr * to module)
145391040Sarr *
145491040Sarr * If the module name is qualified in any way (contains path, etc.) the we
145591040Sarr * simply return a copy of it.
145691040Sarr *
145740159Speter * The search path can be manipulated via sysctl.  Note that we use the ';'
145840159Speter * character as a separator to be consistent with the bootloader.
145940159Speter */
146040159Speter
146183321Speterstatic char linker_hintfile[] = "linker.hints";
1462111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules";
146340159Speter
146440159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
146591040Sarr    sizeof(linker_path), "module load search path");
146640159Speter
146777843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path));
146870417Speter
146959751Speterstatic char *linker_ext_list[] = {
147083321Speter	"",
147159751Speter	".ko",
147259751Speter	NULL
147359751Speter};
147459751Speter
147583321Speter/*
147691040Sarr * Check if file actually exists either with or without extension listed in
147791040Sarr * the linker_ext_list. (probably should be generic for the rest of the
147891040Sarr * kernel)
147983321Speter */
148059751Speterstatic char *
148191040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name,
148291040Sarr    int namelen, struct vattr *vap)
148340159Speter{
148491040Sarr	struct nameidata nd;
148591040Sarr	struct thread *td = curthread;	/* XXX */
148691040Sarr	char *result, **cpp, *sep;
1487159808Sjhb	int error, len, extlen, reclen, flags, vfslocked;
148891040Sarr	enum vtype type;
148940159Speter
149091040Sarr	extlen = 0;
149191040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
149291040Sarr		len = strlen(*cpp);
149391040Sarr		if (len > extlen)
149491040Sarr			extlen = len;
149591040Sarr	}
149691040Sarr	extlen++;		/* trailing '\0' */
149791040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
149883321Speter
149991040Sarr	reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1500111119Simp	result = malloc(reclen, M_LINKER, M_WAITOK);
150191040Sarr	for (cpp = linker_ext_list; *cpp; cpp++) {
150291040Sarr		snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
150391040Sarr		    namelen, name, *cpp);
150491040Sarr		/*
150591040Sarr		 * Attempt to open the file, and return the path if
150691040Sarr		 * we succeed and it's a regular file.
150791040Sarr		 */
1508159808Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td);
150991040Sarr		flags = FREAD;
1510118094Sphk		error = vn_open(&nd, &flags, 0, -1);
151191040Sarr		if (error == 0) {
1512159808Sjhb			vfslocked = NDHASGIANT(&nd);
151391040Sarr			NDFREE(&nd, NDF_ONLY_PNBUF);
151491040Sarr			type = nd.ni_vp->v_type;
151591040Sarr			if (vap)
151691406Sjhb				VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
151791040Sarr			VOP_UNLOCK(nd.ni_vp, 0, td);
151891406Sjhb			vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
1519159808Sjhb			VFS_UNLOCK_GIANT(vfslocked);
152091040Sarr			if (type == VREG)
152191040Sarr				return (result);
152291040Sarr		}
152383321Speter	}
152491040Sarr	free(result, M_LINKER);
152591040Sarr	return (NULL);
152683321Speter}
152783321Speter
152891040Sarr#define	INT_ALIGN(base, ptr)	ptr =					\
152983321Speter	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
153083321Speter
153183321Speter/*
153291040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If
153391040Sarr * version specification is available, then try to find the best KLD.
153483321Speter * Otherwise just find the latest one.
153583321Speter */
153683321Speterstatic char *
153791040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname,
153891040Sarr    int modnamelen, struct mod_depend *verinfo)
153983321Speter{
154091040Sarr	struct thread *td = curthread;	/* XXX */
154191406Sjhb	struct ucred *cred = td ? td->td_ucred : NULL;
154291040Sarr	struct nameidata nd;
154391040Sarr	struct vattr vattr, mattr;
154491040Sarr	u_char *hints = NULL;
154591040Sarr	u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
154691040Sarr	int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1547159808Sjhb	int vfslocked = 0;
154883321Speter
154991040Sarr	result = NULL;
155091040Sarr	bestver = found = 0;
155183321Speter
155291040Sarr	sep = (path[pathlen - 1] != '/') ? "/" : "";
155391040Sarr	reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
155491040Sarr	    strlen(sep) + 1;
1555111119Simp	pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
155691040Sarr	snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
155791040Sarr	    linker_hintfile);
155883321Speter
1559159808Sjhb	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td);
156091040Sarr	flags = FREAD;
1561118094Sphk	error = vn_open(&nd, &flags, 0, -1);
156291040Sarr	if (error)
156391040Sarr		goto bad;
1564159808Sjhb	vfslocked = NDHASGIANT(&nd);
156591040Sarr	NDFREE(&nd, NDF_ONLY_PNBUF);
156691040Sarr	if (nd.ni_vp->v_type != VREG)
156791040Sarr		goto bad;
156891040Sarr	best = cp = NULL;
156991040Sarr	error = VOP_GETATTR(nd.ni_vp, &vattr, cred, td);
157091040Sarr	if (error)
157191040Sarr		goto bad;
157291040Sarr	/*
157391040Sarr	 * XXX: we need to limit this number to some reasonable value
157491040Sarr	 */
157591040Sarr	if (vattr.va_size > 100 * 1024) {
157691040Sarr		printf("hints file too large %ld\n", (long)vattr.va_size);
157791040Sarr		goto bad;
157891040Sarr	}
1579111119Simp	hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
158091040Sarr	if (hints == NULL)
158191040Sarr		goto bad;
158291068Sarr	error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1583101941Srwatson	    UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
158491040Sarr	if (error)
158591040Sarr		goto bad;
158699553Sjeff	VOP_UNLOCK(nd.ni_vp, 0, td);
158791040Sarr	vn_close(nd.ni_vp, FREAD, cred, td);
1588159808Sjhb	VFS_UNLOCK_GIANT(vfslocked);
158991040Sarr	nd.ni_vp = NULL;
159091040Sarr	if (reclen != 0) {
159191040Sarr		printf("can't read %d\n", reclen);
159291040Sarr		goto bad;
159391040Sarr	}
159491040Sarr	intp = (int *)hints;
159583321Speter	ival = *intp++;
159691040Sarr	if (ival != LINKER_HINTS_VERSION) {
159791040Sarr		printf("hints file version mismatch %d\n", ival);
159891040Sarr		goto bad;
159983321Speter	}
160091040Sarr	bufend = hints + vattr.va_size;
160191040Sarr	recptr = (u_char *)intp;
160291040Sarr	clen = blen = 0;
160391040Sarr	while (recptr < bufend && !found) {
160491040Sarr		intp = (int *)recptr;
160591040Sarr		reclen = *intp++;
160691040Sarr		ival = *intp++;
160791040Sarr		cp = (char *)intp;
160891040Sarr		switch (ival) {
160991040Sarr		case MDT_VERSION:
161091040Sarr			clen = *cp++;
161191040Sarr			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
161291040Sarr				break;
161391040Sarr			cp += clen;
161491040Sarr			INT_ALIGN(hints, cp);
161591040Sarr			ival = *(int *)cp;
161691040Sarr			cp += sizeof(int);
161791040Sarr			clen = *cp++;
161891040Sarr			if (verinfo == NULL ||
161991040Sarr			    ival == verinfo->md_ver_preferred) {
162091040Sarr				found = 1;
162191040Sarr				break;
162291040Sarr			}
162391040Sarr			if (ival >= verinfo->md_ver_minimum &&
162491040Sarr			    ival <= verinfo->md_ver_maximum &&
162591040Sarr			    ival > bestver) {
162691040Sarr				bestver = ival;
162791040Sarr				best = cp;
162891040Sarr				blen = clen;
162991040Sarr			}
163091040Sarr			break;
163191040Sarr		default:
163291040Sarr			break;
163391040Sarr		}
163491040Sarr		recptr += reclen + sizeof(int);
163591040Sarr	}
163683321Speter	/*
163791040Sarr	 * Finally check if KLD is in the place
163883321Speter	 */
163991040Sarr	if (found)
164091040Sarr		result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
164191040Sarr	else if (best)
164291040Sarr		result = linker_lookup_file(path, pathlen, best, blen, &mattr);
164391040Sarr
164491040Sarr	/*
164591040Sarr	 * KLD is newer than hints file. What we should do now?
164691040Sarr	 */
164791040Sarr	if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
164891040Sarr		printf("warning: KLD '%s' is newer than the linker.hints"
164991040Sarr		    " file\n", result);
165083321Speterbad:
1651105167Sphk	free(pathbuf, M_LINKER);
165291040Sarr	if (hints)
165391040Sarr		free(hints, M_TEMP);
165499553Sjeff	if (nd.ni_vp != NULL) {
165599553Sjeff		VOP_UNLOCK(nd.ni_vp, 0, td);
165691040Sarr		vn_close(nd.ni_vp, FREAD, cred, td);
1657159808Sjhb		VFS_UNLOCK_GIANT(vfslocked);
165899553Sjeff	}
165991040Sarr	/*
166091040Sarr	 * If nothing found or hints is absent - fallback to the old
166191040Sarr	 * way by using "kldname[.ko]" as module name.
166291040Sarr	 */
166391040Sarr	if (!found && !bestver && result == NULL)
166491040Sarr		result = linker_lookup_file(path, pathlen, modname,
166591040Sarr		    modnamelen, NULL);
166691040Sarr	return (result);
166783321Speter}
166883321Speter
166983321Speter/*
167083321Speter * Lookup KLD which contains requested module in the all directories.
167183321Speter */
167283321Speterstatic char *
167383321Speterlinker_search_module(const char *modname, int modnamelen,
167491040Sarr    struct mod_depend *verinfo)
167583321Speter{
167691040Sarr	char *cp, *ep, *result;
167783321Speter
167891040Sarr	/*
167991040Sarr	 * traverse the linker path
168091040Sarr	 */
168191040Sarr	for (cp = linker_path; *cp; cp = ep + 1) {
168291040Sarr		/* find the end of this component */
168391040Sarr		for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
168491068Sarr		result = linker_hints_lookup(cp, ep - cp, modname,
168591068Sarr		    modnamelen, verinfo);
168691040Sarr		if (result != NULL)
168791040Sarr			return (result);
168891040Sarr		if (*ep == 0)
168991040Sarr			break;
169091040Sarr	}
169191040Sarr	return (NULL);
169283321Speter}
169383321Speter
169483321Speter/*
169583321Speter * Search for module in all directories listed in the linker_path.
169683321Speter */
169783321Speterstatic char *
169883321Speterlinker_search_kld(const char *name)
169983321Speter{
1700158972Sdelphij	char *cp, *ep, *result;
1701158972Sdelphij	int len;
170283321Speter
170391040Sarr	/* qualified at all? */
170491040Sarr	if (index(name, '/'))
170591040Sarr		return (linker_strdup(name));
170640159Speter
170791040Sarr	/* traverse the linker path */
170891040Sarr	len = strlen(name);
170991040Sarr	for (ep = linker_path; *ep; ep++) {
171091040Sarr		cp = ep;
171191040Sarr		/* find the end of this component */
171291040Sarr		for (; *ep != 0 && *ep != ';'; ep++);
171391040Sarr		result = linker_lookup_file(cp, ep - cp, name, len, NULL);
171491040Sarr		if (result != NULL)
171591040Sarr			return (result);
171691040Sarr	}
171791040Sarr	return (NULL);
171840159Speter}
171959751Speter
172059751Speterstatic const char *
172191040Sarrlinker_basename(const char *path)
172259751Speter{
172391040Sarr	const char *filename;
172459751Speter
172591040Sarr	filename = rindex(path, '/');
172691040Sarr	if (filename == NULL)
172791040Sarr		return path;
172891040Sarr	if (filename[1])
172991040Sarr		filename++;
173091040Sarr	return (filename);
173159751Speter}
173259751Speter
1733157144Sjkoshy#ifdef HWPMC_HOOKS
1734157144Sjkoshy
1735159797Sjhbstruct hwpmc_context {
1736159797Sjhb	int	nobjects;
1737159797Sjhb	int	nmappings;
1738159797Sjhb	struct pmckern_map_in *kobase;
1739159797Sjhb};
1740159797Sjhb
1741159797Sjhbstatic int
1742159797Sjhblinker_hwpmc_list_object(linker_file_t lf, void *arg)
1743159797Sjhb{
1744159797Sjhb	struct hwpmc_context *hc;
1745159797Sjhb
1746159797Sjhb	hc = arg;
1747159797Sjhb
1748159797Sjhb	/* If we run out of mappings, fail. */
1749159797Sjhb	if (hc->nobjects >= hc->nmappings)
1750159797Sjhb		return (1);
1751159797Sjhb
1752159797Sjhb	/* Save the info for this linker file. */
1753159797Sjhb	hc->kobase[hc->nobjects].pm_file = lf->filename;
1754159797Sjhb	hc->kobase[hc->nobjects].pm_address = (uintptr_t)lf->address;
1755159797Sjhb	hc->nobjects++;
1756159797Sjhb	return (0);
1757159797Sjhb}
1758159797Sjhb
175959751Speter/*
1760157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded.
1761157144Sjkoshy */
1762157144Sjkoshyvoid *
1763157144Sjkoshylinker_hwpmc_list_objects(void)
1764157144Sjkoshy{
1765159797Sjhb	struct hwpmc_context hc;
1766157144Sjkoshy
1767159797Sjhb	hc.nmappings = 15;	/* a reasonable default */
1768157144Sjkoshy
1769157144Sjkoshy retry:
1770157144Sjkoshy	/* allocate nmappings+1 entries */
1771159797Sjhb	MALLOC(hc.kobase, struct pmckern_map_in *,
1772159797Sjhb	    (hc.nmappings + 1) * sizeof(struct pmckern_map_in), M_LINKER,
1773157144Sjkoshy	    M_WAITOK | M_ZERO);
1774157144Sjkoshy
1775159797Sjhb	hc.nobjects = 0;
1776159797Sjhb	if (linker_file_foreach(linker_hwpmc_list_object, &hc) != 0) {
1777159797Sjhb		hc.nmappings = hc.nobjects;
1778159797Sjhb		FREE(hc.kobase, M_LINKER);
1779157144Sjkoshy		goto retry;
1780157144Sjkoshy	}
1781157144Sjkoshy
1782159797Sjhb	KASSERT(hc.nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
1783159797Sjhb		"objects?"));
1784157144Sjkoshy
1785157144Sjkoshy	/* The last entry of the malloced area comprises of all zeros. */
1786159797Sjhb	KASSERT(hc.kobase[hc.nobjects].pm_file == NULL,
1787157144Sjkoshy	    ("linker_hwpmc_list_objects: last object not NULL"));
1788157144Sjkoshy
1789159797Sjhb	return ((void *)hc.kobase);
1790157144Sjkoshy}
1791157144Sjkoshy#endif
1792157144Sjkoshy
1793157144Sjkoshy/*
179491040Sarr * Find a file which contains given module and load it, if "parent" is not
179591040Sarr * NULL, register a reference to it.
179659751Speter */
1797159796Sjhbstatic int
179883321Speterlinker_load_module(const char *kldname, const char *modname,
179991040Sarr    struct linker_file *parent, struct mod_depend *verinfo,
180091040Sarr    struct linker_file **lfpp)
180159751Speter{
180291040Sarr	linker_file_t lfdep;
180391040Sarr	const char *filename;
180491040Sarr	char *pathname;
180591040Sarr	int error;
180659751Speter
180791040Sarr	if (modname == NULL) {
180891040Sarr		/*
180991040Sarr 		 * We have to load KLD
181091040Sarr 		 */
181191068Sarr		KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
181291068Sarr		    " is not NULL"));
181391040Sarr		pathname = linker_search_kld(kldname);
181491040Sarr	} else {
181591040Sarr		if (modlist_lookup2(modname, verinfo) != NULL)
181691040Sarr			return (EEXIST);
181794322Sbrian		if (kldname != NULL)
181894322Sbrian			pathname = linker_strdup(kldname);
181995488Sbrian		else if (rootvnode == NULL)
182094322Sbrian			pathname = NULL;
182194322Sbrian		else
182291040Sarr			/*
182391040Sarr			 * Need to find a KLD with required module
182491040Sarr			 */
182591040Sarr			pathname = linker_search_module(modname,
182691040Sarr			    strlen(modname), verinfo);
182791040Sarr	}
182891040Sarr	if (pathname == NULL)
182991040Sarr		return (ENOENT);
183091040Sarr
183183321Speter	/*
183291040Sarr	 * Can't load more than one file with the same basename XXX:
183391040Sarr	 * Actually it should be possible to have multiple KLDs with
183491040Sarr	 * the same basename but different path because they can
183591040Sarr	 * provide different versions of the same modules.
183683321Speter	 */
183791040Sarr	filename = linker_basename(pathname);
1838159792Sjhb	if (linker_find_file_by_name(filename))
183991040Sarr		error = EEXIST;
1840159792Sjhb	else do {
184191040Sarr		error = linker_load_file(pathname, &lfdep);
184291040Sarr		if (error)
184391040Sarr			break;
184491040Sarr		if (modname && verinfo &&
184591040Sarr		    modlist_lookup2(modname, verinfo) == NULL) {
1846132117Sphk			linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
184791040Sarr			error = ENOENT;
184891040Sarr			break;
184991040Sarr		}
185091040Sarr		if (parent) {
185191040Sarr			error = linker_file_add_dependency(parent, lfdep);
185291040Sarr			if (error)
185391040Sarr				break;
185491040Sarr		}
185591040Sarr		if (lfpp)
185691040Sarr			*lfpp = lfdep;
185791040Sarr	} while (0);
1858159791Sjhb	free(pathname, M_LINKER);
185991040Sarr	return (error);
186059751Speter}
186159751Speter
186259751Speter/*
186391040Sarr * This routine is responsible for finding dependencies of userland initiated
186491040Sarr * kldload(2)'s of files.
186559751Speter */
186659751Speterint
186786469Siedowselinker_load_dependencies(linker_file_t lf)
186859751Speter{
186991040Sarr	linker_file_t lfdep;
187091040Sarr	struct mod_metadata **start, **stop, **mdp, **nmdp;
187191040Sarr	struct mod_metadata *mp, *nmp;
187291040Sarr	struct mod_depend *verinfo;
187391040Sarr	modlist_t mod;
187491040Sarr	const char *modname, *nmodname;
187592032Sdwmalone	int ver, error = 0, count;
187659751Speter
187791040Sarr	/*
187891040Sarr	 * All files are dependant on /kernel.
187991040Sarr	 */
188091040Sarr	if (linker_kernel_file) {
188191040Sarr		linker_kernel_file->refs++;
188291040Sarr		error = linker_file_add_dependency(lf, linker_kernel_file);
188391040Sarr		if (error)
188491040Sarr			return (error);
188559751Speter	}
188691040Sarr	if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
188791040Sarr	    &count) != 0)
188891040Sarr		return (0);
188991040Sarr	for (mdp = start; mdp < stop; mdp++) {
1890109605Sjake		mp = *mdp;
189191040Sarr		if (mp->md_type != MDT_VERSION)
189291040Sarr			continue;
1893109605Sjake		modname = mp->md_cval;
1894109605Sjake		ver = ((struct mod_version *)mp->md_data)->mv_version;
189591040Sarr		mod = modlist_lookup(modname, ver);
189691040Sarr		if (mod != NULL) {
189791040Sarr			printf("interface %s.%d already present in the KLD"
189891040Sarr			    " '%s'!\n", modname, ver,
189991040Sarr			    mod->container->filename);
190091040Sarr			return (EEXIST);
190191040Sarr		}
190291040Sarr	}
190374642Sbp
190491040Sarr	for (mdp = start; mdp < stop; mdp++) {
1905109605Sjake		mp = *mdp;
190691040Sarr		if (mp->md_type != MDT_DEPEND)
190791040Sarr			continue;
1908109605Sjake		modname = mp->md_cval;
1909109605Sjake		verinfo = mp->md_data;
191091040Sarr		nmodname = NULL;
191191040Sarr		for (nmdp = start; nmdp < stop; nmdp++) {
1912109605Sjake			nmp = *nmdp;
191391040Sarr			if (nmp->md_type != MDT_VERSION)
191491040Sarr				continue;
1915109605Sjake			nmodname = nmp->md_cval;
191692032Sdwmalone			if (strcmp(modname, nmodname) == 0)
191791040Sarr				break;
191891040Sarr		}
191991040Sarr		if (nmdp < stop)/* early exit, it's a self reference */
192091040Sarr			continue;
192191040Sarr		mod = modlist_lookup2(modname, verinfo);
192291040Sarr		if (mod) {	/* woohoo, it's loaded already */
192391040Sarr			lfdep = mod->container;
192491040Sarr			lfdep->refs++;
192591040Sarr			error = linker_file_add_dependency(lf, lfdep);
192691040Sarr			if (error)
192791040Sarr				break;
192891040Sarr			continue;
192991040Sarr		}
193091040Sarr		error = linker_load_module(NULL, modname, lf, verinfo, NULL);
193191040Sarr		if (error) {
193291040Sarr			printf("KLD %s: depends on %s - not available\n",
193391040Sarr			    lf->filename, modname);
193491040Sarr			break;
193591040Sarr		}
193659751Speter	}
193759751Speter
193891040Sarr	if (error)
193991040Sarr		return (error);
194091040Sarr	linker_addmodules(lf, start, stop, 0);
194191040Sarr	return (error);
194259751Speter}
194385736Sgreen
194485736Sgreenstatic int
194585736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque)
194685736Sgreen{
194785736Sgreen	struct sysctl_req *req;
194885736Sgreen
194985736Sgreen	req = opaque;
195085736Sgreen	return (SYSCTL_OUT(req, name, strlen(name) + 1));
195185736Sgreen}
195285736Sgreen
195385736Sgreen/*
195485736Sgreen * Export a nul-separated, double-nul-terminated list of all function names
195585736Sgreen * in the kernel.
195685736Sgreen */
195785736Sgreenstatic int
195885736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
195985736Sgreen{
196085736Sgreen	linker_file_t lf;
196185736Sgreen	int error;
196285736Sgreen
1963107089Srwatson#ifdef MAC
1964107089Srwatson	error = mac_check_kld_stat(req->td->td_ucred);
1965107089Srwatson	if (error)
1966107089Srwatson		return (error);
1967107089Srwatson#endif
1968126253Struckman	error = sysctl_wire_old_buffer(req, 0);
1969126253Struckman	if (error != 0)
1970126253Struckman		return (error);
197198452Sarr	mtx_lock(&kld_mtx);
197285736Sgreen	TAILQ_FOREACH(lf, &linker_files, link) {
197385736Sgreen		error = LINKER_EACH_FUNCTION_NAME(lf,
197485736Sgreen		    sysctl_kern_function_list_iterate, req);
197598452Sarr		if (error) {
197698452Sarr			mtx_unlock(&kld_mtx);
197785736Sgreen			return (error);
197898452Sarr		}
197985736Sgreen	}
198098452Sarr	mtx_unlock(&kld_mtx);
198185736Sgreen	return (SYSCTL_OUT(req, "", 1));
198285736Sgreen}
198385736Sgreen
198485736SgreenSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
198591040Sarr    NULL, 0, sysctl_kern_function_list, "", "kernel function list");
1986