Deleted Added
full compact
kern_linker.c (159843) kern_linker.c (159845)
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

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

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
27#include <sys/cdefs.h>
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

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

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
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/kern/kern_linker.c 159843 2006-06-21 20:15:36Z jhb $");
28__FBSDID("$FreeBSD: head/sys/kern/kern_linker.c 159845 2006-06-21 20:42:08Z jhb $");
29
30#include "opt_ddb.h"
31#include "opt_hwpmc_hooks.h"
32#include "opt_mac.h"
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>

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

57#ifdef HWPMC_HOOKS
58#include <sys/pmckern.h>
59#endif
60
61#ifdef KLD_DEBUG
62int kld_debug = 0;
63#endif
64
29
30#include "opt_ddb.h"
31#include "opt_hwpmc_hooks.h"
32#include "opt_mac.h"
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>

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

57#ifdef HWPMC_HOOKS
58#include <sys/pmckern.h>
59#endif
60
61#ifdef KLD_DEBUG
62int kld_debug = 0;
63#endif
64
65#define KLD_LOCK() do { sx_xlock(&kld_sx); mtx_lock(&Giant); } while (0)
66#define KLD_UNLOCK() do { mtx_unlock(&Giant); sx_xunlock(&kld_sx); } while (0)
67#define KLD_LOCKED() sx_xlocked(&kld_sx)
68#define KLD_LOCK_ASSERT() do { if (!cold) sx_assert(&kld_sx, SX_XLOCKED); } while (0)
69
65/*
66 * static char *linker_search_path(const char *name, struct mod_depend
67 * *verinfo);
68 */
69static const char *linker_basename(const char *path);
70
71/*
72 * Find a currently loaded file given its filename.

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

80
81/* Metadata from the static kernel */
82SET_DECLARE(modmetadata_set, struct mod_metadata);
83
84MALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
85
86linker_file_t linker_kernel_file;
87
70/*
71 * static char *linker_search_path(const char *name, struct mod_depend
72 * *verinfo);
73 */
74static const char *linker_basename(const char *path);
75
76/*
77 * Find a currently loaded file given its filename.

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

85
86/* Metadata from the static kernel */
87SET_DECLARE(modmetadata_set, struct mod_metadata);
88
89MALLOC_DEFINE(M_LINKER, "linker", "kernel linker");
90
91linker_file_t linker_kernel_file;
92
88static struct mtx kld_mtx; /* kernel linker mutex */
93static struct sx kld_sx; /* kernel linker lock */
89
90static linker_class_list_t classes;
91static linker_file_list_t linker_files;
92static int next_file_id = 1;
93static int linker_no_more_classes = 0;
94
95#define LINKER_GET_NEXT_FILE_ID(a) do { \
96 linker_file_t lftmp; \
97 \
94
95static linker_class_list_t classes;
96static linker_file_list_t linker_files;
97static int next_file_id = 1;
98static int linker_no_more_classes = 0;
99
100#define LINKER_GET_NEXT_FILE_ID(a) do { \
101 linker_file_t lftmp; \
102 \
103 KLD_LOCK_ASSERT(); \
98retry: \
104retry: \
99 mtx_lock(&kld_mtx); \
100 TAILQ_FOREACH(lftmp, &linker_files, link) { \
101 if (next_file_id == lftmp->id) { \
102 next_file_id++; \
105 TAILQ_FOREACH(lftmp, &linker_files, link) { \
106 if (next_file_id == lftmp->id) { \
107 next_file_id++; \
103 mtx_unlock(&kld_mtx); \
104 goto retry; \
105 } \
106 } \
107 (a) = next_file_id; \
108 goto retry; \
109 } \
110 } \
111 (a) = next_file_id; \
108 mtx_unlock(&kld_mtx); /* Hold for safe read of id variable */ \
109} while(0)
110
111
112/* XXX wrong name; we're looking at version provision tags here, not modules */
113typedef TAILQ_HEAD(, modlist) modlisthead_t;
114struct modlist {
115 TAILQ_ENTRY(modlist) link; /* chain together all modules */
116 linker_file_t container;
117 const char *name;
118 int version;
119};
120typedef struct modlist *modlist_t;
121static modlisthead_t found_modules;
122
123static int linker_file_add_dependency(linker_file_t file,
124 linker_file_t dep);
112} while(0)
113
114
115/* XXX wrong name; we're looking at version provision tags here, not modules */
116typedef TAILQ_HEAD(, modlist) modlisthead_t;
117struct modlist {
118 TAILQ_ENTRY(modlist) link; /* chain together all modules */
119 linker_file_t container;
120 const char *name;
121 int version;
122};
123typedef struct modlist *modlist_t;
124static modlisthead_t found_modules;
125
126static int linker_file_add_dependency(linker_file_t file,
127 linker_file_t dep);
128static caddr_t linker_file_lookup_symbol_internal(linker_file_t file,
129 const char* name, int deps);
125static int linker_load_module(const char *kldname,
126 const char *modname, struct linker_file *parent,
127 struct mod_depend *verinfo, struct linker_file **lfpp);
128static modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
129
130static char *
131linker_strdup(const char *str)
132{
133 char *result;
134
135 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
136 strcpy(result, str);
137 return (result);
138}
139
140static void
141linker_init(void *arg)
142{
143
130static int linker_load_module(const char *kldname,
131 const char *modname, struct linker_file *parent,
132 struct mod_depend *verinfo, struct linker_file **lfpp);
133static modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
134
135static char *
136linker_strdup(const char *str)
137{
138 char *result;
139
140 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
141 strcpy(result, str);
142 return (result);
143}
144
145static void
146linker_init(void *arg)
147{
148
144 mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
149 sx_init(&kld_sx, "kernel linker");
145 TAILQ_INIT(&classes);
146 TAILQ_INIT(&linker_files);
147}
148
149SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
150
151static void
152linker_stop_class_add(void *arg)

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

267
268 KLD_DPF(FILE,
269 ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
270 lf->filename));
271
272 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
273 return;
274
150 TAILQ_INIT(&classes);
151 TAILQ_INIT(&linker_files);
152}
153
154SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0)
155
156static void
157linker_stop_class_add(void *arg)

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

