kern_linker.c revision 59603
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 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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 59603 2000-04-24 17:08:04Z dfr $ 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> 35#include <sys/sysproto.h> 36#include <sys/sysent.h> 37#include <sys/proc.h> 38#include <sys/lock.h> 39#include <sys/module.h> 40#include <sys/linker.h> 41#include <sys/fcntl.h> 42#include <sys/libkern.h> 43#include <sys/namei.h> 44#include <sys/vnode.h> 45#include <sys/sysctl.h> 46 47#include <vm/vm_zone.h> 48 49#include "linker_if.h" 50 51#ifdef KLD_DEBUG 52int kld_debug = 0; 53#endif 54 55MALLOC_DEFINE(M_LINKER, "kld", "kernel linker"); 56linker_file_t linker_current_file; 57linker_file_t linker_kernel_file; 58 59static struct lock lock; /* lock for the file list */ 60static linker_class_list_t classes; 61static linker_file_list_t linker_files; 62static int next_file_id = 1; 63 64static char * 65linker_strdup(const char *str) 66{ 67 char *result; 68 69 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL) 70 strcpy(result, str); 71 return(result); 72} 73 74static void 75linker_init(void* arg) 76{ 77 lockinit(&lock, PVM, "klink", 0, 0); 78 TAILQ_INIT(&classes); 79 TAILQ_INIT(&linker_files); 80} 81 82SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); 83 84int 85linker_add_class(linker_class_t lc) 86{ 87 kobj_class_compile((kobj_class_t) lc); 88 TAILQ_INSERT_HEAD(&classes, lc, link); 89 return 0; 90} 91 92static void 93linker_file_sysinit(linker_file_t lf) 94{ 95 struct linker_set* sysinits; 96 struct sysinit** sipp; 97 struct sysinit** xipp; 98 struct sysinit* save; 99 const moduledata_t *moddata; 100 int error; 101 102 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 103 lf->filename)); 104 105 sysinits = (struct linker_set*) 106 linker_file_lookup_symbol(lf, "sysinit_set", 0); 107 108 KLD_DPF(FILE, ("linker_file_sysinit: SYSINITs %p\n", sysinits)); 109 if (!sysinits) 110 return; 111 112 /* HACK ALERT! */ 113 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 114 if ((*sipp)->func == module_register_init) { 115 moddata = (*sipp)->udata; 116 error = module_register(moddata, lf); 117 if (error) 118 printf("linker_file_sysinit \"%s\" failed to register! %d\n", 119 lf->filename, error); 120 } 121 } 122 123 /* 124 * Perform a bubble sort of the system initialization objects by 125 * their subsystem (primary key) and order (secondary key). 126 * 127 * Since some things care about execution order, this is the 128 * operation which ensures continued function. 129 */ 130 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 131 for (xipp = sipp + 1; *xipp; xipp++) { 132 if ((*sipp)->subsystem <= (*xipp)->subsystem || 133 ((*sipp)->subsystem == (*xipp)->subsystem && 134 (*sipp)->order <= (*xipp)->order)) 135 continue; /* skip*/ 136 save = *sipp; 137 *sipp = *xipp; 138 *xipp = save; 139 } 140 } 141 142 143 /* 144 * Traverse the (now) ordered list of system initialization tasks. 145 * Perform each task, and continue on to the next task. 146 */ 147 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 148 if ((*sipp)->subsystem == SI_SUB_DUMMY) 149 continue; /* skip dummy task(s)*/ 150 151 /* Call function */ 152 (*((*sipp)->func))((*sipp)->udata); 153 } 154} 155 156static void 157linker_file_sysuninit(linker_file_t lf) 158{ 159 struct linker_set* sysuninits; 160 struct sysinit** sipp; 161 struct sysinit** xipp; 162 struct sysinit* save; 163 164 KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", 165 lf->filename)); 166 167 sysuninits = (struct linker_set*) 168 linker_file_lookup_symbol(lf, "sysuninit_set", 0); 169 170 KLD_DPF(FILE, ("linker_file_sysuninit: SYSUNINITs %p\n", sysuninits)); 171 if (!sysuninits) 172 return; 173 174 /* 175 * Perform a reverse bubble sort of the system initialization objects 176 * by their subsystem (primary key) and order (secondary key). 177 * 178 * Since some things care about execution order, this is the 179 * operation which ensures continued function. 180 */ 181 for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) { 182 for (xipp = sipp + 1; *xipp; xipp++) { 183 if ((*sipp)->subsystem >= (*xipp)->subsystem || 184 ((*sipp)->subsystem == (*xipp)->subsystem && 185 (*sipp)->order >= (*xipp)->order)) 186 continue; /* skip*/ 187 save = *sipp; 188 *sipp = *xipp; 189 *xipp = save; 190 } 191 } 192 193 194 /* 195 * Traverse the (now) ordered list of system initialization tasks. 196 * Perform each task, and continue on to the next task. 197 */ 198 for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) { 199 if ((*sipp)->subsystem == SI_SUB_DUMMY) 200 continue; /* skip dummy task(s)*/ 201 202 /* Call function */ 203 (*((*sipp)->func))((*sipp)->udata); 204 } 205} 206 207static void 208linker_file_register_sysctls(linker_file_t lf) 209{ 210 struct linker_set* sysctls; 211 212 KLD_DPF(FILE, ("linker_file_register_sysctls: registering SYSCTLs for %s\n", 213 lf->filename)); 214 215 sysctls = (struct linker_set*) 216 linker_file_lookup_symbol(lf, "sysctl_set", 0); 217 218 KLD_DPF(FILE, ("linker_file_register_sysctls: SYSCTLs %p\n", sysctls)); 219 if (!sysctls) 220 return; 221 222 sysctl_register_set(sysctls); 223} 224 225static void 226linker_file_unregister_sysctls(linker_file_t lf) 227{ 228 struct linker_set* sysctls; 229 230 KLD_DPF(FILE, ("linker_file_unregister_sysctls: registering SYSCTLs for %s\n", 231 lf->filename)); 232 233 sysctls = (struct linker_set*) 234 linker_file_lookup_symbol(lf, "sysctl_set", 0); 235 236 KLD_DPF(FILE, ("linker_file_unregister_sysctls: SYSCTLs %p\n", sysctls)); 237 if (!sysctls) 238 return; 239 240 sysctl_unregister_set(sysctls); 241} 242 243int 244linker_load_file(const char* filename, linker_file_t* result) 245{ 246 linker_class_t lc; 247 linker_file_t lf; 248 int foundfile, error = 0; 249 char *koname = NULL; 250 251 lf = linker_find_file_by_name(filename); 252 if (lf) { 253 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename)); 254 *result = lf; 255 lf->refs++; 256 goto out; 257 } 258 259 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 260 if (koname == NULL) { 261 error = ENOMEM; 262 goto out; 263 } 264 sprintf(koname, "%s.ko", filename); 265 lf = NULL; 266 foundfile = 0; 267 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 268 KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n", 269 filename, lc->desc)); 270 271 error = LINKER_LOAD_FILE(lc, koname, &lf); /* First with .ko */ 272 if (lf == NULL && error == ENOENT) 273 error = LINKER_LOAD_FILE(lc, filename, &lf); /* Then try without */ 274 /* 275 * If we got something other than ENOENT, then it exists but we cannot 276 * load it for some other reason. 277 */ 278 if (error != ENOENT) 279 foundfile = 1; 280 if (lf) { 281 linker_file_register_sysctls(lf); 282 linker_file_sysinit(lf); 283 284 *result = lf; 285 error = 0; 286 goto out; 287 } 288 } 289 /* 290 * Less than ideal, but tells the user whether it failed to load or 291 * the module was not found. 292 */ 293 if (foundfile) 294 error = ENOEXEC; /* Format not recognised (or unloadable) */ 295 else 296 error = ENOENT; /* Nothing found */ 297 298out: 299 if (koname) 300 free(koname, M_LINKER); 301 return error; 302} 303 304linker_file_t 305linker_find_file_by_name(const char* filename) 306{ 307 linker_file_t lf = 0; 308 char *koname; 309 310 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 311 if (koname == NULL) 312 goto out; 313 sprintf(koname, "%s.ko", filename); 314 315 lockmgr(&lock, LK_SHARED, 0, curproc); 316 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 317 if (!strcmp(lf->filename, koname)) 318 break; 319 if (!strcmp(lf->filename, filename)) 320 break; 321 } 322 lockmgr(&lock, LK_RELEASE, 0, curproc); 323 324out: 325 if (koname) 326 free(koname, M_LINKER); 327 return lf; 328} 329 330linker_file_t 331linker_find_file_by_id(int fileid) 332{ 333 linker_file_t lf = 0; 334 335 lockmgr(&lock, LK_SHARED, 0, curproc); 336 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) 337 if (lf->id == fileid) 338 break; 339 lockmgr(&lock, LK_RELEASE, 0, curproc); 340 341 return lf; 342} 343 344linker_file_t 345linker_make_file(const char* pathname, linker_class_t lc) 346{ 347 linker_file_t lf = 0; 348 const char *filename; 349 350 filename = rindex(pathname, '/'); 351 if (filename && filename[1]) 352 filename++; 353 else 354 filename = pathname; 355 356 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename)); 357 lockmgr(&lock, LK_EXCLUSIVE, 0, curproc); 358 lf = (linker_file_t) kobj_create((kobj_class_t) lc, M_LINKER, M_WAITOK); 359 if (!lf) 360 goto out; 361 362 lf->refs = 1; 363 lf->userrefs = 0; 364 lf->flags = 0; 365 lf->filename = linker_strdup(filename); 366 lf->id = next_file_id++; 367 lf->ndeps = 0; 368 lf->deps = NULL; 369 STAILQ_INIT(&lf->common); 370 TAILQ_INIT(&lf->modules); 371 372 TAILQ_INSERT_TAIL(&linker_files, lf, link); 373 374out: 375 lockmgr(&lock, LK_RELEASE, 0, curproc); 376 return lf; 377} 378 379int 380linker_file_unload(linker_file_t file) 381{ 382 module_t mod, next; 383 struct common_symbol* cp; 384 int error = 0; 385 int i; 386 387 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); 388 lockmgr(&lock, LK_EXCLUSIVE, 0, curproc); 389 if (file->refs == 1) { 390 KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n")); 391 /* 392 * Inform any modules associated with this file. 393 */ 394 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 395 next = module_getfnext(mod); 396 397 /* 398 * Give the module a chance to veto the unload. 399 */ 400 if ((error = module_unload(mod)) != 0) { 401 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n", 402 mod)); 403 lockmgr(&lock, LK_RELEASE, 0, curproc); 404 goto out; 405 } 406 407 module_release(mod); 408 } 409 } 410 411 file->refs--; 412 if (file->refs > 0) { 413 lockmgr(&lock, LK_RELEASE, 0, curproc); 414 goto out; 415 } 416 417 /* Don't try to run SYSUNINITs if we are unloaded due to a link error */ 418 if (file->flags & LINKER_FILE_LINKED) { 419 linker_file_sysuninit(file); 420 linker_file_unregister_sysctls(file); 421 } 422 423 TAILQ_REMOVE(&linker_files, file, link); 424 lockmgr(&lock, LK_RELEASE, 0, curproc); 425 426 for (i = 0; i < file->ndeps; i++) 427 linker_file_unload(file->deps[i]); 428 free(file->deps, M_LINKER); 429 430 for (cp = STAILQ_FIRST(&file->common); cp; 431 cp = STAILQ_FIRST(&file->common)) { 432 STAILQ_REMOVE(&file->common, cp, common_symbol, link); 433 free(cp, M_LINKER); 434 } 435 436 LINKER_UNLOAD(file); 437 free(file->filename, M_LINKER); 438 kobj_delete((kobj_t) file, M_LINKER); 439 440out: 441 return error; 442} 443 444int 445linker_file_add_dependancy(linker_file_t file, linker_file_t dep) 446{ 447 linker_file_t* newdeps; 448 449 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*), 450 M_LINKER, M_WAITOK); 451 if (newdeps == NULL) 452 return ENOMEM; 453 bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*)); 454 455 if (file->deps) { 456 bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*)); 457 free(file->deps, M_LINKER); 458 } 459 file->deps = newdeps; 460 file->deps[file->ndeps] = dep; 461 file->ndeps++; 462 463 return 0; 464} 465 466caddr_t 467linker_file_lookup_symbol(linker_file_t file, const char* name, int deps) 468{ 469 c_linker_sym_t sym; 470 linker_symval_t symval; 471 linker_file_t lf; 472 caddr_t address; 473 size_t common_size = 0; 474 int i; 475 476 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n", 477 file, name, deps)); 478 479 if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) { 480 LINKER_SYMBOL_VALUES(file, sym, &symval); 481 if (symval.value == 0) 482 /* 483 * For commons, first look them up in the dependancies and 484 * only allocate space if not found there. 485 */ 486 common_size = symval.size; 487 else { 488 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value)); 489 return symval.value; 490 } 491 } 492 493 if (deps) { 494 for (i = 0; i < file->ndeps; i++) { 495 address = linker_file_lookup_symbol(file->deps[i], name, 0); 496 if (address) { 497 KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address)); 498 return address; 499 } 500 } 501 502 /* If we have not found it in the dependencies, search globally */ 503 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 504 /* But skip the current file if it's on the list */ 505 if (lf == file) 506 continue; 507 /* And skip the files we searched above */ 508 for (i = 0; i < file->ndeps; i++) 509 if (lf == file->deps[i]) 510 break; 511 if (i < file->ndeps) 512 continue; 513 address = linker_file_lookup_symbol(lf, name, 0); 514 if (address) { 515 KLD_DPF(SYM, ("linker_file_lookup_symbol: global value=%x\n", address)); 516 return address; 517 } 518 } 519 } 520 521 if (common_size > 0) { 522 /* 523 * This is a common symbol which was not found in the 524 * dependancies. We maintain a simple common symbol table in 525 * the file object. 526 */ 527 struct common_symbol* cp; 528 529 for (cp = STAILQ_FIRST(&file->common); cp; 530 cp = STAILQ_NEXT(cp, link)) 531 if (!strcmp(cp->name, name)) { 532 KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address)); 533 return cp->address; 534 } 535 536 /* 537 * Round the symbol size up to align. 538 */ 539 common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 540 cp = malloc(sizeof(struct common_symbol) 541 + common_size 542 + strlen(name) + 1, 543 M_LINKER, M_WAITOK); 544 if (!cp) { 545 KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n")); 546 return 0; 547 } 548 bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1); 549 550 cp->address = (caddr_t) (cp + 1); 551 cp->name = cp->address + common_size; 552 strcpy(cp->name, name); 553 bzero(cp->address, common_size); 554 STAILQ_INSERT_TAIL(&file->common, cp, link); 555 556 KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address)); 557 return cp->address; 558 } 559 560 KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); 561 return 0; 562} 563 564#ifdef DDB 565/* 566 * DDB Helpers. DDB has to look across multiple files with their own 567 * symbol tables and string tables. 568 * 569 * Note that we do not obey list locking protocols here. We really don't 570 * need DDB to hang because somebody's got the lock held. We'll take the 571 * chance that the files list is inconsistant instead. 572 */ 573 574int 575linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym) 576{ 577 linker_file_t lf; 578 579 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 580 if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0) 581 return 0; 582 } 583 return ENOENT; 584} 585 586int 587linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 588{ 589 linker_file_t lf; 590 u_long off = (uintptr_t)value; 591 u_long diff, bestdiff; 592 c_linker_sym_t best; 593 c_linker_sym_t es; 594 595 best = 0; 596 bestdiff = off; 597 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 598 if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0) 599 continue; 600 if (es != 0 && diff < bestdiff) { 601 best = es; 602 bestdiff = diff; 603 } 604 if (bestdiff == 0) 605 break; 606 } 607 if (best) { 608 *sym = best; 609 *diffp = bestdiff; 610 return 0; 611 } else { 612 *sym = 0; 613 *diffp = off; 614 return ENOENT; 615 } 616} 617 618int 619linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 620{ 621 linker_file_t lf; 622 623 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 624 if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0) 625 return 0; 626 } 627 return ENOENT; 628} 629 630#endif 631 632/* 633 * Syscalls. 634 */ 635 636int 637kldload(struct proc* p, struct kldload_args* uap) 638{ 639 char* filename = NULL, *modulename; 640 linker_file_t lf; 641 int error = 0; 642 643 p->p_retval[0] = -1; 644 645 if (securelevel > 0) 646 return EPERM; 647 648 if ((error = suser(p)) != 0) 649 return error; 650 651 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 652 if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0) 653 goto out; 654 655 /* Can't load more than one module with the same name */ 656 modulename = rindex(filename, '/'); 657 if (modulename == NULL) 658 modulename = filename; 659 else 660 modulename++; 661 if (linker_find_file_by_name(modulename)) { 662 error = EEXIST; 663 goto out; 664 } 665 666 if ((error = linker_load_file(filename, &lf)) != 0) 667 goto out; 668 669 lf->userrefs++; 670 p->p_retval[0] = lf->id; 671 672out: 673 if (filename) 674 free(filename, M_TEMP); 675 return error; 676} 677 678int 679kldunload(struct proc* p, struct kldunload_args* uap) 680{ 681 linker_file_t lf; 682 int error = 0; 683 684 if (securelevel > 0) 685 return EPERM; 686 687 if ((error = suser(p)) != 0) 688 return error; 689 690 lf = linker_find_file_by_id(SCARG(uap, fileid)); 691 if (lf) { 692 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 693 if (lf->userrefs == 0) { 694 printf("linkerunload: attempt to unload file that was loaded by the kernel\n"); 695 error = EBUSY; 696 goto out; 697 } 698 lf->userrefs--; 699 error = linker_file_unload(lf); 700 if (error) 701 lf->userrefs++; 702 } else 703 error = ENOENT; 704 705out: 706 return error; 707} 708 709int 710kldfind(struct proc* p, struct kldfind_args* uap) 711{ 712 char* filename = NULL, *modulename; 713 linker_file_t lf; 714 int error = 0; 715 716 p->p_retval[0] = -1; 717 718 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 719 if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0) 720 goto out; 721 722 modulename = rindex(filename, '/'); 723 if (modulename == NULL) 724 modulename = filename; 725 726 lf = linker_find_file_by_name(modulename); 727 if (lf) 728 p->p_retval[0] = lf->id; 729 else 730 error = ENOENT; 731 732out: 733 if (filename) 734 free(filename, M_TEMP); 735 return error; 736} 737 738int 739kldnext(struct proc* p, struct kldnext_args* uap) 740{ 741 linker_file_t lf; 742 int error = 0; 743 744 if (SCARG(uap, fileid) == 0) { 745 if (TAILQ_FIRST(&linker_files)) 746 p->p_retval[0] = TAILQ_FIRST(&linker_files)->id; 747 else 748 p->p_retval[0] = 0; 749 return 0; 750 } 751 752 lf = linker_find_file_by_id(SCARG(uap, fileid)); 753 if (lf) { 754 if (TAILQ_NEXT(lf, link)) 755 p->p_retval[0] = TAILQ_NEXT(lf, link)->id; 756 else 757 p->p_retval[0] = 0; 758 } else 759 error = ENOENT; 760 761 return error; 762} 763 764int 765kldstat(struct proc* p, struct kldstat_args* uap) 766{ 767 linker_file_t lf; 768 int error = 0; 769 int version; 770 struct kld_file_stat* stat; 771 int namelen; 772 773 lf = linker_find_file_by_id(SCARG(uap, fileid)); 774 if (!lf) { 775 error = ENOENT; 776 goto out; 777 } 778 779 stat = SCARG(uap, stat); 780 781 /* 782 * Check the version of the user's structure. 783 */ 784 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) 785 goto out; 786 if (version != sizeof(struct kld_file_stat)) { 787 error = EINVAL; 788 goto out; 789 } 790 791 namelen = strlen(lf->filename) + 1; 792 if (namelen > MAXPATHLEN) 793 namelen = MAXPATHLEN; 794 if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0) 795 goto out; 796 if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0) 797 goto out; 798 if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0) 799 goto out; 800 if ((error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) != 0) 801 goto out; 802 if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0) 803 goto out; 804 805 p->p_retval[0] = 0; 806 807out: 808 return error; 809} 810 811int 812kldfirstmod(struct proc* p, struct kldfirstmod_args* uap) 813{ 814 linker_file_t lf; 815 int error = 0; 816 817 lf = linker_find_file_by_id(SCARG(uap, fileid)); 818 if (lf) { 819 if (TAILQ_FIRST(&lf->modules)) 820 p->p_retval[0] = module_getid(TAILQ_FIRST(&lf->modules)); 821 else 822 p->p_retval[0] = 0; 823 } else 824 error = ENOENT; 825 826 return error; 827} 828 829int 830kldsym(struct proc *p, struct kldsym_args *uap) 831{ 832 char *symstr = NULL; 833 c_linker_sym_t sym; 834 linker_symval_t symval; 835 linker_file_t lf; 836 struct kld_sym_lookup lookup; 837 int error = 0; 838 839 if ((error = copyin(SCARG(uap, data), &lookup, sizeof(lookup))) != 0) 840 goto out; 841 if (lookup.version != sizeof(lookup) || SCARG(uap, cmd) != KLDSYM_LOOKUP) { 842 error = EINVAL; 843 goto out; 844 } 845 846 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 847 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0) 848 goto out; 849 850 if (SCARG(uap, fileid) != 0) { 851 lf = linker_find_file_by_id(SCARG(uap, fileid)); 852 if (lf == NULL) { 853 error = ENOENT; 854 goto out; 855 } 856 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 857 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 858 lookup.symvalue = (uintptr_t)symval.value; 859 lookup.symsize = symval.size; 860 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup)); 861 } else 862 error = ENOENT; 863 } else { 864 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 865 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 866 LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 867 lookup.symvalue = (uintptr_t)symval.value; 868 lookup.symsize = symval.size; 869 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup)); 870 break; 871 } 872 } 873 if (!lf) 874 error = ENOENT; 875 } 876out: 877 if (symstr) 878 free(symstr, M_TEMP); 879 return error; 880} 881 882/* 883 * Preloaded module support 884 */ 885 886static void 887linker_preload(void* arg) 888{ 889 caddr_t modptr; 890 char *modname; 891 char *modtype; 892 linker_file_t lf; 893 linker_class_t lc; 894 int error; 895 struct linker_set *sysinits; 896 struct sysinit **sipp; 897 const moduledata_t *moddata; 898 899 modptr = NULL; 900 while ((modptr = preload_search_next_name(modptr)) != NULL) { 901 modname = (char *)preload_search_info(modptr, MODINFO_NAME); 902 modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); 903 if (modname == NULL) { 904 printf("Preloaded module at %p does not have a name!\n", modptr); 905 continue; 906 } 907 if (modtype == NULL) { 908 printf("Preloaded module at %p does not have a type!\n", modptr); 909 continue; 910 } 911 printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr); 912 lf = linker_find_file_by_name(modname); 913 if (lf) { 914 lf->userrefs++; 915 continue; 916 } 917 lf = NULL; 918 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 919 error = LINKER_LOAD_FILE(lc, modname, &lf); 920 if (error) { 921 lf = NULL; 922 break; 923 } 924 } 925 if (lf) { 926 lf->userrefs++; 927 928 sysinits = (struct linker_set*) 929 linker_file_lookup_symbol(lf, "sysinit_set", 0); 930 if (sysinits) { 931 /* HACK ALERT! 932 * This is to set the sysinit moduledata so that the module 933 * can attach itself to the correct containing file. 934 * The sysinit could be run at *any* time. 935 */ 936 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 937 if ((*sipp)->func == module_register_init) { 938 moddata = (*sipp)->udata; 939 error = module_register(moddata, lf); 940 if (error) 941 printf("Preloaded %s \"%s\" failed to register: %d\n", 942 modtype, modname, error); 943 } 944 } 945 sysinit_add((struct sysinit **)sysinits->ls_items); 946 } 947 linker_file_register_sysctls(lf); 948 } 949 } 950} 951 952SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); 953 954/* 955 * Search for a not-loaded module by name. 956 * 957 * Modules may be found in the following locations: 958 * 959 * - preloaded (result is just the module name) 960 * - on disk (result is full path to module) 961 * 962 * If the module name is qualified in any way (contains path, etc.) 963 * the we simply return a copy of it. 964 * 965 * The search path can be manipulated via sysctl. Note that we use the ';' 966 * character as a separator to be consistent with the bootloader. 967 */ 968 969static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/"; 970 971SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, 972 sizeof(linker_path), "module load search path"); 973 974char * 975linker_search_path(const char *name) 976{ 977 struct nameidata nd; 978 struct proc *p = curproc; /* XXX */ 979 char *cp, *ep, *result; 980 int error; 981 enum vtype type; 982 983 /* qualified at all? */ 984 if (index(name, '/')) 985 return(linker_strdup(name)); 986 987 /* traverse the linker path */ 988 cp = linker_path; 989 for (;;) { 990 991 /* find the end of this component */ 992 for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) 993 ; 994 result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); 995 if (result == NULL) /* actually ENOMEM */ 996 return(NULL); 997 998 strncpy(result, cp, ep - cp); 999 strcpy(result + (ep - cp), name); 1000 1001 /* 1002 * Attempt to open the file, and return the path if we succeed and it's 1003 * a regular file. 1004 */ 1005 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p); 1006 error = vn_open(&nd, FREAD, 0); 1007 if (error == 0) { 1008 NDFREE(&nd, NDF_ONLY_PNBUF); 1009 type = nd.ni_vp->v_type; 1010 VOP_UNLOCK(nd.ni_vp, 0, p); 1011 vn_close(nd.ni_vp, FREAD, p->p_ucred, p); 1012 if (type == VREG) 1013 return(result); 1014 } 1015 free(result, M_LINKER); 1016 1017 if (*ep == 0) 1018 break; 1019 cp = ep + 1; 1020 } 1021 return(NULL); 1022} 1023