Deleted Added
full compact
kern_linker.c (90483) kern_linker.c (91040)
1/*-
2 * Copyright (c) 1997-2000 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1997-2000 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/kern/kern_linker.c 90483 2002-02-10 21:29:02Z rwatson $
26 * $FreeBSD: head/sys/kern/kern_linker.c 91040 2002-02-22 04:14:49Z arr $
27 */
28
29#include "opt_ddb.h"
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>

--- 12 unchanged lines hidden (view full) ---

47
48
49#include "linker_if.h"
50
51#ifdef KLD_DEBUG
52int kld_debug = 0;
53#endif
54
27 */
28
29#include "opt_ddb.h"
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>

--- 12 unchanged lines hidden (view full) ---

47
48
49#include "linker_if.h"
50
51#ifdef KLD_DEBUG
52int kld_debug = 0;
53#endif
54
55/*static char *linker_search_path(const char *name, struct mod_depend *verinfo);*/
56static const char *linker_basename(const char* path);
57static int linker_load_module(const char *kldname, const char *modname,
58 struct linker_file *parent, struct mod_depend *verinfo,
59 struct linker_file **lfpp);
55/*
56 * static char *linker_search_path(const char *name, struct mod_depend
57 * *verinfo);
58 */
59static const char *linker_basename(const char *path);
60static int linker_load_module(const char *kldname, const char *modname,
61 struct linker_file *parent, struct mod_depend *verinfo,
62 struct linker_file **lfpp);
60
61/* Metadata from the static kernel */
62SET_DECLARE(modmetadata_set, struct mod_metadata);
63
64MALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
65
66linker_file_t linker_kernel_file;
67
68static struct lock lock; /* lock for the file list */
69static linker_class_list_t classes;
70static linker_file_list_t linker_files;
71static int next_file_id = 1;
72
73#define LINKER_GET_NEXT_FILE_ID(a) do { \
63
64/* Metadata from the static kernel */
65SET_DECLARE(modmetadata_set, struct mod_metadata);
66
67MALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
68
69linker_file_t linker_kernel_file;
70
71static struct lock lock; /* lock for the file list */
72static linker_class_list_t classes;
73static linker_file_list_t linker_files;
74static int next_file_id = 1;
75
76#define LINKER_GET_NEXT_FILE_ID(a) do { \
74 linker_file_t lftmp; \
77 linker_file_t lftmp; \
75 \
76retry: \
78 \
79retry: \
77 TAILQ_FOREACH(lftmp, &linker_files, link) { \
78 if (next_file_id == lftmp->id) { \
79 next_file_id++; \
80 goto retry; \
81 } \
82 } \
83 (a) = next_file_id; \
80 TAILQ_FOREACH(lftmp, &linker_files, link) { \
81 if (next_file_id == lftmp->id) { \
82 next_file_id++; \
83 goto retry; \
84 } \
85 } \
86 (a) = next_file_id; \
84} while(0)
85
86
87/* XXX wrong name; we're looking at version provision tags here, not modules */
88typedef TAILQ_HEAD(, modlist) modlisthead_t;
89struct modlist {
87} while(0)
88
89
90/* XXX wrong name; we're looking at version provision tags here, not modules */
91typedef TAILQ_HEAD(, modlist) modlisthead_t;
92struct modlist {
90 TAILQ_ENTRY(modlist) link; /* chain together all modules */
91 linker_file_t container;
92 const char *name;
93 int version;
93 TAILQ_ENTRY(modlist) link; /* chain together all modules */
94 linker_file_t container;
95 const char *name;
96 int version;
94};
97};
95typedef struct modlist *modlist_t;
96static modlisthead_t found_modules;
98typedef struct modlist *modlist_t;
99static modlisthead_t found_modules;
97
98static char *
99linker_strdup(const char *str)
100{
100
101static char *
102linker_strdup(const char *str)
103{
101 char *result;
104 char *result;
102
105
103 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
104 strcpy(result, str);
105 return(result);
106 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
107 strcpy(result, str);
108 return (result);
106}
107
108static void
109}
110
111static void
109linker_init(void* arg)
112linker_init(void *arg)
110{
113{
111 lockinit(&lock, PVM, "klink", 0, 0);
112 TAILQ_INIT(&classes);
113 TAILQ_INIT(&linker_files);
114
115 lockinit(&lock, PVM, "klink", 0, 0);
116 TAILQ_INIT(&classes);
117 TAILQ_INIT(&linker_files);
114}
115
118}
119
116SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
120SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
117
118int
119linker_add_class(linker_class_t lc)
120{
121
122int
123linker_add_class(linker_class_t lc)
124{
121 kobj_class_compile((kobj_class_t) lc);
122 TAILQ_INSERT_TAIL(&classes, lc, link);
123 return 0;
125
126 kobj_class_compile((kobj_class_t) lc);
127 TAILQ_INSERT_TAIL(&classes, lc, link);
128 return (0);
124}
125
126static void
127linker_file_sysinit(linker_file_t lf)
128{
129}
130
131static void
132linker_file_sysinit(linker_file_t lf)
133{
129 struct sysinit** start, ** stop;
130 struct sysinit** sipp;
131 struct sysinit** xipp;
132 struct sysinit* save;
134 struct sysinit **start, **stop, **sipp, **xipp, *save;
133
135
134 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
135 lf->filename));
136 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
137 lf->filename));
136
138
137 if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
138 return;
139 /*
140 * Perform a bubble sort of the system initialization objects by
141 * their subsystem (primary key) and order (secondary key).
142 *
143 * Since some things care about execution order, this is the
144 * operation which ensures continued function.
145 */
146 for (sipp = start; sipp < stop; sipp++) {
147 for (xipp = sipp + 1; xipp < stop; xipp++) {
148 if ((*sipp)->subsystem < (*xipp)->subsystem ||
149 ((*sipp)->subsystem == (*xipp)->subsystem &&
150 (*sipp)->order <= (*xipp)->order))
151 continue; /* skip*/
152 save = *sipp;
153 *sipp = *xipp;
154 *xipp = save;
139 if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
140 return;
141 /*
142 * Perform a bubble sort of the system initialization objects by
143 * their subsystem (primary key) and order (secondary key).
144 *
145 * Since some things care about execution order, this is the operation
146 * which ensures continued function.
147 */
148 for (sipp = start; sipp < stop; sipp++) {
149 for (xipp = sipp + 1; xipp < stop; xipp++) {
150 if ((*sipp)->subsystem < (*xipp)->subsystem ||
151 ((*sipp)->subsystem == (*xipp)->subsystem &&
152 (*sipp)->order <= (*xipp)->order))
153 continue; /* skip */
154 save = *sipp;
155 *sipp = *xipp;
156 *xipp = save;
157 }
155 }
158 }
156 }
157
159
160 /*
161 * Traverse the (now) ordered list of system initialization tasks.
162 * Perform each task, and continue on to the next task.
163 */
164 for (sipp = start; sipp < stop; sipp++) {
165 if ((*sipp)->subsystem == SI_SUB_DUMMY)
166 continue; /* skip dummy task(s) */
158
167
159 /*
160 * Traverse the (now) ordered list of system initialization tasks.
161 * Perform each task, and continue on to the next task.
162 */
163 for (sipp = start; sipp < stop; sipp++) {
164 if ((*sipp)->subsystem == SI_SUB_DUMMY)
165 continue; /* skip dummy task(s)*/
166
167 /* Call function */
168 (*((*sipp)->func))((*sipp)->udata);
169 }
168 /* Call function */
169 (*((*sipp)->func)) ((*sipp)->udata);
170 }
170}
171
172static void
173linker_file_sysuninit(linker_file_t lf)
174{
171}
172
173static void
174linker_file_sysuninit(linker_file_t lf)
175{
175 struct sysinit** start, ** stop;
176 struct sysinit** sipp;
177 struct sysinit** xipp;
178 struct sysinit* save;
176 struct sysinit **start, **stop, **sipp, **xipp, *save;
179
177
180 KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
181 lf->filename));
178 KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
179 lf->filename));
182
180
183 if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, NULL) != 0)
184 return;
181 if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
182 NULL) != 0)
183 return;
185
184
186 /*
187 * Perform a reverse bubble sort of the system initialization objects
188 * by their subsystem (primary key) and order (secondary key).
189 *
190 * Since some things care about execution order, this is the
191 * operation which ensures continued function.
192 */
193 for (sipp = start; sipp < stop; sipp++) {
194 for (xipp = sipp + 1; xipp < stop; xipp++) {
195 if ((*sipp)->subsystem > (*xipp)->subsystem ||
196 ((*sipp)->subsystem == (*xipp)->subsystem &&
197 (*sipp)->order >= (*xipp)->order))
198 continue; /* skip*/
199 save = *sipp;
200 *sipp = *xipp;
201 *xipp = save;
185 /*
186 * Perform a reverse bubble sort of the system initialization objects
187 * by their subsystem (primary key) and order (secondary key).
188 *
189 * Since some things care about execution order, this is the operation
190 * which ensures continued function.
191 */
192 for (sipp = start; sipp < stop; sipp++) {
193 for (xipp = sipp + 1; xipp < stop; xipp++) {
194 if ((*sipp)->subsystem > (*xipp)->subsystem ||
195 ((*sipp)->subsystem == (*xipp)->subsystem &&
196 (*sipp)->order >= (*xipp)->order))
197 continue; /* skip */
198 save = *sipp;
199 *sipp = *xipp;
200 *xipp = save;
201 }
202 }
202 }
203 }
204
203
205 /*
206 * Traverse the (now) ordered list of system initialization tasks.
207 * Perform each task, and continue on to the next task.
208 */
209 for (sipp = start; sipp < stop; sipp++) {
210 if ((*sipp)->subsystem == SI_SUB_DUMMY)
211 continue; /* skip dummy task(s)*/
204 /*
205 * Traverse the (now) ordered list of system initialization tasks.
206 * Perform each task, and continue on to the next task.
207 */
208 for (sipp = start; sipp < stop; sipp++) {
209 if ((*sipp)->subsystem == SI_SUB_DUMMY)
210 continue; /* skip dummy task(s) */
212
211
213 /* Call function */
214 (*((*sipp)->func))((*sipp)->udata);
215 }
212 /* Call function */
213 (*((*sipp)->func)) ((*sipp)->udata);
214 }
216}
217
218static void
219linker_file_register_sysctls(linker_file_t lf)
220{
215}
216
217static void
218linker_file_register_sysctls(linker_file_t lf)
219{
221 struct sysctl_oid **start, **stop, **oidp;
220 struct sysctl_oid **start, **stop, **oidp;
222
221
223 KLD_DPF(FILE, ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
224 lf->filename));
222 KLD_DPF(FILE,
223 ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
224 lf->filename));
225
225
226 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
227 return;
226 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
227 return;
228
228
229 for (oidp = start; oidp < stop; oidp++)
230 sysctl_register_oid(*oidp);
229 for (oidp = start; oidp < stop; oidp++)
230 sysctl_register_oid(*oidp);
231}
232
233static void
234linker_file_unregister_sysctls(linker_file_t lf)
235{
231}
232
233static void
234linker_file_unregister_sysctls(linker_file_t lf)
235{
236 struct sysctl_oid **start, **stop, **oidp;
236 struct sysctl_oid **start, **stop, **oidp;
237
237
238 KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs for %s\n",
239 lf->filename));
238 KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
239 " for %s\n", lf->filename));
240
240
241 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
242 return;
241 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
242 return;
243
243
244 for (oidp = start; oidp < stop; oidp++)
245 sysctl_unregister_oid(*oidp);
244 for (oidp = start; oidp < stop; oidp++)
245 sysctl_unregister_oid(*oidp);
246}
247
248static int
249linker_file_register_modules(linker_file_t lf)
250{
246}
247
248static int
249linker_file_register_modules(linker_file_t lf)
250{
251 int error;
252 struct mod_metadata **start, **stop;
253 struct mod_metadata **mdp;
254 const moduledata_t *moddata;
251 struct mod_metadata **start, **stop, **mdp;
252 const moduledata_t *moddata;
253 int error;
255
254
256 KLD_DPF(FILE, ("linker_file_register_modules: registering modules in %s\n",
257 lf->filename));
255 KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
256 " in %s\n", lf->filename));
258
257
259 if (linker_file_lookup_set(lf, "modmetadata_set", &start, &stop, 0) != 0) {
260 /*
261 * This fallback should be unnecessary, but if we get booted from
262 * boot2 instead of loader and we are missing our metadata then
263 * we have to try the best we can.
264 */
265 if (lf == linker_kernel_file) {
266 start = SET_BEGIN(modmetadata_set);
267 stop = SET_LIMIT(modmetadata_set);
268 } else {
269 return 0;
258 if (linker_file_lookup_set(lf, "modmetadata_set", &start,
259 &stop, 0) != 0) {
260 /*
261 * This fallback should be unnecessary, but if we get booted
262 * from boot2 instead of loader and we are missing our
263 * metadata then we have to try the best we can.
264 */
265 if (lf == linker_kernel_file) {
266 start = SET_BEGIN(modmetadata_set);
267 stop = SET_LIMIT(modmetadata_set);
268 } else
269 return (0);
270 }
270 }
271 }
272 for (mdp = start; mdp < stop; mdp++) {
273 if ((*mdp)->md_type != MDT_MODULE)
274 continue;
275 moddata = (*mdp)->md_data;
276 KLD_DPF(FILE, ("Registering module %s in %s\n",
277 moddata->name, lf->filename));
278 if (module_lookupbyname(moddata->name) != NULL) {
279 printf("Warning: module %s already exists\n", moddata->name);
280 continue; /* or return a error ? */
271 for (mdp = start; mdp < stop; mdp++) {
272 if ((*mdp)->md_type != MDT_MODULE)
273 continue;
274 moddata = (*mdp)->md_data;
275 KLD_DPF(FILE, ("Registering module %s in %s\n",
276 moddata->name, lf->filename));
277 if (module_lookupbyname(moddata->name) != NULL) {
278 printf("Warning: module %s already exists\n",
279 moddata->name);
280 continue; /* or return a error ? */
281 }
282 error = module_register(moddata, lf);
283 if (error)
284 printf("Module %s failed to register: %d\n",
285 moddata->name, error);
281 }
286 }
282 error = module_register(moddata, lf);
283 if (error)
284 printf("Module %s failed to register: %d\n", moddata->name, error);
285 }
286 return 0;
287 return (0);
287}
288
289static void
290linker_init_kernel_modules(void)
291{
288}
289
290static void
291linker_init_kernel_modules(void)
292{
292 linker_file_register_modules(linker_kernel_file);
293
294 linker_file_register_modules(linker_kernel_file);
293}
294
295}
296
295SYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 0);
297SYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 0)
296
297int
298
299int
298linker_load_file(const char* filename, linker_file_t* result)
300linker_load_file(const char *filename, linker_file_t *result)
299{
301{
300 linker_class_t lc;
301 linker_file_t lf;
302 int foundfile, error = 0;
302 linker_class_t lc;
303 linker_file_t lf;
304 int foundfile, error = 0;
303
305
304 /* Refuse to load modules if securelevel raised */
305 if (securelevel > 0)
306 return EPERM;
306 /* Refuse to load modules if securelevel raised */
307 if (securelevel > 0)
308 return (EPERM);
307
309
308 lf = linker_find_file_by_name(filename);
309 if (lf) {
310 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename));
311 *result = lf;
312 lf->refs++;
313 goto out;
314 }
315
316 lf = NULL;
317 foundfile = 0;
318 TAILQ_FOREACH(lc, &classes, link) {
319 KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
320 filename));
321 error = LINKER_LOAD_FILE(lc, filename, &lf);
322 /*
323 * If we got something other than ENOENT, then it exists but we cannot
324 * load it for some other reason.
325 */
326 if (error != ENOENT)
327 foundfile = 1;
310 lf = linker_find_file_by_name(filename);
328 if (lf) {
311 if (lf) {
329 linker_file_register_modules(lf);
330 linker_file_register_sysctls(lf);
331 linker_file_sysinit(lf);
332 lf->flags |= LINKER_FILE_LINKED;
333
334 *result = lf;
335 error = 0;
336 goto out;
312 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
313 " incrementing refs\n", filename));
314 *result = lf;
315 lf->refs++;
316 goto out;
337 }
317 }
338 }
339 /*
340 * Less than ideal, but tells the user whether it failed to load or
341 * the module was not found.
342 */
343 if (foundfile)
344 error = ENOEXEC; /* Format not recognised (or unloadable) */
345 else
346 error = ENOENT; /* Nothing found */
347
318 lf = NULL;
319 foundfile = 0;
320 TAILQ_FOREACH(lc, &classes, link) {
321 KLD_DPF(FILE, ("linker_load_file: trying to load %s\n",
322 filename));
323 error = LINKER_LOAD_FILE(lc, filename, &lf);
324 /*
325 * If we got something other than ENOENT, then it exists but
326 * we cannot load it for some other reason.
327 */
328 if (error != ENOENT)
329 foundfile = 1;
330 if (lf) {
331 linker_file_register_modules(lf);
332 linker_file_register_sysctls(lf);
333 linker_file_sysinit(lf);
334 lf->flags |= LINKER_FILE_LINKED;
335 *result = lf;
336 error = 0;
337 goto out;
338 }
339 }
340 /*
341 * Less than ideal, but tells the user whether it failed to load or
342 * the module was not found.
343 */
344 if (foundfile)
345 error = ENOEXEC; /* Format not recognised (or unloadable) */
346 else
347 error = ENOENT; /* Nothing found */
348out:
348out:
349 return error;
349 return (error);
350}
351
352/* XXX: function parameters are incomplete */
353int
354linker_reference_module(const char *modname, linker_file_t *result)
355{
350}
351
352/* XXX: function parameters are incomplete */
353int
354linker_reference_module(const char *modname, linker_file_t *result)
355{
356
357 return linker_load_module(NULL, modname, NULL, NULL, result);
356 return (linker_load_module(NULL, modname, NULL, NULL, result));
358}
359
360linker_file_t
357}
358
359linker_file_t
361linker_find_file_by_name(const char* filename)
360linker_find_file_by_name(const char *filename)
362{
361{
363 linker_file_t lf = 0;
364 char *koname;
362 linker_file_t lf = 0;
363 char *koname;
364 int err;
365
365
366 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
367 if (koname == NULL)
368 goto out;
369 sprintf(koname, "%s.ko", filename);
366 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
367 if (koname == NULL)
368 goto out;
369 sprintf(koname, "%s.ko", filename);
370
370
371 lockmgr(&lock, LK_SHARED, 0, curthread);
372 TAILQ_FOREACH(lf, &linker_files, link) {
373 if (!strcmp(lf->filename, koname))
374 break;
375 if (!strcmp(lf->filename, filename))
376 break;
377 }
378 lockmgr(&lock, LK_RELEASE, 0, curthread);
379
371 lockmgr(&lock, LK_SHARED, 0, curthread);
372 TAILQ_FOREACH(lf, &linker_files, link) {
373 err = strcmp(lf->filename, koname);
374 if (err == 0)
375 break;
376 err = strcmp(lf->filename, filename);
377 if (err == 0)
378 break;
379 }
380 lockmgr(&lock, LK_RELEASE, 0, curthread);
380out:
381out:
381 if (koname)
382 free(koname, M_LINKER);
383 return lf;
382 if (koname)
383 free(koname, M_LINKER);
384 return (lf);
384}
385
386linker_file_t
387linker_find_file_by_id(int fileid)
388{
385}
386
387linker_file_t
388linker_find_file_by_id(int fileid)
389{
389 linker_file_t lf = 0;
390 linker_file_t lf = 0;
390
391
391 lockmgr(&lock, LK_SHARED, 0, curthread);
392 TAILQ_FOREACH(lf, &linker_files, link)
393 if (lf->id == fileid)
394 break;
395 lockmgr(&lock, LK_RELEASE, 0, curthread);
396
397 return lf;
392 lockmgr(&lock, LK_SHARED, 0, curthread);
393 TAILQ_FOREACH(lf, &linker_files, link)
394 if (lf->id == fileid)
395 break;
396 lockmgr(&lock, LK_RELEASE, 0, curthread);
397 return (lf);
398}
399
400linker_file_t
398}
399
400linker_file_t
401linker_make_file(const char* pathname, linker_class_t lc)
401linker_make_file(const char *pathname, linker_class_t lc)
402{
402{
403 linker_file_t lf = 0;
404 const char *filename;
403 linker_file_t lf;
404 const char *filename;
405
405
406 filename = linker_basename(pathname);
406 lf = NULL;
407 filename = linker_basename(pathname);
407
408
408 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
409 lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
410 lf = (linker_file_t) kobj_create((kobj_class_t) lc, M_LINKER, M_WAITOK);
411 if (!lf)
412 goto out;
413
414 lf->refs = 1;
415 lf->userrefs = 0;
416 lf->flags = 0;
417 lf->filename = linker_strdup(filename);
418 LINKER_GET_NEXT_FILE_ID(lf->id);
419 lf->ndeps = 0;
420 lf->deps = NULL;
421 STAILQ_INIT(&lf->common);
422 TAILQ_INIT(&lf->modules);
423
424 TAILQ_INSERT_TAIL(&linker_files, lf, link);
425
409 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
410 lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
411 lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
412 if (lf == NULL)
413 goto out;
414 lf->refs = 1;
415 lf->userrefs = 0;
416 lf->flags = 0;
417 lf->filename = linker_strdup(filename);
418 LINKER_GET_NEXT_FILE_ID(lf->id);
419 lf->ndeps = 0;
420 lf->deps = NULL;
421 STAILQ_INIT(&lf->common);
422 TAILQ_INIT(&lf->modules);
423 TAILQ_INSERT_TAIL(&linker_files, lf, link);
426out:
424out:
427 lockmgr(&lock, LK_RELEASE, 0, curthread);
428 return lf;
425 lockmgr(&lock, LK_RELEASE, 0, curthread);
426 return (lf);
429}
430
431int
432linker_file_unload(linker_file_t file)
433{
427}
428
429int
430linker_file_unload(linker_file_t file)
431{
434 module_t mod, next;
435 modlist_t ml, nextml;
436 struct common_symbol* cp;
437 int error = 0;
438 int i;
432 module_t mod, next;
433 modlist_t ml, nextml;
434 struct common_symbol *cp;
435 int error, i;
439
436
440 /* Refuse to unload modules if securelevel raised */
441 if (securelevel > 0)
442 return EPERM;
437 error = 0;
443
438
444 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
445 lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
446 if (file->refs == 1) {
447 KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
448 /*
449 * Inform any modules associated with this file.
450 */
451 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
452 next = module_getfnext(mod);
439 /* Refuse to unload modules if securelevel raised. */
440 if (securelevel > 0)
441 return (EPERM);
453
442
454 /*
455 * Give the module a chance to veto the unload.
456 */
457 if ((error = module_unload(mod)) != 0) {
458 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
459 mod));
443 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
444 lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
445 if (file->refs == 1) {
446 KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
447 " informing modules\n"));
448
449 /*
450 * Inform any modules associated with this file.
451 */
452 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
453 next = module_getfnext(mod);
454
455 /*
456 * Give the module a chance to veto the unload.
457 */
458 if ((error = module_unload(mod)) != 0) {
459 KLD_DPF(FILE, ("linker_file_unload: module %x"
460 " vetoes unload\n", mod));
461 lockmgr(&lock, LK_RELEASE, 0, curthread);
462 goto out;
463 }
464 module_release(mod);
465 }
466 }
467 file->refs--;
468 if (file->refs > 0) {
460 lockmgr(&lock, LK_RELEASE, 0, curthread);
461 goto out;
469 lockmgr(&lock, LK_RELEASE, 0, curthread);
470 goto out;
462 }
463
464 module_release(mod);
465 }
471 }
466 }
472 for (ml = TAILQ_FIRST(&found_modules); ml; ml = nextml) {
473 nextml = TAILQ_NEXT(ml, link);
474 if (ml->container == file)
475 TAILQ_REMOVE(&found_modules, ml, link);
476 }
467
477
468 file->refs--;
469 if (file->refs > 0) {
478 /*
479 * Don't try to run SYSUNINITs if we are unloaded due to a
480 * link error.
481 */
482 if (file->flags & LINKER_FILE_LINKED) {
483 linker_file_sysuninit(file);
484 linker_file_unregister_sysctls(file);
485 }
486 TAILQ_REMOVE(&linker_files, file, link);
470 lockmgr(&lock, LK_RELEASE, 0, curthread);
487 lockmgr(&lock, LK_RELEASE, 0, curthread);
471 goto out;
472 }
473
488
474 for (ml = TAILQ_FIRST(&found_modules); ml; ml = nextml) {
475 nextml = TAILQ_NEXT(ml, link);
476 if (ml->container == file) {
477 TAILQ_REMOVE(&found_modules, ml, link);
489 if (file->deps) {
490 for (i = 0; i < file->ndeps; i++)
491 linker_file_unload(file->deps[i]);
492 free(file->deps, M_LINKER);
493 file->deps = NULL;
478 }
494 }
479 }
495 for (cp = STAILQ_FIRST(&file->common); cp;
496 cp = STAILQ_FIRST(&file->common)) {
497 STAILQ_REMOVE(&file->common, cp, common_symbol, link);
498 free(cp, M_LINKER);
499 }
480
500
481 /* Don't try to run SYSUNINITs if we are unloaded due to a link error */
482 if (file->flags & LINKER_FILE_LINKED) {
483 linker_file_sysuninit(file);
484 linker_file_unregister_sysctls(file);
485 }
486
487 TAILQ_REMOVE(&linker_files, file, link);
488 lockmgr(&lock, LK_RELEASE, 0, curthread);
489
490 if (file->deps) {
491 for (i = 0; i < file->ndeps; i++)
492 linker_file_unload(file->deps[i]);
493 free(file->deps, M_LINKER);
494 file->deps = NULL;
495 }
496
497 for (cp = STAILQ_FIRST(&file->common); cp;
498 cp = STAILQ_FIRST(&file->common)) {
499 STAILQ_REMOVE(&file->common, cp, common_symbol, link);
500 free(cp, M_LINKER);
501 }
502
503 LINKER_UNLOAD(file);
504 if (file->filename) {
505 free(file->filename, M_LINKER);
506 file->filename = NULL;
507 }
508 kobj_delete((kobj_t) file, M_LINKER);
509
501 LINKER_UNLOAD(file);
502 if (file->filename) {
503 free(file->filename, M_LINKER);
504 file->filename = NULL;
505 }
506 kobj_delete((kobj_t) file, M_LINKER);
510out:
507out:
511 return error;
508 return (error);
512}
513
514int
515linker_file_add_dependency(linker_file_t file, linker_file_t dep)
516{
509}
510
511int
512linker_file_add_dependency(linker_file_t file, linker_file_t dep)
513{
517 linker_file_t* newdeps;
514 linker_file_t *newdeps;
518
515
519 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*),
520 M_LINKER, M_WAITOK | M_ZERO);
521 if (newdeps == NULL)
522 return ENOMEM;
516 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
517 M_LINKER, M_WAITOK | M_ZERO);
518 if (newdeps == NULL)
519 return (ENOMEM);
523
520
524 if (file->deps) {
525 bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*));
526 free(file->deps, M_LINKER);
527 }
528 file->deps = newdeps;
529 file->deps[file->ndeps] = dep;
530 file->ndeps++;
531
532 return 0;
521 if (file->deps) {
522 bcopy(file->deps, newdeps,
523 file->ndeps * sizeof(linker_file_t *));
524 free(file->deps, M_LINKER);
525 }
526 file->deps = newdeps;
527 file->deps[file->ndeps] = dep;
528 file->ndeps++;
529 return (0);
533}
534
535/*
530}
531
532/*
536 * Locate a linker set and its contents.
537 * This is a helper function to avoid linker_if.h exposure elsewhere.
538 * Note: firstp and lastp are really void ***
533 * Locate a linker set and its contents. This is a helper function to avoid
534 * linker_if.h exposure elsewhere. Note: firstp and lastp are really void ***
539 */
540int
541linker_file_lookup_set(linker_file_t file, const char *name,
535 */
536int
537linker_file_lookup_set(linker_file_t file, const char *name,
542 void *firstp, void *lastp, int *countp)
538 void *firstp, void *lastp, int *countp)
543{
544
539{
540
545 return LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
541 return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
546}
547
548caddr_t
542}
543
544caddr_t
549linker_file_lookup_symbol(linker_file_t file, const char* name, int deps)
545linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
550{
546{
551 c_linker_sym_t sym;
552 linker_symval_t symval;
553 caddr_t address;
554 size_t common_size = 0;
555 int i;
547 c_linker_sym_t sym;
548 linker_symval_t symval;
549 caddr_t address;
550 size_t common_size = 0;
551 int err, i;
556
552
557 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n",
558 file, name, deps));
553 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n",
554 file, name, deps));
559
555
560 if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
561 LINKER_SYMBOL_VALUES(file, sym, &symval);
562 if (symval.value == 0)
563 /*
564 * For commons, first look them up in the dependencies and
565 * only allocate space if not found there.
566 */
567 common_size = symval.size;
568 else {
569 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value));
570 return symval.value;
556 if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
557 LINKER_SYMBOL_VALUES(file, sym, &symval);
558 if (symval.value == 0)
559 /*
560 * For commons, first look them up in the
561 * dependencies and only allocate space if not found
562 * there.
563 */
564 common_size = symval.size;
565 else {
566 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
567 ".value=%x\n", symval.value));
568 return (symval.value);
569 }
571 }
570 }
572 }
573
574 if (deps) {
575 for (i = 0; i < file->ndeps; i++) {
576 address = linker_file_lookup_symbol(file->deps[i], name, 0);
577 if (address) {
578 KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address));
579 return address;
580 }
571 if (deps) {
572 for (i = 0; i < file->ndeps; i++) {
573 address = linker_file_lookup_symbol(file->deps[i],
574 name, 0);
575 if (address) {
576 KLD_DPF(SYM, ("linker_file_lookup_symbol:"
577 " deps value=%x\n", address));
578 return (address);
579 }
580 }
581 }
581 }
582 }
582 if (common_size > 0) {
583 /*
584 * This is a common symbol which was not found in the
585 * dependencies. We maintain a simple common symbol table in
586 * the file object.
587 */
588 struct common_symbol *cp;
583
589
584 if (common_size > 0) {
585 /*
586 * This is a common symbol which was not found in the
587 * dependencies. We maintain a simple common symbol table in
588 * the file object.
589 */
590 struct common_symbol* cp;
590 STAILQ_FOREACH(cp, &file->common, link) {
591 err = strcmp(cp->name, name);
592 if (err == 0) {
593 KLD_DPF(SYM, ("linker_file_lookup_symbol:"
594 " old common value=%x\n", cp->address));
595 return (cp->address);
596 }
597 }
598 /*
599 * Round the symbol size up to align.
600 */
601 common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
602 cp = malloc(sizeof(struct common_symbol)
603 + common_size + strlen(name) + 1, M_LINKER,
604 M_WAITOK | M_ZERO);
605 if (cp == NULL) {
606 KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
607 return (0);
608 }
609 cp->address = (caddr_t)(cp + 1);
610 cp->name = cp->address + common_size;
611 strcpy(cp->name, name);
612 bzero(cp->address, common_size);
613 STAILQ_INSERT_TAIL(&file->common, cp, link);
591
614
592 STAILQ_FOREACH(cp, &file->common, link)
593 if (!strcmp(cp->name, name)) {
594 KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address));
595 return cp->address;
596 }
597
598 /*
599 * Round the symbol size up to align.
600 */
601 common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
602 cp = malloc(sizeof(struct common_symbol)
603 + common_size
604 + strlen(name) + 1,
605 M_LINKER, M_WAITOK | M_ZERO);
606 if (!cp) {
607 KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
608 return 0;
615 KLD_DPF(SYM, ("linker_file_lookup_symbol: new common"
616 " value=%x\n", cp->address));
617 return (cp->address);
609 }
618 }
610
611 cp->address = (caddr_t) (cp + 1);
612 cp->name = cp->address + common_size;
613 strcpy(cp->name, name);
614 bzero(cp->address, common_size);
615 STAILQ_INSERT_TAIL(&file->common, cp, link);
616
617 KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address));
618 return cp->address;
619 }
620
621 KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
622 return 0;
619 KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
620 return (0);
623}
624
625#ifdef DDB
626/*
621}
622
623#ifdef DDB
624/*
627 * DDB Helpers. DDB has to look across multiple files with their own
628 * symbol tables and string tables.
629 *
630 * Note that we do not obey list locking protocols here. We really don't
631 * need DDB to hang because somebody's got the lock held. We'll take the
632 * chance that the files list is inconsistant instead.
625 * DDB Helpers. DDB has to look across multiple files with their own symbol
626 * tables and string tables.
627 *
628 * Note that we do not obey list locking protocols here. We really don't need
629 * DDB to hang because somebody's got the lock held. We'll take the chance
630 * that the files list is inconsistant instead.
633 */
634
635int
636linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
637{
631 */
632
633int
634linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
635{
638 linker_file_t lf;
636 linker_file_t lf;
639
637
640 TAILQ_FOREACH(lf, &linker_files, link) {
641 if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
642 return 0;
643 }
644 return ENOENT;
638 TAILQ_FOREACH(lf, &linker_files, link) {
639 if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0)
640 return (0);
641 }
642 return (ENOENT);
645}
646
647int
648linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
649{
643}
644
645int
646linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
647{
650 linker_file_t lf;
651 u_long off = (uintptr_t)value;
652 u_long diff, bestdiff;
653 c_linker_sym_t best;
654 c_linker_sym_t es;
648 linker_file_t lf;
649 c_linker_sym_t best, es;
650 u_long diff, bestdiff, off;
655
651
656 best = 0;
657 bestdiff = off;
658 TAILQ_FOREACH(lf, &linker_files, link) {
659 if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
660 continue;
661 if (es != 0 && diff < bestdiff) {
662 best = es;
663 bestdiff = diff;
652 best = 0;
653 off = (uintptr_t)value;
654 bestdiff = off;
655 TAILQ_FOREACH(lf, &linker_files, link) {
656 if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0)
657 continue;
658 if (es != 0 && diff < bestdiff) {
659 best = es;
660 bestdiff = diff;
661 }
662 if (bestdiff == 0)
663 break;
664 }
664 }
665 if (bestdiff == 0)
666 break;
667 }
668 if (best) {
669 *sym = best;
670 *diffp = bestdiff;
671 return 0;
672 } else {
673 *sym = 0;
674 *diffp = off;
675 return ENOENT;
676 }
665 if (best) {
666 *sym = best;
667 *diffp = bestdiff;
668 return (0);
669 } else {
670 *sym = 0;
671 *diffp = off;
672 return (ENOENT);
673 }
677}
678
679int
680linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
681{
674}
675
676int
677linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
678{
682 linker_file_t lf;
679 linker_file_t lf;
683
680
684 TAILQ_FOREACH(lf, &linker_files, link) {
685 if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
686 return 0;
687 }
688 return ENOENT;
681 TAILQ_FOREACH(lf, &linker_files, link) {
682 if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0)
683 return (0);
684 }
685 return (ENOENT);
689}
686}
690
691#endif
692
693/*
694 * Syscalls.
695 */
696/*
697 * MPSAFE
698 */
699int
687#endif
688
689/*
690 * Syscalls.
691 */
692/*
693 * MPSAFE
694 */
695int
700kldload(struct thread* td, struct kldload_args* uap)
696kldload(struct thread *td, struct kldload_args *uap)
701{
697{
702 char *kldname, *modname;
703 char *pathname = NULL;
704 linker_file_t lf;
705 int error = 0;
698 char *kldname, *modname;
699 char *pathname = NULL;
700 linker_file_t lf;
701 int error = 0;
706
702
707 td->td_retval[0] = -1;
703 td->td_retval[0] = -1;
708
704
709 if (securelevel > 0) /* redundant, but that's OK */
710 return EPERM;
705 if (securelevel > 0) /* redundant, but that's OK */
706 return (EPERM);
711
707
712 mtx_lock(&Giant);
708 mtx_lock(&Giant);
713
709
714 if ((error = suser_xxx(td->td_proc->p_ucred, NULL, 0)) != 0)
715 goto out;
710 if ((error = suser_xxx(td->td_proc->p_ucred, NULL, 0)) != 0)
711 goto out;
716
712
717 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
718 if ((error = copyinstr(SCARG(uap, file), pathname, MAXPATHLEN, NULL)) != 0)
719 goto out;
713 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
714 if ((error = copyinstr(SCARG(uap, file), pathname, MAXPATHLEN,
715 NULL)) != 0)
716 goto out;
720
717
721 /*
722 * If path do not contain qualified name or any dot in it (kldname.ko, or
723 * kldname.ver.ko) treat it as interface name.
724 */
725 if (index(pathname, '/') || index(pathname, '.')) {
726 kldname = pathname;
727 modname = NULL;
728 } else {
729 kldname = NULL;
730 modname = pathname;
731 }
732 error = linker_load_module(kldname, modname, NULL, NULL, &lf);
733 if (error)
734 goto out;
718 /*
719 * If path do not contain qualified name or any dot in it
720 * (kldname.ko, or kldname.ver.ko) treat it as interface
721 * name.
722 */
723 if (index(pathname, '/') || index(pathname, '.')) {
724 kldname = pathname;
725 modname = NULL;
726 } else {
727 kldname = NULL;
728 modname = pathname;
729 }
730 error = linker_load_module(kldname, modname, NULL, NULL, &lf);
731 if (error)
732 goto out;
735
733
736 lf->userrefs++;
737 td->td_retval[0] = lf->id;
738
734 lf->userrefs++;
735 td->td_retval[0] = lf->id;
739out:
736out:
740 if (pathname)
741 free(pathname, M_TEMP);
742 mtx_unlock(&Giant);
743 return (error);
737 if (pathname)
738 free(pathname, M_TEMP);
739 mtx_unlock(&Giant);
740 return (error);
744}
745
746/*
747 * MPSAFE
748 */
749int
741}
742
743/*
744 * MPSAFE
745 */
746int
750kldunload(struct thread* td, struct kldunload_args* uap)
747kldunload(struct thread *td, struct kldunload_args *uap)
751{
748{
752 linker_file_t lf;
753 int error = 0;
749 linker_file_t lf;
750 int error = 0;
754
751
755 if (securelevel > 0) /* redundant, but that's OK */
756 return EPERM;
752 if (securelevel > 0) /* redundant, but that's OK */
753 return (EPERM);
757
754
758 mtx_lock(&Giant);
755 mtx_lock(&Giant);
759
756
760 if ((error = suser_xxx(td->td_proc->p_ucred, NULL, 0)) != 0)
761 goto out;
757 if ((error = suser_xxx(td->td_proc->p_ucred, NULL, 0)) != 0)
758 goto out;
762
759
763 lf = linker_find_file_by_id(SCARG(uap, fileid));
764 if (lf) {
765 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
766 if (lf->userrefs == 0) {
767 printf("kldunload: attempt to unload file that was loaded by the kernel\n");
768 error = EBUSY;
769 goto out;
770 }
771 lf->userrefs--;
772 error = linker_file_unload(lf);
773 if (error)
774 lf->userrefs++;
775 } else {
776 error = ENOENT;
777 }
760 lf = linker_find_file_by_id(SCARG(uap, fileid));
761 if (lf) {
762 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
763 if (lf->userrefs == 0) {
764 printf("kldunload: attempt to unload file that was"
765 " loaded by the kernel\n");
766 error = EBUSY;
767 goto out;
768 }
769 lf->userrefs--;
770 error = linker_file_unload(lf);
771 if (error)
772 lf->userrefs++;
773 } else
774 error = ENOENT;
778out:
775out:
779 mtx_unlock(&Giant);
780 return (error);
776 mtx_unlock(&Giant);
777 return (error);
781}
782
783/*
784 * MPSAFE
785 */
786int
778}
779
780/*
781 * MPSAFE
782 */
783int
787kldfind(struct thread* td, struct kldfind_args* uap)
784kldfind(struct thread *td, struct kldfind_args *uap)
788{
785{
789 char* pathname;
790 const char *filename;
791 linker_file_t lf;
792 int error = 0;
786 char *pathname;
787 const char *filename;
788 linker_file_t lf;
789 int error = 0;
793
790
794 mtx_lock(&Giant);
795 td->td_retval[0] = -1;
791 mtx_lock(&Giant);
792 td->td_retval[0] = -1;
796
793
797 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
798 if ((error = copyinstr(SCARG(uap, file), pathname, MAXPATHLEN, NULL)) != 0)
799 goto out;
794 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
795 if ((error = copyinstr(SCARG(uap, file), pathname, MAXPATHLEN,
796 NULL)) != 0)
797 goto out;
800
798
801 filename = linker_basename(pathname);
802
803 lf = linker_find_file_by_name(filename);
804 if (lf)
805 td->td_retval[0] = lf->id;
806 else
807 error = ENOENT;
808
799 filename = linker_basename(pathname);
800 lf = linker_find_file_by_name(filename);
801 if (lf)
802 td->td_retval[0] = lf->id;
803 else
804 error = ENOENT;
809out:
805out:
810 if (pathname)
811 free(pathname, M_TEMP);
812 mtx_unlock(&Giant);
813 return (error);
806 if (pathname)
807 free(pathname, M_TEMP);
808 mtx_unlock(&Giant);
809 return (error);
814}
815
816/*
817 * MPSAFE
818 */
819int
810}
811
812/*
813 * MPSAFE
814 */
815int
820kldnext(struct thread* td, struct kldnext_args* uap)
816kldnext(struct thread *td, struct kldnext_args *uap)
821{
817{
822 linker_file_t lf;
823 int error = 0;
818 linker_file_t lf;
819 int error = 0;
824
820
825 mtx_lock(&Giant);
821 mtx_lock(&Giant);
826
822
827 if (SCARG(uap, fileid) == 0) {
828 if (TAILQ_FIRST(&linker_files))
829 td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
830 else
831 td->td_retval[0] = 0;
832 goto out;
833 }
834
835 lf = linker_find_file_by_id(SCARG(uap, fileid));
836 if (lf) {
837 if (TAILQ_NEXT(lf, link))
838 td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
839 else
840 td->td_retval[0] = 0;
841 } else {
842 error = ENOENT;
843 }
823 if (SCARG(uap, fileid) == 0) {
824 if (TAILQ_FIRST(&linker_files))
825 td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
826 else
827 td->td_retval[0] = 0;
828 goto out;
829 }
830 lf = linker_find_file_by_id(SCARG(uap, fileid));
831 if (lf) {
832 if (TAILQ_NEXT(lf, link))
833 td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
834 else
835 td->td_retval[0] = 0;
836 } else
837 error = ENOENT;
844out:
838out:
845 mtx_unlock(&Giant);
846 return (error);
839 mtx_unlock(&Giant);
840 return (error);
847}
848
849/*
850 * MPSAFE
851 */
852int
841}
842
843/*
844 * MPSAFE
845 */
846int
853kldstat(struct thread* td, struct kldstat_args* uap)
847kldstat(struct thread *td, struct kldstat_args *uap)
854{
848{
855 linker_file_t lf;
856 int error = 0;
857 int version;
858 struct kld_file_stat* stat;
859 int namelen;
849 linker_file_t lf;
850 int error = 0;
851 int namelen, version;
852 struct kld_file_stat *stat;
860
853
861 mtx_lock(&Giant);
854 mtx_lock(&Giant);
862
855
863 lf = linker_find_file_by_id(SCARG(uap, fileid));
864 if (!lf) {
865 error = ENOENT;
866 goto out;
867 }
856 lf = linker_find_file_by_id(SCARG(uap, fileid));
857 if (lf == NULL) {
858 error = ENOENT;
859 goto out;
860 }
861 stat = SCARG(uap, stat);
868
862
869 stat = SCARG(uap, stat);
863 /*
864 * Check the version of the user's structure.
865 */
866 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
867 goto out;
868 if (version != sizeof(struct kld_file_stat)) {
869 error = EINVAL;
870 goto out;
871 }
872 namelen = strlen(lf->filename) + 1;
873 if (namelen > MAXPATHLEN)
874 namelen = MAXPATHLEN;
875 if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0)
876 goto out;
877 if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0)
878 goto out;
879 if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0)
880 goto out;
881 if ((error = copyout(&lf->address, &stat->address,
882 sizeof(caddr_t))) != 0)
883 goto out;
884 if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0)
885 goto out;
870
886
871 /*
872 * Check the version of the user's structure.
873 */
874 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
875 goto out;
876 if (version != sizeof(struct kld_file_stat)) {
877 error = EINVAL;
878 goto out;
879 }
880
881 namelen = strlen(lf->filename) + 1;
882 if (namelen > MAXPATHLEN)
883 namelen = MAXPATHLEN;
884 if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0)
885 goto out;
886 if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0)
887 goto out;
888 if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0)
889 goto out;
890 if ((error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) != 0)
891 goto out;
892 if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0)
893 goto out;
894
895 td->td_retval[0] = 0;
896
887 td->td_retval[0] = 0;
897out:
888out:
898 mtx_unlock(&Giant);
899 return (error);
889 mtx_unlock(&Giant);
890 return (error);
900}
901
902/*
903 * MPSAFE
904 */
905int
891}
892
893/*
894 * MPSAFE
895 */
896int
906kldfirstmod(struct thread* td, struct kldfirstmod_args* uap)
897kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
907{
898{
908 linker_file_t lf;
909 int error = 0;
899 linker_file_t lf;
900 module_t mp;
901 int error = 0;
910
902
911 mtx_lock(&Giant);
912 lf = linker_find_file_by_id(SCARG(uap, fileid));
913 if (lf) {
914 if (TAILQ_FIRST(&lf->modules))
915 td->td_retval[0] = module_getid(TAILQ_FIRST(&lf->modules));
916 else
917 td->td_retval[0] = 0;
918 } else {
919 error = ENOENT;
920 }
921 mtx_unlock(&Giant);
922 return (error);
903 mtx_lock(&Giant);
904 lf = linker_find_file_by_id(SCARG(uap, fileid));
905 if (lf) {
906 mp = TAILQ_FIRST(&lf->modules);
907 if (mp != NULL)
908 td->td_retval[0] = module_getid(mp);
909 else
910 td->td_retval[0] = 0;
911 } else
912 error = ENOENT;
913 mtx_unlock(&Giant);
914 return (error);
923}
924
925/*
926 * MPSAFE
927 */
928int
929kldsym(struct thread *td, struct kldsym_args *uap)
930{
915}
916
917/*
918 * MPSAFE
919 */
920int
921kldsym(struct thread *td, struct kldsym_args *uap)
922{
931 char *symstr = NULL;
932 c_linker_sym_t sym;
933 linker_symval_t symval;
934 linker_file_t lf;
935 struct kld_sym_lookup lookup;
936 int error = 0;
923 char *symstr = NULL;
924 c_linker_sym_t sym;
925 linker_symval_t symval;
926 linker_file_t lf;
927 struct kld_sym_lookup lookup;
928 int error = 0;
937
929
938 mtx_lock(&Giant);
930 mtx_lock(&Giant);
939
931
940 if ((error = copyin(SCARG(uap, data), &lookup, sizeof(lookup))) != 0)
941 goto out;
942 if (lookup.version != sizeof(lookup) || SCARG(uap, cmd) != KLDSYM_LOOKUP) {
943 error = EINVAL;
944 goto out;
945 }
932 if ((error = copyin(SCARG(uap, data), &lookup, sizeof(lookup))) != 0)
933 goto out;
934 if (lookup.version != sizeof(lookup) ||
935 SCARG(uap, cmd) != KLDSYM_LOOKUP) {
936 error = EINVAL;
937 goto out;
938 }
946
939
947 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
948 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
949 goto out;
950
951 if (SCARG(uap, fileid) != 0) {
952 lf = linker_find_file_by_id(SCARG(uap, fileid));
953 if (lf == NULL) {
954 error = ENOENT;
955 goto out;
940 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
941 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
942 goto out;
943 if (SCARG(uap, fileid) != 0) {
944 lf = linker_find_file_by_id(SCARG(uap, fileid));
945 if (lf == NULL) {
946 error = ENOENT;
947 goto out;
948 }
949 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
950 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
951 lookup.symvalue = (uintptr_t) symval.value;
952 lookup.symsize = symval.size;
953 error = copyout(&lookup, SCARG(uap, data),
954 sizeof(lookup));
955 } else
956 error = ENOENT;
957 } else {
958 TAILQ_FOREACH(lf, &linker_files, link) {
959 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
960 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
961 lookup.symvalue = (uintptr_t)symval.value;
962 lookup.symsize = symval.size;
963 error = copyout(&lookup, SCARG(uap, data),
964 sizeof(lookup));
965 break;
966 }
967 }
968 if (lf == NULL)
969 error = ENOENT;
956 }
970 }
957 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
958 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
959 lookup.symvalue = (uintptr_t)symval.value;
960 lookup.symsize = symval.size;
961 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup));
962 } else
963 error = ENOENT;
964 } else {
965 TAILQ_FOREACH(lf, &linker_files, link) {
966 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
967 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
968 lookup.symvalue = (uintptr_t)symval.value;
969 lookup.symsize = symval.size;
970 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup));
971 break;
972 }
973 }
974 if (!lf)
975 error = ENOENT;
976 }
977out:
971out:
978 if (symstr)
979 free(symstr, M_TEMP);
980 mtx_unlock(&Giant);
981 return (error);
972 if (symstr)
973 free(symstr, M_TEMP);
974 mtx_unlock(&Giant);
975 return (error);
982}
983
984/*
985 * Preloaded module support
986 */
987
988static modlist_t
989modlist_lookup(const char *name, int ver)
990{
976}
977
978/*
979 * Preloaded module support
980 */
981
982static modlist_t
983modlist_lookup(const char *name, int ver)
984{
991 modlist_t mod;
985 modlist_t mod;
986 int err;
992
987
993 TAILQ_FOREACH(mod, &found_modules, link) {
994 if (strcmp(mod->name, name) == 0 && (ver == 0 || mod->version == ver))
995 return mod;
996 }
997 return NULL;
988 TAILQ_FOREACH(mod, &found_modules, link) {
989 err = strcmp(mod->name, name);
990 if (err == 0 && (ver == 0 || mod->version == ver))
991 return (mod);
992 }
993 return (NULL);
998}
999
1000static modlist_t
1001modlist_lookup2(const char *name, struct mod_depend *verinfo)
1002{
994}
995
996static modlist_t
997modlist_lookup2(const char *name, struct mod_depend *verinfo)
998{
1003 modlist_t mod, bestmod;
1004 int ver;
999 modlist_t mod, bestmod;
1000 int err, ver;
1005
1001
1006 if (verinfo == NULL)
1007 return modlist_lookup(name, 0);
1008 bestmod = NULL;
1009 for (mod = TAILQ_FIRST(&found_modules); mod; mod = TAILQ_NEXT(mod, link)) {
1010 if (strcmp(mod->name, name) != 0)
1011 continue;
1012 ver = mod->version;
1013 if (ver == verinfo->md_ver_preferred)
1014 return mod;
1015 if (ver >= verinfo->md_ver_minimum &&
1016 ver <= verinfo->md_ver_maximum &&
1017 ver > bestmod->version)
1018 bestmod = mod;
1019 }
1020 return bestmod;
1002 if (verinfo == NULL)
1003 return (modlist_lookup(name, 0));
1004 bestmod = NULL;
1005 for (mod = TAILQ_FIRST(&found_modules); mod;
1006 mod = TAILQ_NEXT(mod, link)) {
1007 err = strcmp(mod->name, name);
1008 if (err != 0)
1009 continue;
1010 ver = mod->version;
1011 if (ver == verinfo->md_ver_preferred)
1012 return (mod);
1013 if (ver >= verinfo->md_ver_minimum &&
1014 ver <= verinfo->md_ver_maximum &&
1015 ver > bestmod->version)
1016 bestmod = mod;
1017 }
1018 return (bestmod);
1021}
1022
1023static modlist_t
1024modlist_newmodule(const char *modname, int version, linker_file_t container)
1025{
1019}
1020
1021static modlist_t
1022modlist_newmodule(const char *modname, int version, linker_file_t container)
1023{
1026 modlist_t mod;
1024 modlist_t mod;
1027
1025
1028 mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT);
1029 if (mod == NULL)
1030 panic("no memory for module list");
1031 bzero(mod, sizeof(*mod));
1032 mod->container = container;
1033 mod->name = modname;
1034 mod->version = version;
1035 TAILQ_INSERT_TAIL(&found_modules, mod, link);
1036 return mod;
1026 mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT);
1027 if (mod == NULL)
1028 panic("no memory for module list");
1029 bzero(mod, sizeof(*mod));
1030 mod->container = container;
1031 mod->name = modname;
1032 mod->version = version;
1033 TAILQ_INSERT_TAIL(&found_modules, mod, link);
1034 return (mod);
1037}
1038
1039/*
1040 * This routine is cheap and nasty but will work for data pointers.
1041 */
1042static void *
1043linker_reloc_ptr(linker_file_t lf, const void *offset)
1044{
1035}
1036
1037/*
1038 * This routine is cheap and nasty but will work for data pointers.
1039 */
1040static void *
1041linker_reloc_ptr(linker_file_t lf, const void *offset)
1042{
1045 return lf->address + (uintptr_t)offset;
1043 return (lf->address + (uintptr_t)offset);
1046}
1047
1048/*
1049 * Dereference MDT_VERSION metadata into module name and version
1050 */
1051static void
1052linker_mdt_version(linker_file_t lf, struct mod_metadata *mp,
1044}
1045
1046/*
1047 * Dereference MDT_VERSION metadata into module name and version
1048 */
1049static void
1050linker_mdt_version(linker_file_t lf, struct mod_metadata *mp,
1053 const char **modname, int *version)
1051 const char **modname, int *version)
1054{
1052{
1055 struct mod_version *mvp;
1053 struct mod_version *mvp;
1056
1054
1057 if (modname)
1058 *modname = linker_reloc_ptr(lf, mp->md_cval);
1059 if (version) {
1060 mvp = linker_reloc_ptr(lf, mp->md_data);
1061 *version = mvp->mv_version;
1062 }
1055 if (modname)
1056 *modname = linker_reloc_ptr(lf, mp->md_cval);
1057 if (version) {
1058 mvp = linker_reloc_ptr(lf, mp->md_data);
1059 *version = mvp->mv_version;
1060 }
1063}
1064
1065/*
1066 * Dereference MDT_DEPEND metadata into module name and mod_depend structure
1067 */
1068static void
1069linker_mdt_depend(linker_file_t lf, struct mod_metadata *mp,
1061}
1062
1063/*
1064 * Dereference MDT_DEPEND metadata into module name and mod_depend structure
1065 */
1066static void
1067linker_mdt_depend(linker_file_t lf, struct mod_metadata *mp,
1070 const char **modname, struct mod_depend **verinfo)
1068 const char **modname, struct mod_depend **verinfo)
1071{
1072
1069{
1070
1073 if (modname)
1074 *modname = linker_reloc_ptr(lf, mp->md_cval);
1075 if (verinfo)
1076 *verinfo = linker_reloc_ptr(lf, mp->md_data);
1071 if (modname)
1072 *modname = linker_reloc_ptr(lf, mp->md_cval);
1073 if (verinfo)
1074 *verinfo = linker_reloc_ptr(lf, mp->md_data);
1077}
1078
1079static void
1080linker_addmodules(linker_file_t lf, struct mod_metadata **start,
1075}
1076
1077static void
1078linker_addmodules(linker_file_t lf, struct mod_metadata **start,
1081 struct mod_metadata **stop, int preload)
1079 struct mod_metadata **stop, int preload)
1082{
1080{
1083 struct mod_metadata *mp, **mdp;
1084 const char *modname;
1085 int ver;
1081 struct mod_metadata *mp, **mdp;
1082 const char *modname;
1083 int ver;
1086
1084
1087 for (mdp = start; mdp < stop; mdp++) {
1088 if (preload)
1089 mp = *mdp;
1090 else
1091 mp = linker_reloc_ptr(lf, *mdp);
1092 if (mp->md_type != MDT_VERSION)
1093 continue;
1094 if (preload) {
1095 modname = mp->md_cval;
1096 ver = ((struct mod_version*)mp->md_data)->mv_version;
1097 } else
1098 linker_mdt_version(lf, mp, &modname, &ver);
1099 if (modlist_lookup(modname, ver) != NULL) {
1100 printf("module %s already present!\n", modname);
1101 /* XXX what can we do? this is a build error. :-( */
1102 continue;
1085 for (mdp = start; mdp < stop; mdp++) {
1086 if (preload)
1087 mp = *mdp;
1088 else
1089 mp = linker_reloc_ptr(lf, *mdp);
1090 if (mp->md_type != MDT_VERSION)
1091 continue;
1092 if (preload) {
1093 modname = mp->md_cval;
1094 ver = ((struct mod_version *)mp->md_data)->mv_version;
1095 } else
1096 linker_mdt_version(lf, mp, &modname, &ver);
1097 if (modlist_lookup(modname, ver) != NULL) {
1098 printf("module %s already present!\n", modname);
1099 /* XXX what can we do? this is a build error. :-( */
1100 continue;
1101 }
1102 modlist_newmodule(modname, ver, lf);
1103 }
1103 }
1104 modlist_newmodule(modname, ver, lf);
1105 }
1106}
1107
1108static void
1104}
1105
1106static void
1109linker_preload(void* arg)
1107linker_preload(void *arg)
1110{
1108{
1111 caddr_t modptr;
1112 const char *modname, *nmodname;
1113 char *modtype;
1114 linker_file_t lf;
1115 linker_class_t lc;
1116 int error;
1117 linker_file_list_t loaded_files;
1118 linker_file_list_t depended_files;
1119 struct mod_metadata *mp, *nmp;
1120 struct mod_metadata **start, **stop, **mdp, **nmdp;
1121 struct mod_depend *verinfo;
1122 int nver;
1123 int resolves;
1124 modlist_t mod;
1125 struct sysinit **si_start, **si_stop;
1109 caddr_t modptr;
1110 const char *modname, *nmodname;
1111 char *modtype;
1112 linker_file_t lf;
1113 linker_class_t lc;
1114 int error;
1115 linker_file_list_t loaded_files;
1116 linker_file_list_t depended_files;
1117 struct mod_metadata *mp, *nmp;
1118 struct mod_metadata **start, **stop, **mdp, **nmdp;
1119 struct mod_depend *verinfo;
1120 int nver;
1121 int resolves;
1122 modlist_t mod;
1123 struct sysinit **si_start, **si_stop;
1126
1124
1127 TAILQ_INIT(&loaded_files);
1128 TAILQ_INIT(&depended_files);
1129 TAILQ_INIT(&found_modules);
1130 error = 0;
1125 TAILQ_INIT(&loaded_files);
1126 TAILQ_INIT(&depended_files);
1127 TAILQ_INIT(&found_modules);
1128 error = 0;
1131
1129
1132 modptr = NULL;
1133 while ((modptr = preload_search_next_name(modptr)) != NULL) {
1134 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
1135 modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
1136 if (modname == NULL) {
1137 printf("Preloaded module at %p does not have a name!\n", modptr);
1138 continue;
1139 }
1140 if (modtype == NULL) {
1141 printf("Preloaded module at %p does not have a type!\n", modptr);
1142 continue;
1143 }
1144 printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr);
1145 lf = NULL;
1146 TAILQ_FOREACH(lc, &classes, link) {
1147 error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1148 if (error) {
1130 modptr = NULL;
1131 while ((modptr = preload_search_next_name(modptr)) != NULL) {
1132 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
1133 modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
1134 if (modname == NULL) {
1135 printf("Preloaded module at %p does not have a"
1136 " name!\n", modptr);
1137 continue;
1138 }
1139 if (modtype == NULL) {
1140 printf("Preloaded module at %p does not have a type!\n",
1141 modptr);
1142 continue;
1143 }
1144 printf("Preloaded %s \"%s\" at %p.\n", modtype, modname,
1145 modptr);
1149 lf = NULL;
1146 lf = NULL;
1150 break;
1151 }
1147 TAILQ_FOREACH(lc, &classes, link) {
1148 error = LINKER_LINK_PRELOAD(lc, modname, &lf);
1149 if (error) {
1150 lf = NULL;
1151 break;
1152 }
1153 }
1154 if (lf)
1155 TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
1152 }
1156 }
1153 if (lf)
1154 TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
1155 }
1156
1157
1157 /*
1158 * First get a list of stuff in the kernel.
1159 */
1160 if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start, &stop,
1161 NULL) == 0)
1162 linker_addmodules(linker_kernel_file, start, stop, 1);
1158 /*
1159 * First get a list of stuff in the kernel.
1160 */
1161 if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start,
1162 &stop, NULL) == 0)
1163 linker_addmodules(linker_kernel_file, start, stop, 1);
1163
1164
1164 /*
1165 * this is a once-off kinky bubble sort
1166 * resolve relocation dependency requirements
1167 */
1168restart:
1169 TAILQ_FOREACH(lf, &loaded_files, loaded) {
1170 error = linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, NULL);
1171 /*
1165 /*
1172 * First, look to see if we would successfully link with this stuff.
1166 * this is a once-off kinky bubble sort resolve relocation dependency
1167 * requirements
1173 */
1168 */
1174 resolves = 1; /* unless we know otherwise */
1175 if (!error) {
1176 for (mdp = start; mdp < stop; mdp++) {
1177 mp = linker_reloc_ptr(lf, *mdp);
1178 if (mp->md_type != MDT_DEPEND)
1179 continue;
1180 linker_mdt_depend(lf, mp, &modname, &verinfo);
1181 for (nmdp = start; nmdp < stop; nmdp++) {
1182 nmp = linker_reloc_ptr(lf, *nmdp);
1183 if (nmp->md_type != MDT_VERSION)
1184 continue;
1185 linker_mdt_version(lf, nmp, &nmodname, NULL);
1186 nmodname = linker_reloc_ptr(lf, nmp->md_cval);
1187 if (strcmp(modname, nmodname) == 0)
1188 break;
1169restart:
1170 TAILQ_FOREACH(lf, &loaded_files, loaded) {
1171 error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
1172 &stop, NULL);
1173 /*
1174 * First, look to see if we would successfully link with this
1175 * stuff.
1176 */
1177 resolves = 1; /* unless we know otherwise */
1178 if (!error) {
1179 for (mdp = start; mdp < stop; mdp++) {
1180 mp = linker_reloc_ptr(lf, *mdp);
1181 if (mp->md_type != MDT_DEPEND)
1182 continue;
1183 linker_mdt_depend(lf, mp, &modname, &verinfo);
1184 for (nmdp = start; nmdp < stop; nmdp++) {
1185 nmp = linker_reloc_ptr(lf, *nmdp);
1186 if (nmp->md_type != MDT_VERSION)
1187 continue;
1188 linker_mdt_version(lf, nmp, &nmodname,
1189 NULL);
1190 nmodname = linker_reloc_ptr(lf,
1191 nmp->md_cval);
1192 error = strcmp(modname, nmodname);
1193 if (error == 0)
1194 break;
1195 }
1196 if (nmdp < stop) /* it's a self reference */
1197 continue;
1198
1199 /*
1200 * ok, the module isn't here yet, we
1201 * are not finished
1202 */
1203 if (modlist_lookup2(modname, verinfo) == NULL)
1204 resolves = 0;
1205 }
1189 }
1206 }
1190 if (nmdp < stop) /* it's a self reference */
1191 continue;
1192 if (modlist_lookup2(modname, verinfo) == NULL) {
1193 /* ok, the module isn't here yet, we are not finished */
1194 resolves = 0;
1207 /*
1208 * OK, if we found our modules, we can link. So, "provide"
1209 * the modules inside and add it to the end of the link order
1210 * list.
1211 */
1212 if (resolves) {
1213 if (!error) {
1214 for (mdp = start; mdp < stop; mdp++) {
1215 mp = linker_reloc_ptr(lf, *mdp);
1216 if (mp->md_type != MDT_VERSION)
1217 continue;
1218 linker_mdt_version(lf, mp,
1219 &modname, &nver);
1220 if (modlist_lookup(modname,
1221 nver) != NULL) {
1222 printf("module %s already"
1223 " present!\n", modname);
1224 linker_file_unload(lf);
1225 TAILQ_REMOVE(&loaded_files,
1226 lf, loaded);
1227 /* we changed tailq next ptr */
1228 goto restart;
1229 }
1230 modlist_newmodule(modname, nver, lf);
1231 }
1232 }
1233 TAILQ_REMOVE(&loaded_files, lf, loaded);
1234 TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
1235 /*
1236 * Since we provided modules, we need to restart the
1237 * sort so that the previous files that depend on us
1238 * have a chance. Also, we've busted the tailq next
1239 * pointer with the REMOVE.
1240 */
1241 goto restart;
1195 }
1242 }
1196 }
1197 }
1243 }
1244
1198 /*
1245 /*
1199 * OK, if we found our modules, we can link. So, "provide" the
1200 * modules inside and add it to the end of the link order list.
1246 * At this point, we check to see what could not be resolved..
1201 */
1247 */
1202 if (resolves) {
1203 if (!error) {
1204 for (mdp = start; mdp < stop; mdp++) {
1205 mp = linker_reloc_ptr(lf, *mdp);
1206 if (mp->md_type != MDT_VERSION)
1207 continue;
1208 linker_mdt_version(lf, mp, &modname, &nver);
1209 if (modlist_lookup(modname, nver) != NULL) {
1210 printf("module %s already present!\n", modname);
1211 linker_file_unload(lf);
1212 TAILQ_REMOVE(&loaded_files, lf, loaded);
1213 goto restart; /* we changed the tailq next ptr */
1214 }
1215 modlist_newmodule(modname, nver, lf);
1216 }
1217 }
1218 TAILQ_REMOVE(&loaded_files, lf, loaded);
1219 TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
1220 /*
1221 * Since we provided modules, we need to restart the sort so
1222 * that the previous files that depend on us have a chance.
1223 * Also, we've busted the tailq next pointer with the REMOVE.
1224 */
1225 goto restart;
1248 TAILQ_FOREACH(lf, &loaded_files, loaded) {
1249 printf("KLD file %s is missing dependencies\n", lf->filename);
1250 linker_file_unload(lf);
1251 TAILQ_REMOVE(&loaded_files, lf, loaded);
1226 }
1252 }
1227 }
1228
1253
1229 /*
1230 * At this point, we check to see what could not be resolved..
1231 */
1232 TAILQ_FOREACH(lf, &loaded_files, loaded) {
1233 printf("KLD file %s is missing dependencies\n", lf->filename);
1234 linker_file_unload(lf);
1235 TAILQ_REMOVE(&loaded_files, lf, loaded);
1236 }
1237
1238 /*
1239 * We made it. Finish off the linking in the order we determined.
1240 */
1241 TAILQ_FOREACH(lf, &depended_files, loaded) {
1242 if (linker_kernel_file) {
1243 linker_kernel_file->refs++;
1244 error = linker_file_add_dependency(lf, linker_kernel_file);
1245 if (error)
1246 panic("cannot add dependency");
1247 }
1248 lf->userrefs++; /* so we can (try to) kldunload it */
1249 error = linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, NULL);
1250 if (!error) {
1251 for (mdp = start; mdp < stop; mdp++) {
1252 mp = linker_reloc_ptr(lf, *mdp);
1253 if (mp->md_type != MDT_DEPEND)
1254 continue;
1255 linker_mdt_depend(lf, mp, &modname, &verinfo);
1256 mod = modlist_lookup2(modname, verinfo);
1257 mod->container->refs++;
1258 error = linker_file_add_dependency(lf, mod->container);
1259 if (error)
1260 panic("cannot add dependency");
1261 }
1262 }
1263
1264 /*
1254 /*
1265 * Now do relocation etc using the symbol search paths established by
1266 * the dependencies
1255 * We made it. Finish off the linking in the order we determined.
1267 */
1256 */
1268 error = LINKER_LINK_PRELOAD_FINISH(lf);
1269 if (error) {
1270 printf("KLD file %s - could not finalize loading\n", lf->filename);
1271 linker_file_unload(lf);
1272 continue;
1257 TAILQ_FOREACH(lf, &depended_files, loaded) {
1258 if (linker_kernel_file) {
1259 linker_kernel_file->refs++;
1260 error = linker_file_add_dependency(lf,
1261 linker_kernel_file);
1262 if (error)
1263 panic("cannot add dependency");
1264 }
1265 lf->userrefs++; /* so we can (try to) kldunload it */
1266 error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
1267 &stop, NULL);
1268 if (!error) {
1269 for (mdp = start; mdp < stop; mdp++) {
1270 mp = linker_reloc_ptr(lf, *mdp);
1271 if (mp->md_type != MDT_DEPEND)
1272 continue;
1273 linker_mdt_depend(lf, mp, &modname, &verinfo);
1274 mod = modlist_lookup2(modname, verinfo);
1275 mod->container->refs++;
1276 error = linker_file_add_dependency(lf,
1277 mod->container);
1278 if (error)
1279 panic("cannot add dependency");
1280 }
1281 }
1282 /*
1283 * Now do relocation etc using the symbol search paths
1284 * established by the dependencies
1285 */
1286 error = LINKER_LINK_PRELOAD_FINISH(lf);
1287 if (error) {
1288 printf("KLD file %s - could not finalize loading\n",
1289 lf->filename);
1290 linker_file_unload(lf);
1291 continue;
1292 }
1293 linker_file_register_modules(lf);
1294 if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
1295 &si_stop, NULL) == 0)
1296 sysinit_add(si_start, si_stop);
1297 linker_file_register_sysctls(lf);
1298 lf->flags |= LINKER_FILE_LINKED;
1273 }
1299 }
1274
1275 linker_file_register_modules(lf);
1276 if (linker_file_lookup_set(lf, "sysinit_set", &si_start, &si_stop, NULL) == 0)
1277 sysinit_add(si_start, si_stop);
1278 linker_file_register_sysctls(lf);
1279 lf->flags |= LINKER_FILE_LINKED;
1280 }
1281 /* woohoo! we made it! */
1300 /* woohoo! we made it! */
1282}
1283
1301}
1302
1284SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
1303SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0)
1285
1286/*
1287 * Search for a not-loaded module by name.
1304
1305/*
1306 * Search for a not-loaded module by name.
1288 *
1307 *
1289 * Modules may be found in the following locations:
1308 * Modules may be found in the following locations:
1290 *
1291 * - preloaded (result is just the module name)
1292 * - on disk (result is full path to module)
1293 *
1294 * If the module name is qualified in any way (contains path, etc.)
1295 * the we simply return a copy of it.
1296 *
1309 *
1310 * - preloaded (result is just the module name) - on disk (result is full path
1311 * to module)
1312 *
1313 * If the module name is qualified in any way (contains path, etc.) the we
1314 * simply return a copy of it.
1315 *
1297 * The search path can be manipulated via sysctl. Note that we use the ';'
1298 * character as a separator to be consistent with the bootloader.
1299 */
1300
1301static char linker_hintfile[] = "linker.hints";
1302static char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules;/modules";
1303
1304SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
1316 * The search path can be manipulated via sysctl. Note that we use the ';'
1317 * character as a separator to be consistent with the bootloader.
1318 */
1319
1320static char linker_hintfile[] = "linker.hints";
1321static char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules;/modules";
1322
1323SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
1305 sizeof(linker_path), "module load search path");
1324 sizeof(linker_path), "module load search path");
1306
1307TUNABLE_STR("module_path", linker_path, sizeof(linker_path));
1308
1309static char *linker_ext_list[] = {
1310 "",
1311 ".ko",
1312 NULL
1313};
1314
1315/*
1325
1326TUNABLE_STR("module_path", linker_path, sizeof(linker_path));
1327
1328static char *linker_ext_list[] = {
1329 "",
1330 ".ko",
1331 NULL
1332};
1333
1334/*
1316 * Check if file actually exists either with or without extension listed
1317 * in the linker_ext_list.
1318 * (probably should be generic for the rest of the kernel)
1335 * Check if file actually exists either with or without extension listed in
1336 * the linker_ext_list. (probably should be generic for the rest of the
1337 * kernel)
1319 */
1320static char *
1338 */
1339static char *
1321linker_lookup_file(const char *path, int pathlen,
1322 const char *name, int namelen, struct vattr *vap)
1340linker_lookup_file(const char *path, int pathlen, const char *name,
1341 int namelen, struct vattr *vap)
1323{
1342{
1324 struct nameidata nd;
1325 struct thread *td = curthread; /* XXX */
1326 char *result, **cpp, *sep;
1327 int error, len, extlen, reclen, flags;
1328 enum vtype type;
1343 struct nameidata nd;
1344 struct thread *td = curthread; /* XXX */
1345 char *result, **cpp, *sep;
1346 int error, len, extlen, reclen, flags;
1347 enum vtype type;
1329
1348
1330 extlen = 0;
1331 for (cpp = linker_ext_list; *cpp; cpp++) {
1332 len = strlen(*cpp);
1333 if (len > extlen)
1334 extlen = len;
1335 }
1336 extlen++; /* trailing '\0' */
1337 sep = (path[pathlen - 1] != '/') ? "/" : "";
1349 extlen = 0;
1350 for (cpp = linker_ext_list; *cpp; cpp++) {
1351 len = strlen(*cpp);
1352 if (len > extlen)
1353 extlen = len;
1354 }
1355 extlen++; /* trailing '\0' */
1356 sep = (path[pathlen - 1] != '/') ? "/" : "";
1338
1357
1339 reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1340 result = malloc(reclen, M_LINKER, M_WAITOK);
1341 for (cpp = linker_ext_list; *cpp; cpp++) {
1342 snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
1343 namelen, name, *cpp);
1344 /*
1345 * Attempt to open the file, and return the path if we succeed
1346 * and it's a regular file.
1347 */
1348 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
1349 flags = FREAD;
1350 error = vn_open(&nd, &flags, 0);
1351 if (error == 0) {
1352 NDFREE(&nd, NDF_ONLY_PNBUF);
1353 type = nd.ni_vp->v_type;
1354 if (vap)
1355 VOP_GETATTR(nd.ni_vp, vap, td->td_proc->p_ucred, td);
1356 VOP_UNLOCK(nd.ni_vp, 0, td);
1357 vn_close(nd.ni_vp, FREAD, td->td_proc->p_ucred, td);
1358 if (type == VREG)
1359 return(result);
1358 reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1359 result = malloc(reclen, M_LINKER, M_WAITOK);
1360 for (cpp = linker_ext_list; *cpp; cpp++) {
1361 snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep,
1362 namelen, name, *cpp);
1363 /*
1364 * Attempt to open the file, and return the path if
1365 * we succeed and it's a regular file.
1366 */
1367 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
1368 flags = FREAD;
1369 error = vn_open(&nd, &flags, 0);
1370 if (error == 0) {
1371 NDFREE(&nd, NDF_ONLY_PNBUF);
1372 type = nd.ni_vp->v_type;
1373 if (vap)
1374 VOP_GETATTR(nd.ni_vp, vap,
1375 td->td_proc->p_ucred, td);
1376 VOP_UNLOCK(nd.ni_vp, 0, td);
1377 vn_close(nd.ni_vp, FREAD, td->td_proc->p_ucred, td);
1378 if (type == VREG)
1379 return (result);
1380 }
1360 }
1381 }
1361 }
1362 free(result, M_LINKER);
1363 return(NULL);
1382 free(result, M_LINKER);
1383 return (NULL);
1364}
1365
1384}
1385
1366#define INT_ALIGN(base, ptr) ptr = \
1386#define INT_ALIGN(base, ptr) ptr = \
1367 (base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
1368
1369/*
1387 (base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
1388
1389/*
1370 * Lookup KLD which contains requested module in the "linker.hints" file.
1371 * If version specification is available, then try to find the best KLD.
1390 * Lookup KLD which contains requested module in the "linker.hints" file. If
1391 * version specification is available, then try to find the best KLD.
1372 * Otherwise just find the latest one.
1392 * Otherwise just find the latest one.
1373 *
1393 *
1374 * XXX: Vnode locking here is hosed; lock should be held for calls to
1375 * VOP_GETATTR() and vn_rdwr().
1376 */
1377static char *
1394 * XXX: Vnode locking here is hosed; lock should be held for calls to
1395 * VOP_GETATTR() and vn_rdwr().
1396 */
1397static char *
1378linker_hints_lookup(const char *path, int pathlen,
1379 const char *modname, int modnamelen,
1380 struct mod_depend *verinfo)
1398linker_hints_lookup(const char *path, int pathlen, const char *modname,
1399 int modnamelen, struct mod_depend *verinfo)
1381{
1400{
1382 struct thread *td = curthread; /* XXX */
1383 struct ucred *cred = td ? td->td_proc->p_ucred : NULL;
1384 struct nameidata nd;
1385 struct vattr vattr, mattr;
1386 u_char *hints = NULL;
1387 u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
1388 int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1401 struct thread *td = curthread; /* XXX */
1402 struct ucred *cred = td ? td->td_proc->p_ucred : NULL;
1403 struct nameidata nd;
1404 struct vattr vattr, mattr;
1405 u_char *hints = NULL;
1406 u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
1407 int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
1389
1408
1390 result = NULL;
1391 bestver = found = 0;
1409 result = NULL;
1410 bestver = found = 0;
1392
1411
1393 sep = (path[pathlen - 1] != '/') ? "/" : "";
1394 reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
1395 strlen(sep) + 1;
1396 pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
1397 snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep, linker_hintfile);
1412 sep = (path[pathlen - 1] != '/') ? "/" : "";
1413 reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen +
1414 strlen(sep) + 1;
1415 pathbuf = malloc(reclen, M_LINKER, M_WAITOK);
1416 snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
1417 linker_hintfile);
1398
1418
1399 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
1400 flags = FREAD;
1401 error = vn_open(&nd, &flags, 0);
1402 if (error)
1403 goto bad;
1404 NDFREE(&nd, NDF_ONLY_PNBUF);
1405 VOP_UNLOCK(nd.ni_vp, 0, td);
1406 if (nd.ni_vp->v_type != VREG)
1407 goto bad;
1408 best = cp = NULL;
1409 error = VOP_GETATTR(nd.ni_vp, &vattr, cred, td);
1410 if (error)
1411 goto bad;
1412 /*
1413 * XXX: we need to limit this number to some reasonable value
1414 */
1415 if (vattr.va_size > 100 * 1024) {
1416 printf("hints file too large %ld\n", (long)vattr.va_size);
1417 goto bad;
1418 }
1419 hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
1420 if (hints == NULL)
1421 goto bad;
1422 error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1423 UIO_SYSSPACE, IO_NODELOCKED, cred, &reclen, td);
1424 if (error)
1425 goto bad;
1426 vn_close(nd.ni_vp, FREAD, cred, td);
1427 nd.ni_vp = NULL;
1428 if (reclen != 0) {
1429 printf("can't read %d\n", reclen);
1430 goto bad;
1431 }
1432 intp = (int*)hints;
1433 ival = *intp++;
1434 if (ival != LINKER_HINTS_VERSION) {
1435 printf("hints file version mismatch %d\n", ival);
1436 goto bad;
1437 }
1438 bufend = hints + vattr.va_size;
1439 recptr = (u_char*)intp;
1440 clen = blen = 0;
1441 while (recptr < bufend && !found) {
1442 intp = (int*)recptr;
1443 reclen = *intp++;
1419 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
1420 flags = FREAD;
1421 error = vn_open(&nd, &flags, 0);
1422 if (error)
1423 goto bad;
1424 NDFREE(&nd, NDF_ONLY_PNBUF);
1425 VOP_UNLOCK(nd.ni_vp, 0, td);
1426 if (nd.ni_vp->v_type != VREG)
1427 goto bad;
1428 best = cp = NULL;
1429 error = VOP_GETATTR(nd.ni_vp, &vattr, cred, td);
1430 if (error)
1431 goto bad;
1432 /*
1433 * XXX: we need to limit this number to some reasonable value
1434 */
1435 if (vattr.va_size > 100 * 1024) {
1436 printf("hints file too large %ld\n", (long)vattr.va_size);
1437 goto bad;
1438 }
1439 hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
1440 if (hints == NULL)
1441 goto bad;
1442 error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t) hints, vattr.va_size, 0,
1443 UIO_SYSSPACE, IO_NODELOCKED, cred, &reclen, td);
1444 if (error)
1445 goto bad;
1446 vn_close(nd.ni_vp, FREAD, cred, td);
1447 nd.ni_vp = NULL;
1448 if (reclen != 0) {
1449 printf("can't read %d\n", reclen);
1450 goto bad;
1451 }
1452 intp = (int *)hints;
1444 ival = *intp++;
1453 ival = *intp++;
1445 cp = (char*)intp;
1446 switch (ival) {
1447 case MDT_VERSION:
1448 clen = *cp++;
1449 if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
1450 break;
1451 cp += clen;
1452 INT_ALIGN(hints, cp);
1453 ival = *(int*)cp;
1454 cp += sizeof(int);
1455 clen = *cp++;
1456 if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
1457 found = 1;
1458 break;
1459 }
1460 if (ival >= verinfo->md_ver_minimum &&
1461 ival <= verinfo->md_ver_maximum &&
1462 ival > bestver) {
1463 bestver = ival;
1464 best = cp;
1465 blen = clen;
1466 }
1467 break;
1468 default:
1469 break;
1454 if (ival != LINKER_HINTS_VERSION) {
1455 printf("hints file version mismatch %d\n", ival);
1456 goto bad;
1470 }
1457 }
1471 recptr += reclen + sizeof(int);
1472 }
1473 /*
1474 * Finally check if KLD is in the place
1475 */
1476 if (found)
1477 result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
1478 else if (best)
1479 result = linker_lookup_file(path, pathlen, best, blen, &mattr);
1480 if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >)) {
1458 bufend = hints + vattr.va_size;
1459 recptr = (u_char *)intp;
1460 clen = blen = 0;
1461 while (recptr < bufend && !found) {
1462 intp = (int *)recptr;
1463 reclen = *intp++;
1464 ival = *intp++;
1465 cp = (char *)intp;
1466 switch (ival) {
1467 case MDT_VERSION:
1468 clen = *cp++;
1469 if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
1470 break;
1471 cp += clen;
1472 INT_ALIGN(hints, cp);
1473 ival = *(int *)cp;
1474 cp += sizeof(int);
1475 clen = *cp++;
1476 if (verinfo == NULL ||
1477 ival == verinfo->md_ver_preferred) {
1478 found = 1;
1479 break;
1480 }
1481 if (ival >= verinfo->md_ver_minimum &&
1482 ival <= verinfo->md_ver_maximum &&
1483 ival > bestver) {
1484 bestver = ival;
1485 best = cp;
1486 blen = clen;
1487 }
1488 break;
1489 default:
1490 break;
1491 }
1492 recptr += reclen + sizeof(int);
1493 }
1481 /*
1494 /*
1482 * KLD is newer than hints file. What we should do now ?
1495 * Finally check if KLD is in the place
1483 */
1496 */
1484 printf("warning: KLD '%s' is newer than the linker.hints file\n",
1485 result);
1486 }
1497 if (found)
1498 result = linker_lookup_file(path, pathlen, cp, clen, &mattr);
1499 else if (best)
1500 result = linker_lookup_file(path, pathlen, best, blen, &mattr);
1501
1502 /*
1503 * KLD is newer than hints file. What we should do now?
1504 */
1505 if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
1506 printf("warning: KLD '%s' is newer than the linker.hints"
1507 " file\n", result);
1487bad:
1508bad:
1488 if (hints)
1489 free(hints, M_TEMP);
1490 if (nd.ni_vp != NULL)
1491 vn_close(nd.ni_vp, FREAD, cred, td);
1492 /*
1493 * If nothing found or hints is absent - fallback to the old way
1494 * by using "kldname[.ko]" as module name.
1495 */
1496 if (!found && !bestver && result == NULL)
1497 result = linker_lookup_file(path, pathlen, modname, modnamelen, NULL);
1498 return result;
1509 if (hints)
1510 free(hints, M_TEMP);
1511 if (nd.ni_vp != NULL)
1512 vn_close(nd.ni_vp, FREAD, cred, td);
1513 /*
1514 * If nothing found or hints is absent - fallback to the old
1515 * way by using "kldname[.ko]" as module name.
1516 */
1517 if (!found && !bestver && result == NULL)
1518 result = linker_lookup_file(path, pathlen, modname,
1519 modnamelen, NULL);
1520 return (result);
1499}
1500
1501/*
1502 * Lookup KLD which contains requested module in the all directories.
1503 */
1504static char *
1505linker_search_module(const char *modname, int modnamelen,
1521}
1522
1523/*
1524 * Lookup KLD which contains requested module in the all directories.
1525 */
1526static char *
1527linker_search_module(const char *modname, int modnamelen,
1506 struct mod_depend *verinfo)
1528 struct mod_depend *verinfo)
1507{
1529{
1508 char *cp, *ep, *result;
1530 char *cp, *ep, *result;
1509
1531
1510 /*
1511 * traverse the linker path
1512 */
1513 for (cp = linker_path; *cp; cp = ep + 1) {
1514
1515 /* find the end of this component */
1516 for (ep = cp; (*ep != 0) && (*ep != ';'); ep++)
1517 ;
1518 result = linker_hints_lookup(cp, ep - cp, modname, modnamelen, verinfo);
1519 if (result != NULL)
1520 return(result);
1521 if (*ep == 0)
1522 break;
1523 }
1524 return (NULL);
1532 /*
1533 * traverse the linker path
1534 */
1535 for (cp = linker_path; *cp; cp = ep + 1) {
1536 /* find the end of this component */
1537 for (ep = cp; (*ep != 0) && (*ep != ';'); ep++);
1538 result = linker_hints_lookup(cp, ep - cp, modname,
1539 modnamelen, verinfo);
1540 if (result != NULL)
1541 return (result);
1542 if (*ep == 0)
1543 break;
1544 }
1545 return (NULL);
1525}
1526
1527/*
1528 * Search for module in all directories listed in the linker_path.
1529 */
1530static char *
1531linker_search_kld(const char *name)
1532{
1546}
1547
1548/*
1549 * Search for module in all directories listed in the linker_path.
1550 */
1551static char *
1552linker_search_kld(const char *name)
1553{
1533 char *cp, *ep, *result, **cpp;
1534 int extlen, len;
1554 char *cp, *ep, *result, **cpp;
1555 int extlen, len;
1535
1556
1536 /* qualified at all? */
1537 if (index(name, '/'))
1538 return(linker_strdup(name));
1557 /* qualified at all? */
1558 if (index(name, '/'))
1559 return (linker_strdup(name));
1539
1560
1540 extlen = 0;
1541 for (cpp = linker_ext_list; *cpp; cpp++) {
1542 len = strlen(*cpp);
1543 if (len > extlen)
1544 extlen = len;
1545 }
1546 extlen++; /* trailing '\0' */
1561 extlen = 0;
1562 for (cpp = linker_ext_list; *cpp; cpp++) {
1563 len = strlen(*cpp);
1564 if (len > extlen)
1565 extlen = len;
1566 }
1567 extlen++; /* trailing '\0' */
1547
1568
1548 /* traverse the linker path */
1549 len = strlen(name);
1550 for (ep = linker_path; *ep; ep++) {
1551 cp = ep;
1552 /* find the end of this component */
1553 for (; *ep != 0 && *ep != ';'; ep++)
1554 ;
1555 result = linker_lookup_file(cp, ep - cp, name, len, NULL);
1556 if (result != NULL)
1557 return(result);
1558 }
1559 return(NULL);
1569 /* traverse the linker path */
1570 len = strlen(name);
1571 for (ep = linker_path; *ep; ep++) {
1572 cp = ep;
1573 /* find the end of this component */
1574 for (; *ep != 0 && *ep != ';'; ep++);
1575 result = linker_lookup_file(cp, ep - cp, name, len, NULL);
1576 if (result != NULL)
1577 return (result);
1578 }
1579 return (NULL);
1560}
1561
1562static const char *
1580}
1581
1582static const char *
1563linker_basename(const char* path)
1583linker_basename(const char *path)
1564{
1584{
1565 const char *filename;
1585 const char *filename;
1566
1586
1567 filename = rindex(path, '/');
1568 if (filename == NULL)
1569 return path;
1570 if (filename[1])
1571 filename++;
1572 return filename;
1587 filename = rindex(path, '/');
1588 if (filename == NULL)
1589 return path;
1590 if (filename[1])
1591 filename++;
1592 return (filename);
1573}
1574
1575/*
1593}
1594
1595/*
1576 * Find a file which contains given module and load it,
1577 * if "parent" is not NULL, register a reference to it.
1596 * Find a file which contains given module and load it, if "parent" is not
1597 * NULL, register a reference to it.
1578 */
1579static int
1580linker_load_module(const char *kldname, const char *modname,
1598 */
1599static int
1600linker_load_module(const char *kldname, const char *modname,
1581 struct linker_file *parent, struct mod_depend *verinfo,
1582 struct linker_file **lfpp)
1601 struct linker_file *parent, struct mod_depend *verinfo,
1602 struct linker_file **lfpp)
1583{
1603{
1584 linker_file_t lfdep;
1585 const char *filename;
1586 char *pathname;
1587 int error;
1604 linker_file_t lfdep;
1605 const char *filename;
1606 char *pathname;
1607 int error;
1588
1608
1589 if (modname == NULL) {
1609 if (modname == NULL) {
1610 /*
1611 * We have to load KLD
1612 */
1613 KASSERT(verinfo == NULL,
1614 ("linker_load_module: verinfo is not NULL"));
1615 pathname = linker_search_kld(kldname);
1616 } else {
1617 if (modlist_lookup2(modname, verinfo) != NULL)
1618 return (EEXIST);
1619 if (kldname == NULL)
1620 /*
1621 * Need to find a KLD with required module
1622 */
1623 pathname = linker_search_module(modname,
1624 strlen(modname), verinfo);
1625 else
1626 pathname = linker_strdup(kldname);
1627 }
1628 if (pathname == NULL)
1629 return (ENOENT);
1630
1590 /*
1631 /*
1591 * We have to load KLD
1632 * Can't load more than one file with the same basename XXX:
1633 * Actually it should be possible to have multiple KLDs with
1634 * the same basename but different path because they can
1635 * provide different versions of the same modules.
1592 */
1636 */
1593 KASSERT(verinfo == NULL, ("linker_load_module: verinfo is not NULL"));
1594 pathname = linker_search_kld(kldname);
1595 } else {
1596 if (modlist_lookup2(modname, verinfo) != NULL)
1597 return (EEXIST);
1598 if (kldname == NULL) {
1599 /*
1600 * Need to find a KLD with required module
1601 */
1602 pathname = linker_search_module(modname, strlen(modname), verinfo);
1603 } else
1604 pathname = linker_strdup(kldname);
1605 }
1606 if (pathname == NULL)
1607 return (ENOENT);
1608
1609 /*
1610 * Can't load more than one file with the same basename
1611 * XXX: Actually it should be possible to have multiple KLDs
1612 * with the same basename but different path because they can provide
1613 * different versions of the same modules.
1614 */
1615 filename = linker_basename(pathname);
1616 if (linker_find_file_by_name(filename)) {
1617 error = EEXIST;
1618 goto out;
1619 }
1620
1621 do {
1622 error = linker_load_file(pathname, &lfdep);
1623 if (error)
1624 break;
1625 if (modname && verinfo && modlist_lookup2(modname, verinfo) == NULL) {
1626 linker_file_unload(lfdep);
1627 error = ENOENT;
1628 break;
1637 filename = linker_basename(pathname);
1638 if (linker_find_file_by_name(filename)) {
1639 error = EEXIST;
1640 goto out;
1629 }
1641 }
1630 if (parent) {
1631 error = linker_file_add_dependency(parent, lfdep);
1632 if (error)
1633 break;
1634 }
1635 if (lfpp)
1636 *lfpp = lfdep;
1637 } while(0);
1642 do {
1643 error = linker_load_file(pathname, &lfdep);
1644 if (error)
1645 break;
1646 if (modname && verinfo &&
1647 modlist_lookup2(modname, verinfo) == NULL) {
1648 linker_file_unload(lfdep);
1649 error = ENOENT;
1650 break;
1651 }
1652 if (parent) {
1653 error = linker_file_add_dependency(parent, lfdep);
1654 if (error)
1655 break;
1656 }
1657 if (lfpp)
1658 *lfpp = lfdep;
1659 } while (0);
1638out:
1660out:
1639 if (pathname)
1640 free(pathname, M_LINKER);
1641 return error;
1661 if (pathname)
1662 free(pathname, M_LINKER);
1663 return (error);
1642}
1643
1644/*
1664}
1665
1666/*
1645 * This routine is responsible for finding dependencies of userland
1646 * initiated kldload(2)'s of files.
1667 * This routine is responsible for finding dependencies of userland initiated
1668 * kldload(2)'s of files.
1647 */
1648int
1649linker_load_dependencies(linker_file_t lf)
1650{
1669 */
1670int
1671linker_load_dependencies(linker_file_t lf)
1672{
1651 linker_file_t lfdep;
1652 struct mod_metadata **start, **stop, **mdp, **nmdp;
1653 struct mod_metadata *mp, *nmp;
1654 struct mod_depend *verinfo;
1655 modlist_t mod;
1656 const char *modname, *nmodname;
1657 int ver, error = 0, count;
1673 linker_file_t lfdep;
1674 struct mod_metadata **start, **stop, **mdp, **nmdp;
1675 struct mod_metadata *mp, *nmp;
1676 struct mod_depend *verinfo;
1677 modlist_t mod;
1678 const char *modname, *nmodname;
1679 int ver, error = 0, count;
1658
1680
1659 /*
1660 * All files are dependant on /kernel.
1661 */
1662 if (linker_kernel_file) {
1663 linker_kernel_file->refs++;
1664 error = linker_file_add_dependency(lf, linker_kernel_file);
1665 if (error)
1666 return error;
1667 }
1668
1669 if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, &count) != 0)
1670 return 0;
1671 for (mdp = start; mdp < stop; mdp++) {
1672 mp = linker_reloc_ptr(lf, *mdp);
1673 if (mp->md_type != MDT_VERSION)
1674 continue;
1675 linker_mdt_version(lf, mp, &modname, &ver);
1676 mod = modlist_lookup(modname, ver);
1677 if (mod != NULL) {
1678 printf("interface %s.%d already present in the KLD '%s'!\n",
1679 modname, ver, mod->container->filename);
1680 return EEXIST;
1681 /*
1682 * All files are dependant on /kernel.
1683 */
1684 if (linker_kernel_file) {
1685 linker_kernel_file->refs++;
1686 error = linker_file_add_dependency(lf, linker_kernel_file);
1687 if (error)
1688 return (error);
1681 }
1689 }
1682 }
1690 if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
1691 &count) != 0)
1692 return (0);
1693 for (mdp = start; mdp < stop; mdp++) {
1694 mp = linker_reloc_ptr(lf, *mdp);
1695 if (mp->md_type != MDT_VERSION)
1696 continue;
1697 linker_mdt_version(lf, mp, &modname, &ver);
1698 mod = modlist_lookup(modname, ver);
1699 if (mod != NULL) {
1700 printf("interface %s.%d already present in the KLD"
1701 " '%s'!\n", modname, ver,
1702 mod->container->filename);
1703 return (EEXIST);
1704 }
1705 }
1683
1706
1684 for (mdp = start; mdp < stop; mdp++) {
1685 mp = linker_reloc_ptr(lf, *mdp);
1686 if (mp->md_type != MDT_DEPEND)
1687 continue;
1688 linker_mdt_depend(lf, mp, &modname, &verinfo);
1689 nmodname = NULL;
1690 for (nmdp = start; nmdp < stop; nmdp++) {
1691 nmp = linker_reloc_ptr(lf, *nmdp);
1692 if (nmp->md_type != MDT_VERSION)
1693 continue;
1694 nmodname = linker_reloc_ptr(lf, nmp->md_cval);
1695 if (strcmp(modname, nmodname) == 0)
1696 break;
1707 for (mdp = start; mdp < stop; mdp++) {
1708 mp = linker_reloc_ptr(lf, *mdp);
1709 if (mp->md_type != MDT_DEPEND)
1710 continue;
1711 linker_mdt_depend(lf, mp, &modname, &verinfo);
1712 nmodname = NULL;
1713 for (nmdp = start; nmdp < stop; nmdp++) {
1714 nmp = linker_reloc_ptr(lf, *nmdp);
1715 if (nmp->md_type != MDT_VERSION)
1716 continue;
1717 nmodname = linker_reloc_ptr(lf, nmp->md_cval);
1718 error = strcmp(modname, nmodname);
1719 if (error == 0)
1720 break;
1721 }
1722 if (nmdp < stop)/* early exit, it's a self reference */
1723 continue;
1724 mod = modlist_lookup2(modname, verinfo);
1725 if (mod) { /* woohoo, it's loaded already */
1726 lfdep = mod->container;
1727 lfdep->refs++;
1728 error = linker_file_add_dependency(lf, lfdep);
1729 if (error)
1730 break;
1731 continue;
1732 }
1733 error = linker_load_module(NULL, modname, lf, verinfo, NULL);
1734 if (error) {
1735 printf("KLD %s: depends on %s - not available\n",
1736 lf->filename, modname);
1737 break;
1738 }
1697 }
1739 }
1698 if (nmdp < stop) /* early exit, it's a self reference */
1699 continue;
1700 mod = modlist_lookup2(modname, verinfo);
1701 if (mod) { /* woohoo, it's loaded already */
1702 lfdep = mod->container;
1703 lfdep->refs++;
1704 error = linker_file_add_dependency(lf, lfdep);
1705 if (error)
1706 break;
1707 continue;
1708 }
1709 error = linker_load_module(NULL, modname, lf, verinfo, NULL);
1710 if (error) {
1711 printf("KLD %s: depends on %s - not available\n",
1712 lf->filename, modname);
1713 break;
1714 }
1715 }
1716
1740
1717 if (error)
1718 return error;
1719 linker_addmodules(lf, start, stop, 0);
1720 return error;
1741 if (error)
1742 return (error);
1743 linker_addmodules(lf, start, stop, 0);
1744 return (error);
1721}
1722
1723static int
1724sysctl_kern_function_list_iterate(const char *name, void *opaque)
1725{
1726 struct sysctl_req *req;
1727
1728 req = opaque;

--- 15 unchanged lines hidden (view full) ---

1744 sysctl_kern_function_list_iterate, req);
1745 if (error)
1746 return (error);
1747 }
1748 return (SYSCTL_OUT(req, "", 1));
1749}
1750
1751SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
1745}
1746
1747static int
1748sysctl_kern_function_list_iterate(const char *name, void *opaque)
1749{
1750 struct sysctl_req *req;
1751
1752 req = opaque;

--- 15 unchanged lines hidden (view full) ---

1768 sysctl_kern_function_list_iterate, req);
1769 if (error)
1770 return (error);
1771 }
1772 return (SYSCTL_OUT(req, "", 1));
1773}
1774
1775SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
1752 NULL, 0, sysctl_kern_function_list, "", "kernel function list");
1776 NULL, 0, sysctl_kern_function_list, "", "kernel function list");