272
273 KLD_DPF(FILE,
274 ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
275 lf->filename));
276
277 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
278 return;
279
280 mtx_lock(&Giant);
275 for (oidp = start; oidp < stop; oidp++)
276 sysctl_register_oid(*oidp);
281 for (oidp = start; oidp < stop; oidp++)
282 sysctl_register_oid(*oidp);
283 mtx_unlock(&Giant);
277}
278
279static void
280linker_file_unregister_sysctls(linker_file_t lf)
281{
282 struct sysctl_oid **start, **stop, **oidp;
283
284 KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
285 " for %s\n", lf->filename));
286
287 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
288 return;
289
284}
285
286static void
287linker_file_unregister_sysctls(linker_file_t lf)
288{
289 struct sysctl_oid **start, **stop, **oidp;
290
291 KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs"
292 " for %s\n", lf->filename));
293
294 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
295 return;
296
297 mtx_lock(&Giant);
290 for (oidp = start; oidp < stop; oidp++)
291 sysctl_unregister_oid(*oidp);
298 for (oidp = start; oidp < stop; oidp++)
299 sysctl_unregister_oid(*oidp);
300 mtx_unlock(&Giant);
292}
293
294static int
295linker_file_register_modules(linker_file_t lf)
296{
297 struct mod_metadata **start, **stop, **mdp;
298 const moduledata_t *moddata;
299 int first_error, error;

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

347 linker_class_t lc;
348 linker_file_t lf;
349 int foundfile, error;
350
351 /* Refuse to load modules if securelevel raised */
352 if (securelevel > 0)
353 return (EPERM);
354
301}
302
303static int
304linker_file_register_modules(linker_file_t lf)
305{
306 struct mod_metadata **start, **stop, **mdp;
307 const moduledata_t *moddata;
308 int first_error, error;

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

356 linker_class_t lc;
357 linker_file_t lf;
358 int foundfile, error;
359
360 /* Refuse to load modules if securelevel raised */
361 if (securelevel > 0)
362 return (EPERM);
363
364 KLD_LOCK_ASSERT();
355 lf = linker_find_file_by_name(filename);
356 if (lf) {
357 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
358 " incrementing refs\n", filename));
359 *result = lf;
360 lf->refs++;
361 return (0);
362 }

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

413
414int
415linker_reference_module(const char *modname, struct mod_depend *verinfo,
416 linker_file_t *result)
417{
418 modlist_t mod;
419 int error;
420
365 lf = linker_find_file_by_name(filename);
366 if (lf) {
367 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
368 " incrementing refs\n", filename));
369 *result = lf;
370 lf->refs++;
371 return (0);
372 }

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

