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"); |