423
424int
425linker_reference_module(const char *modname, struct mod_depend *verinfo,
426 linker_file_t *result)
427{
428 modlist_t mod;
429 int error;
430
421 mtx_lock(&Giant);
431 KLD_LOCK();
422 if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
423 *result = mod->container;
424 (*result)->refs++;
432 if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
433 *result = mod->container;
434 (*result)->refs++;
425 mtx_unlock(&Giant);
435 KLD_UNLOCK();
426 return (0);
427 }
428
429 error = linker_load_module(NULL, modname, NULL, verinfo, result);
436 return (0);
437 }
438
439 error = linker_load_module(NULL, modname, NULL, verinfo, result);
430 mtx_unlock(&Giant);
440 KLD_UNLOCK();
431 return (error);
432}
433
434int
435linker_release_module(const char *modname, struct mod_depend *verinfo,
436 linker_file_t lf)
437{
438 modlist_t mod;
439 int error;
440
441 return (error);
442}
443
444int
445linker_release_module(const char *modname, struct mod_depend *verinfo,
446 linker_file_t lf)
447{
448 modlist_t mod;
449 int error;
450
441 mtx_lock(&Giant);
451 KLD_LOCK();
442 if (lf == NULL) {
443 KASSERT(modname != NULL,
444 ("linker_release_module: no file or name"));
445 mod = modlist_lookup2(modname, verinfo);
446 if (mod == NULL) {
452 if (lf == NULL) {
453 KASSERT(modname != NULL,
454 ("linker_release_module: no file or name"));
455 mod = modlist_lookup2(modname, verinfo);
456 if (mod == NULL) {
447 mtx_unlock(&Giant);
457 KLD_UNLOCK();
448 return (ESRCH);
449 }
450 lf = mod->container;
451 } else
452 KASSERT(modname == NULL && verinfo == NULL,
453 ("linker_release_module: both file and name"));
454 error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
458 return (ESRCH);
459 }
460 lf = mod->container;
461 } else
462 KASSERT(modname == NULL && verinfo == NULL,
463 ("linker_release_module: both file and name"));
464 error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
455 mtx_unlock(&Giant);
465 KLD_UNLOCK();
456 return (error);
457}
458
459static linker_file_t
460linker_find_file_by_name(const char *filename)
461{
462 linker_file_t lf;
463 char *koname;
464
465 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
466 sprintf(koname, "%s.ko", filename);
467
466 return (error);
467}
468
469static linker_file_t
470linker_find_file_by_name(const char *filename)
471{
472 linker_file_t lf;
473 char *koname;
474
475 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
476 sprintf(koname, "%s.ko", filename);
477
468 mtx_lock(&kld_mtx);
478 KLD_LOCK_ASSERT();
469 TAILQ_FOREACH(lf, &linker_files, link) {
470 if (strcmp(lf->filename, koname) == 0)
471 break;
472 if (strcmp(lf->filename, filename) == 0)
473 break;
474 }
479 TAILQ_FOREACH(lf, &linker_files, link) {
480 if (strcmp(lf->filename, koname) == 0)
481 break;
482 if (strcmp(lf->filename, filename) == 0)
483 break;
484 }
475 mtx_unlock(&kld_mtx);
476 free(koname, M_LINKER);
477 return (lf);
478}
479
480static linker_file_t
481linker_find_file_by_id(int fileid)
482{
483 linker_file_t lf;
485 free(koname, M_LINKER);
486 return (lf);
487}
488
489static linker_file_t
490linker_find_file_by_id(int fileid)
491{
492 linker_file_t lf;
484
485 mtx_lock(&kld_mtx);
493
494 KLD_LOCK_ASSERT();
486 TAILQ_FOREACH(lf, &linker_files, link)
487 if (lf->id == fileid)
488 break;
495 TAILQ_FOREACH(lf, &linker_files, link)
496 if (lf->id == fileid)
497 break;
489 mtx_unlock(&kld_mtx);
490 return (lf);
491}
492
493int
494linker_file_foreach(linker_predicate_t *predicate, void *context)
495{
496 linker_file_t lf;
497 int retval = 0;
498
498 return (lf);
499}
500
501int
502linker_file_foreach(linker_predicate_t *predicate, void *context)
503{
504 linker_file_t lf;
505 int retval = 0;
506
499 mtx_lock(&Giant);
507 KLD_LOCK();
500 TAILQ_FOREACH(lf, &linker_files, link) {
501 retval = predicate(lf, context);
502 if (retval != 0)
503 break;
504 }
508 TAILQ_FOREACH(lf, &linker_files, link) {
509 retval = predicate(lf, context);
510 if (retval != 0)
511 break;
512 }
505 mtx_unlock(&Giant);
513 KLD_UNLOCK();
506 return (retval);
507}
508
509linker_file_t
510linker_make_file(const char *pathname, linker_class_t lc)
511{
512 linker_file_t lf;
513 const char *filename;
514
514 return (retval);
515}
516
517linker_file_t
518linker_make_file(const char *pathname, linker_class_t lc)
519{
520 linker_file_t lf;
521 const char *filename;
522
523 KLD_LOCK_ASSERT();
515 filename = linker_basename(pathname);
516
517 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
518 lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
519 if (lf == NULL)
520 return (NULL);
521 lf->refs = 1;
522 lf->userrefs = 0;
523 lf->flags = 0;
524 lf->filename = linker_strdup(filename);
525 LINKER_GET_NEXT_FILE_ID(lf->id);
526 lf->ndeps = 0;
527 lf->deps = NULL;
528 STAILQ_INIT(&lf->common);
529 TAILQ_INIT(&lf->modules);
524 filename = linker_basename(pathname);
525
526 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
527 lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
528 if (lf == NULL)
529 return (NULL);
530 lf->refs = 1;
531 lf->userrefs = 0;
532 lf->flags = 0;
533 lf->filename = linker_strdup(filename);
534 LINKER_GET_NEXT_FILE_ID(lf->id);
535 lf->ndeps = 0;
536 lf->deps = NULL;
537 STAILQ_INIT(&lf->common);
538 TAILQ_INIT(&lf->modules);
530 mtx_lock(&kld_mtx);
531 TAILQ_INSERT_TAIL(&linker_files, lf, link);
539 TAILQ_INSERT_TAIL(&linker_files, lf, link);
532 mtx_unlock(&kld_mtx);
533 return (lf);
534}
535
536int
537linker_file_unload(linker_file_t file, int flags)
538{
539 module_t mod, next;
540 modlist_t ml, nextml;

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

545 if (securelevel > 0)
546 return (EPERM);
547#ifdef MAC
548 error = mac_check_kld_unload(curthread->td_ucred);
549 if (error)
550 return (error);
551#endif
552
540 return (lf);
541}
542
543int
544linker_file_unload(linker_file_t file, int flags)
545{
546 module_t mod, next;
547 modlist_t ml, nextml;

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

552 if (securelevel > 0)
553 return (EPERM);
554#ifdef MAC
555 error = mac_check_kld_unload(curthread->td_ucred);
556 if (error)
557 return (error);
558#endif
559
560 KLD_LOCK_ASSERT();
553 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
554
555 /* Easy case of just dropping a reference. */
556 if (file->refs > 1) {
557 file->refs--;
558 return (0);
559 }
560

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

592 /*
593 * Don't try to run SYSUNINITs if we are unloaded due to a
594 * link error.
595 */
596 if (file->flags & LINKER_FILE_LINKED) {
597 linker_file_sysuninit(file);
598 linker_file_unregister_sysctls(file);
599 }
561 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
562
563 /* Easy case of just dropping a reference. */
564 if (file->refs > 1) {
565 file->refs--;
566 return (0);
567 }
568

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

600 /*
601 * Don't try to run SYSUNINITs if we are unloaded due to a
602 * link error.
603 */
604 if (file->flags & LINKER_FILE_LINKED) {
605 linker_file_sysuninit(file);
606 linker_file_unregister_sysctls(file);
607 }
600 mtx_lock(&kld_mtx);
601 TAILQ_REMOVE(&linker_files, file, link);
608 TAILQ_REMOVE(&linker_files, file, link);
602 mtx_unlock(&kld_mtx);
603
604 if (file->deps) {
605 for (i = 0; i < file->ndeps; i++)
606 linker_file_unload(file->deps[i], flags);
607 free(file->deps, M_LINKER);
608 file->deps = NULL;
609 }
610 for (cp = STAILQ_FIRST(&file->common); cp;

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

622 return (0);
623}
624
625static int
626linker_file_add_dependency(linker_file_t file, linker_file_t dep)
627{
628 linker_file_t *newdeps;
629
609
610 if (file->deps) {
611 for (i = 0; i < file->ndeps; i++)
612 linker_file_unload(file->deps[i], flags);
613 free(file->deps, M_LINKER);
614 file->deps = NULL;
615 }
616 for (cp = STAILQ_FIRST(&file->common); cp;

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

628 return (0);
629}
630
631static int
632linker_file_add_dependency(linker_file_t file, linker_file_t dep)
633{
634 linker_file_t *newdeps;
635
636 KLD_LOCK_ASSERT();
630 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
631 M_LINKER, M_WAITOK | M_ZERO);
632 if (newdeps == NULL)
633 return (ENOMEM);
634
635 if (file->deps) {
636 bcopy(file->deps, newdeps,
637 file->ndeps * sizeof(linker_file_t *));

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

648 * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **.
649 * This function is used in this file so we can avoid having lots of (void **)
650 * casts.
651 */
652int
653linker_file_lookup_set(linker_file_t file, const char *name,
654 void *firstp, void *lastp, int *countp)
655{
637 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
638 M_LINKER, M_WAITOK | M_ZERO);
639 if (newdeps == NULL)
640 return (ENOMEM);
641
642 if (file->deps) {
643 bcopy(file->deps, newdeps,
644 file->ndeps * sizeof(linker_file_t *));

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

655 * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **.
656 * This function is used in this file so we can avoid having lots of (void **)
657 * casts.
658 */
659int
660linker_file_lookup_set(linker_file_t file, const char *name,
661 void *firstp, void *lastp, int *countp)
662{
663 int error, locked;
656
664
657 return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
665 locked = KLD_LOCKED();
666 if (!locked)
667 KLD_LOCK();
668 error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
669 if (!locked)
670 KLD_UNLOCK();
671 return (error);
658}
659
660caddr_t
661linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
662{
672}
673
674caddr_t
675linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
676{
677 caddr_t sym;
678 int locked;
679
680 locked = KLD_LOCKED();
681 if (!locked)
682 KLD_LOCK();
683 sym = linker_file_lookup_symbol_internal(file, name, deps);
684 if (!locked)
685 KLD_UNLOCK();
686 return (sym);
687}
688
689static caddr_t
690linker_file_lookup_symbol_internal(linker_file_t file, const char *name,
691 int deps)
692{
663 c_linker_sym_t sym;
664 linker_symval_t symval;
665 caddr_t address;
666 size_t common_size = 0;
667 int i;
668
693 c_linker_sym_t sym;
694 linker_symval_t symval;
695 caddr_t address;
696 size_t common_size = 0;
697 int i;
698
699 KLD_LOCK_ASSERT();
669 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
670 file, name, deps));
671
672 if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
673 LINKER_SYMBOL_VALUES(file, sym, &symval);
674 if (symval.value == 0)
675 /*
676 * For commons, first look them up in the

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

681 else {
682 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
683 ".value=%p\n", symval.value));
684 return (symval.value);
685 }
686 }
687 if (deps) {
688 for (i = 0; i < file->ndeps; i++) {
700 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
701 file, name, deps));
702
703 if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
704 LINKER_SYMBOL_VALUES(file, sym, &symval);
705 if (symval.value == 0)
706 /*
707 * For commons, first look them up in the

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

712 else {
713 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol"
714 ".value=%p\n", symval.value));
715 return (symval.value);
716 }
717 }
718 if (deps) {
719 for (i = 0; i < file->ndeps; i++) {
689 address = linker_file_lookup_symbol(file->deps[i],
690 name, 0);
720 address = linker_file_lookup_symbol_internal(
721 file->deps[i], name, 0);
691 if (address) {
692 KLD_DPF(SYM, ("linker_file_lookup_symbol:"
693 " deps value=%p\n", address));
694 return (address);
695 }
696 }
697 }
698 if (common_size > 0) {

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

827 if (index(file, '/') || index(file, '.')) {
828 kldname = file;
829 modname = NULL;
830 } else {
831 kldname = NULL;
832 modname = file;
833 }
834
722 if (address) {
723 KLD_DPF(SYM, ("linker_file_lookup_symbol:"
724 " deps value=%p\n", address));
725 return (address);
726 }
727 }
728 }
729 if (common_size > 0) {

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

858 if (index(file, '/') || index(file, '.')) {
859 kldname = file;
860 modname = NULL;
861 } else {
862 kldname = NULL;
863 modname = file;
864 }
865
835 mtx_lock(&Giant);
866 KLD_LOCK();
836 error = linker_load_module(kldname, modname, NULL, NULL, &lf);
837 if (error)
838 goto unlock;
839#ifdef HWPMC_HOOKS
840 pkm.pm_file = lf->filename;
841 pkm.pm_address = (uintptr_t) lf->address;
842 PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
843#endif
844 lf->userrefs++;
845 if (fileid != NULL)
846 *fileid = lf->id;
847unlock:
867 error = linker_load_module(kldname, modname, NULL, NULL, &lf);
868 if (error)
869 goto unlock;
870#ifdef HWPMC_HOOKS
871 pkm.pm_file = lf->filename;
872 pkm.pm_address = (uintptr_t) lf->address;
873 PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
874#endif
875 lf->userrefs++;
876 if (fileid != NULL)
877 *fileid = lf->id;
878unlock:
848 mtx_unlock(&Giant);
879 KLD_UNLOCK();
849 return (error);
850}
851
852int
853kldload(struct thread *td, struct kldload_args *uap)
854{
855 char *pathname = NULL;
856 int error, fileid;

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

881 int error = 0;
882
883 if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
884 return (error);
885
886 if ((error = suser(td)) != 0)
887 return (error);
888
880 return (error);
881}
882
883int
884kldload(struct thread *td, struct kldload_args *uap)
885{
886 char *pathname = NULL;
887 int error, fileid;

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

912 int error = 0;
913
914 if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
915 return (error);
916
917 if ((error = suser(td)) != 0)
918 return (error);
919
889 mtx_lock(&Giant);
920 KLD_LOCK();
890 lf = linker_find_file_by_id(fileid);
891 if (lf) {
892 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
893 if (lf->userrefs == 0) {
894 /*
895 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
896 */
897 printf("kldunload: attempt to unload file that was"

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

910 }
911 } else
912 error = ENOENT;
913
914#ifdef HWPMC_HOOKS
915 if (error == 0)
916 PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
917#endif
921 lf = linker_find_file_by_id(fileid);
922 if (lf) {
923 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
924 if (lf->userrefs == 0) {
925 /*
926 * XXX: maybe LINKER_UNLOAD_FORCE should override ?
927 */
928 printf("kldunload: attempt to unload file that was"

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

941 }
942 } else
943 error = ENOENT;
944
945#ifdef HWPMC_HOOKS
946 if (error == 0)
947 PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
948#endif
918 mtx_unlock(&Giant);
949 KLD_UNLOCK();
919 return (error);
920}
921
922/*
923 * MPSAFE
924 */
925int
926kldunload(struct thread *td, struct kldunload_args *uap)

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

961
962 td->td_retval[0] = -1;
963
964 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
965 if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
966 goto out;
967
968 filename = linker_basename(pathname);
950 return (error);
951}
952
953/*
954 * MPSAFE
955 */
956int
957kldunload(struct thread *td, struct kldunload_args *uap)

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

992
993 td->td_retval[0] = -1;
994
995 pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
996 if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
997 goto out;
998
999 filename = linker_basename(pathname);
969 mtx_lock(&Giant);
1000 KLD_LOCK();
970 lf = linker_find_file_by_name(filename);
971 if (lf)
972 td->td_retval[0] = lf->id;
973 else
974 error = ENOENT;
1001 lf = linker_find_file_by_name(filename);
1002 if (lf)
1003 td->td_retval[0] = lf->id;
1004 else
1005 error = ENOENT;
975 mtx_unlock(&Giant);
1006 KLD_UNLOCK();
976out:
977 free(pathname, M_TEMP);
978 return (error);
979}
980
981/*
982 * MPSAFE
983 */

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

988 int error = 0;
989
990#ifdef MAC
991 error = mac_check_kld_stat(td->td_ucred);
992 if (error)
993 return (error);
994#endif
995
1007out:
1008 free(pathname, M_TEMP);
1009 return (error);
1010}
1011
1012/*
1013 * MPSAFE
1014 */

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

1019 int error = 0;
1020
1021#ifdef MAC
1022 error = mac_check_kld_stat(td->td_ucred);
1023 if (error)
1024 return (error);
1025#endif
1026
996 mtx_lock(&Giant);
997
1027 KLD_LOCK();
998 if (uap->fileid == 0) {
1028 if (uap->fileid == 0) {
999 mtx_lock(&kld_mtx);
1000 if (TAILQ_FIRST(&linker_files))
1001 td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
1002 else
1003 td->td_retval[0] = 0;
1029 if (TAILQ_FIRST(&linker_files))
1030 td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
1031 else
1032 td->td_retval[0] = 0;
1004 mtx_unlock(&kld_mtx);
1005 goto out;
1006 }
1007 lf = linker_find_file_by_id(uap->fileid);
1008 if (lf) {
1009 if (TAILQ_NEXT(lf, link))
1010 td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
1011 else
1012 td->td_retval[0] = 0;
1013 } else
1014 error = ENOENT;
1015out:
1033 goto out;
1034 }
1035 lf = linker_find_file_by_id(uap->fileid);
1036 if (lf) {
1037 if (TAILQ_NEXT(lf, link))
1038 td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
1039 else
1040 td->td_retval[0] = 0;
1041 } else
1042 error = ENOENT;
1043out:
1016 mtx_unlock(&Giant);
1044 KLD_UNLOCK();
1017 return (error);
1018}
1019
1020/*
1021 * MPSAFE
1022 */
1023int
1024kldstat(struct thread *td, struct kldstat_args *uap)

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

1037 return (EINVAL);
1038
1039#ifdef MAC
1040 error = mac_check_kld_stat(td->td_ucred);
1041 if (error)
1042 return (error);
1043#endif
1044
1045 return (error);
1046}
1047
1048/*
1049 * MPSAFE
1050 */
1051int
1052kldstat(struct thread *td, struct kldstat_args *uap)

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

1065 return (EINVAL);
1066
1067#ifdef MAC
1068 error = mac_check_kld_stat(td->td_ucred);
1069 if (error)
1070 return (error);
1071#endif
1072
1045 mtx_lock(&Giant);
1046
1073 KLD_LOCK();
1047 lf = linker_find_file_by_id(uap->fileid);
1048 if (lf == NULL) {
1074 lf = linker_find_file_by_id(uap->fileid);
1075 if (lf == NULL) {
1049 mtx_unlock(&Giant);
1076 KLD_UNLOCK();
1050 return (ENOENT);
1051 }
1052
1053 namelen = strlen(lf->filename) + 1;
1054 if (namelen > MAXPATHLEN)
1055 namelen = MAXPATHLEN;
1056 bcopy(lf->filename, &stat.name[0], namelen);
1057 stat.refs = lf->refs;
1058 stat.id = lf->id;
1059 stat.address = lf->address;
1060 stat.size = lf->size;
1077 return (ENOENT);
1078 }
1079
1080 namelen = strlen(lf->filename) + 1;
1081 if (namelen > MAXPATHLEN)
1082 namelen = MAXPATHLEN;
1083 bcopy(lf->filename, &stat.name[0], namelen);
1084 stat.refs = lf->refs;
1085 stat.id = lf->id;
1086 stat.address = lf->address;
1087 stat.size = lf->size;
1061 mtx_unlock(&Giant);
1088 KLD_UNLOCK();
1062
1063 td->td_retval[0] = 0;
1064
1065 return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat)));
1066}
1067
1068/*
1069 * MPSAFE

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

1076 int error = 0;
1077
1078#ifdef MAC
1079 error = mac_check_kld_stat(td->td_ucred);
1080 if (error)
1081 return (error);
1082#endif
1083
1089
1090 td->td_retval[0] = 0;
1091
1092 return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat)));
1093}
1094
1095/*
1096 * MPSAFE

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

1103 int error = 0;
1104
1105#ifdef MAC
1106 error = mac_check_kld_stat(td->td_ucred);
1107 if (error)
1108 return (error);
1109#endif
1110
1084 mtx_lock(&Giant);
1111 KLD_LOCK();
1085 lf = linker_find_file_by_id(uap->fileid);
1086 if (lf) {
1087 MOD_SLOCK;
1088 mp = TAILQ_FIRST(&lf->modules);
1089 if (mp != NULL)
1090 td->td_retval[0] = module_getid(mp);
1091 else
1092 td->td_retval[0] = 0;
1093 MOD_SUNLOCK;
1094 } else
1095 error = ENOENT;
1112 lf = linker_find_file_by_id(uap->fileid);
1113 if (lf) {
1114 MOD_SLOCK;
1115 mp = TAILQ_FIRST(&lf->modules);
1116 if (mp != NULL)
1117 td->td_retval[0] = module_getid(mp);
1118 else
1119 td->td_retval[0] = 0;
1120 MOD_SUNLOCK;
1121 } else
1122 error = ENOENT;
1096 mtx_unlock(&Giant);
1123 KLD_UNLOCK();
1097 return (error);
1098}
1099
1100/*
1101 * MPSAFE
1102 */
1103int
1104kldsym(struct thread *td, struct kldsym_args *uap)

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

1119 if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1120 return (error);
1121 if (lookup.version != sizeof(lookup) ||
1122 uap->cmd != KLDSYM_LOOKUP)
1123 return (EINVAL);
1124 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1125 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
1126 goto out;
1124 return (error);
1125}
1126
1127/*
1128 * MPSAFE
1129 */
1130int
1131kldsym(struct thread *td, struct kldsym_args *uap)

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

1146 if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0)
1147 return (error);
1148 if (lookup.version != sizeof(lookup) ||
1149 uap->cmd != KLDSYM_LOOKUP)
1150 return (EINVAL);
1151 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1152 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
1153 goto out;
1127 mtx_lock(&Giant);
1154 KLD_LOCK();
1128 if (uap->fileid != 0) {
1129 lf = linker_find_file_by_id(uap->fileid);
1130 if (lf == NULL)
1131 error = ENOENT;
1132 else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
1133 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
1134 lookup.symvalue = (uintptr_t) symval.value;
1135 lookup.symsize = symval.size;
1136 error = copyout(&lookup, uap->data, sizeof(lookup));
1137 } else
1138 error = ENOENT;
1139 } else {
1155 if (uap->fileid != 0) {
1156 lf = linker_find_file_by_id(uap->fileid);
1157 if (lf == NULL)
1158 error = ENOENT;
1159 else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
1160 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
1161 lookup.symvalue = (uintptr_t) symval.value;
1162 lookup.symsize = symval.size;
1163 error = copyout(&lookup, uap->data, sizeof(lookup));
1164 } else
1165 error = ENOENT;
1166 } else {
1140 mtx_lock(&kld_mtx);
1141 TAILQ_FOREACH(lf, &linker_files, link) {
1142 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
1143 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
1144 lookup.symvalue = (uintptr_t)symval.value;
1145 lookup.symsize = symval.size;
1146 error = copyout(&lookup, uap->data,
1147 sizeof(lookup));
1148 break;
1149 }
1150 }
1167 TAILQ_FOREACH(lf, &linker_files, link) {
1168 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
1169 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
1170 lookup.symvalue = (uintptr_t)symval.value;
1171 lookup.symsize = symval.size;
1172 error = copyout(&lookup, uap->data,
1173 sizeof(lookup));
1174 break;
1175 }
1176 }
1151 mtx_unlock(&kld_mtx);
1152 if (lf == NULL)
1153 error = ENOENT;
1154 }
1177 if (lf == NULL)
1178 error = ENOENT;
1179 }
1155 mtx_unlock(&Giant);
1180 KLD_UNLOCK();
1156out:
1157 free(symstr, M_TEMP);
1158 return (error);
1159}
1160
1161/*
1162 * Preloaded module support
1163 */

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

1794 struct linker_file *parent, struct mod_depend *verinfo,
1795 struct linker_file **lfpp)
1796{
1797 linker_file_t lfdep;
1798 const char *filename;
1799 char *pathname;
1800 int error;
1801
1181out:
1182 free(symstr, M_TEMP);
1183 return (error);
1184}
1185
1186/*
1187 * Preloaded module support
1188 */

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

1819 struct linker_file *parent, struct mod_depend *verinfo,
1820 struct linker_file **lfpp)
1821{
1822 linker_file_t lfdep;
1823 const char *filename;
1824 char *pathname;
1825 int error;
1826
1827 KLD_LOCK_ASSERT();
1802 if (modname == NULL) {
1803 /*
1804 * We have to load KLD
1805 */
1806 KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
1807 " is not NULL"));
1808 pathname = linker_search_kld(kldname);
1809 } else {

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

1867 struct mod_depend *verinfo;
1868 modlist_t mod;
1869 const char *modname, *nmodname;
1870 int ver, error = 0, count;
1871
1872 /*
1873 * All files are dependant on /kernel.
1874 */
1828 if (modname == NULL) {
1829 /*
1830 * We have to load KLD
1831 */
1832 KASSERT(verinfo == NULL, ("linker_load_module: verinfo"
1833 " is not NULL"));
1834 pathname = linker_search_kld(kldname);
1835 } else {

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

1893 struct mod_depend *verinfo;
1894 modlist_t mod;
1895 const char *modname, *nmodname;
1896 int ver, error = 0, count;
1897
1898 /*
1899 * All files are dependant on /kernel.
1900 */
1901 KLD_LOCK_ASSERT();
1875 if (linker_kernel_file) {
1876 linker_kernel_file->refs++;
1877 error = linker_file_add_dependency(lf, linker_kernel_file);
1878 if (error)
1879 return (error);
1880 }
1881 if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
1882 &count) != 0)

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

1958#ifdef MAC
1959 error = mac_check_kld_stat(req->td->td_ucred);
1960 if (error)
1961 return (error);
1962#endif
1963 error = sysctl_wire_old_buffer(req, 0);
1964 if (error != 0)
1965 return (error);
1902 if (linker_kernel_file) {
1903 linker_kernel_file->refs++;
1904 error = linker_file_add_dependency(lf, linker_kernel_file);
1905 if (error)
1906 return (error);
1907 }
1908 if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop,
1909 &count) != 0)

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

1985#ifdef MAC
1986 error = mac_check_kld_stat(req->td->td_ucred);
1987 if (error)
1988 return (error);
1989#endif
1990 error = sysctl_wire_old_buffer(req, 0);
1991 if (error != 0)
1992 return (error);
1966 mtx_lock(&kld_mtx);
1993 KLD_LOCK();
1967 TAILQ_FOREACH(lf, &linker_files, link) {
1968 error = LINKER_EACH_FUNCTION_NAME(lf,
1969 sysctl_kern_function_list_iterate, req);
1970 if (error) {
1994 TAILQ_FOREACH(lf, &linker_files, link) {
1995 error = LINKER_EACH_FUNCTION_NAME(lf,
1996 sysctl_kern_function_list_iterate, req);
1997 if (error) {
1971 mtx_unlock(&kld_mtx);
1998 KLD_UNLOCK();
1972 return (error);
1973 }
1974 }
1999 return (error);
2000 }
2001 }
1975 mtx_unlock(&kld_mtx);
2002 KLD_UNLOCK();
1976 return (SYSCTL_OUT(req, "", 1));
1977}
1978
1979SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
1980 NULL, 0, sysctl_kern_function_list, "", "kernel function list");
2003 return (SYSCTL_OUT(req, "", 1));
2004}
2005
2006SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLFLAG_RD,
2007 NULL, 0, sysctl_kern_function_list, "", "kernel function list");