kern_linker.c revision 50477
1/*- 2 * Copyright (c) 1997 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 50477 1999-08-28 01:08:13Z peter $ 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 <machine/cpu.h> 40#include <machine/bootinfo.h> 41#include <sys/module.h> 42#include <sys/linker.h> 43#include <sys/unistd.h> 44#include <sys/fcntl.h> 45#include <sys/libkern.h> 46#include <sys/namei.h> 47#include <sys/vnode.h> 48#include <sys/sysctl.h> 49 50#ifdef KLD_DEBUG 51int kld_debug = 0; 52#endif 53 54MALLOC_DEFINE(M_LINKER, "kld", "kernel linker"); 55linker_file_t linker_current_file; 56linker_file_t linker_kernel_file; 57 58static struct lock lock; /* lock for the file list */ 59static linker_class_list_t classes; 60static linker_file_list_t linker_files; 61static int next_file_id = 1; 62 63static void 64linker_init(void* arg) 65{ 66 lockinit(&lock, PVM, "klink", 0, 0); 67 TAILQ_INIT(&classes); 68 TAILQ_INIT(&linker_files); 69} 70 71SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); 72 73int 74linker_add_class(const char* desc, void* priv, 75 struct linker_class_ops* ops) 76{ 77 linker_class_t lc; 78 79 lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT); 80 if (!lc) 81 return ENOMEM; 82 bzero(lc, sizeof(*lc)); 83 84 lc->desc = desc; 85 lc->priv = priv; 86 lc->ops = ops; 87 TAILQ_INSERT_HEAD(&classes, lc, link); 88 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 = lc->ops->load_file(koname, &lf); /* First with .ko */ 272 if (lf == NULL && error == ENOENT) 273 error = lc->ops->load_file(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, void* priv, struct linker_file_ops* ops) 346{ 347 linker_file_t lf = 0; 348 int namelen; 349 const char *filename; 350 351 filename = rindex(pathname, '/'); 352 if (filename && filename[1]) 353 filename++; 354 else 355 filename = pathname; 356 357 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename)); 358 lockmgr(&lock, LK_EXCLUSIVE, 0, curproc); 359 namelen = strlen(filename) + 1; 360 lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK); 361 if (!lf) 362 goto out; 363 bzero(lf, sizeof(*lf)); 364 365 lf->refs = 1; 366 lf->userrefs = 0; 367 lf->flags = 0; 368 lf->filename = (char*) (lf + 1); 369 strcpy(lf->filename, filename); 370 lf->id = next_file_id++; 371 lf->ndeps = 0; 372 lf->deps = NULL; 373 STAILQ_INIT(&lf->common); 374 TAILQ_INIT(&lf->modules); 375 376 lf->priv = priv; 377 lf->ops = ops; 378 TAILQ_INSERT_TAIL(&linker_files, lf, link); 379 380out: 381 lockmgr(&lock, LK_RELEASE, 0, curproc); 382 return lf; 383} 384 385int 386linker_file_unload(linker_file_t file) 387{ 388 module_t mod, next; 389 struct common_symbol* cp; 390 int error = 0; 391 int i; 392 393 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); 394 lockmgr(&lock, LK_EXCLUSIVE, 0, curproc); 395 if (file->refs == 1) { 396 KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n")); 397 /* 398 * Inform any modules associated with this file. 399 */ 400 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 401 next = module_getfnext(mod); 402 403 /* 404 * Give the module a chance to veto the unload. 405 */ 406 if ((error = module_unload(mod)) != 0) { 407 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n", 408 mod)); 409 lockmgr(&lock, LK_RELEASE, 0, curproc); 410 goto out; 411 } 412 413 module_release(mod); 414 } 415 } 416 417 file->refs--; 418 if (file->refs > 0) { 419 lockmgr(&lock, LK_RELEASE, 0, curproc); 420 goto out; 421 } 422 423 /* Don't try to run SYSUNINITs if we are unloaded due to a link error */ 424 if (file->flags & LINKER_FILE_LINKED) { 425 linker_file_sysuninit(file); 426 linker_file_unregister_sysctls(file); 427 } 428 429 TAILQ_REMOVE(&linker_files, file, link); 430 lockmgr(&lock, LK_RELEASE, 0, curproc); 431 432 for (i = 0; i < file->ndeps; i++) 433 linker_file_unload(file->deps[i]); 434 free(file->deps, M_LINKER); 435 436 for (cp = STAILQ_FIRST(&file->common); cp; 437 cp = STAILQ_FIRST(&file->common)) { 438 STAILQ_REMOVE(&file->common, cp, common_symbol, link); 439 free(cp, M_LINKER); 440 } 441 442 file->ops->unload(file); 443 free(file, M_LINKER); 444 445out: 446 return error; 447} 448 449int 450linker_file_add_dependancy(linker_file_t file, linker_file_t dep) 451{ 452 linker_file_t* newdeps; 453 454 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*), 455 M_LINKER, M_WAITOK); 456 if (newdeps == NULL) 457 return ENOMEM; 458 bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*)); 459 460 if (file->deps) { 461 bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*)); 462 free(file->deps, M_LINKER); 463 } 464 file->deps = newdeps; 465 file->deps[file->ndeps] = dep; 466 file->ndeps++; 467 468 return 0; 469} 470 471caddr_t 472linker_file_lookup_symbol(linker_file_t file, const char* name, int deps) 473{ 474 c_linker_sym_t sym; 475 linker_symval_t symval; 476 linker_file_t lf; 477 caddr_t address; 478 size_t common_size = 0; 479 int i; 480 481 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n", 482 file, name, deps)); 483 484 if (file->ops->lookup_symbol(file, name, &sym) == 0) { 485 file->ops->symbol_values(file, sym, &symval); 486 if (symval.value == 0) 487 /* 488 * For commons, first look them up in the dependancies and 489 * only allocate space if not found there. 490 */ 491 common_size = symval.size; 492 else { 493 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value)); 494 return symval.value; 495 } 496 } 497 498 if (deps) { 499 for (i = 0; i < file->ndeps; i++) { 500 address = linker_file_lookup_symbol(file->deps[i], name, 0); 501 if (address) { 502 KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address)); 503 return address; 504 } 505 } 506 507 /* If we have not found it in the dependencies, search globally */ 508 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 509 /* But skip the current file if it's on the list */ 510 if (lf == file) 511 continue; 512 /* And skip the files we searched above */ 513 for (i = 0; i < file->ndeps; i++) 514 if (lf == file->deps[i]) 515 break; 516 if (i < file->ndeps) 517 continue; 518 address = linker_file_lookup_symbol(lf, name, 0); 519 if (address) { 520 KLD_DPF(SYM, ("linker_file_lookup_symbol: global value=%x\n", address)); 521 return address; 522 } 523 } 524 } 525 526 if (common_size > 0) { 527 /* 528 * This is a common symbol which was not found in the 529 * dependancies. We maintain a simple common symbol table in 530 * the file object. 531 */ 532 struct common_symbol* cp; 533 534 for (cp = STAILQ_FIRST(&file->common); cp; 535 cp = STAILQ_NEXT(cp, link)) 536 if (!strcmp(cp->name, name)) { 537 KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address)); 538 return cp->address; 539 } 540 541 /* 542 * Round the symbol size up to align. 543 */ 544 common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 545 cp = malloc(sizeof(struct common_symbol) 546 + common_size 547 + strlen(name) + 1, 548 M_LINKER, M_WAITOK); 549 if (!cp) { 550 KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n")); 551 return 0; 552 } 553 bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1); 554 555 cp->address = (caddr_t) (cp + 1); 556 cp->name = cp->address + common_size; 557 strcpy(cp->name, name); 558 bzero(cp->address, common_size); 559 STAILQ_INSERT_TAIL(&file->common, cp, link); 560 561 KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address)); 562 return cp->address; 563 } 564 565 KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); 566 return 0; 567} 568 569#ifdef DDB 570/* 571 * DDB Helpers. DDB has to look across multiple files with their own 572 * symbol tables and string tables. 573 * 574 * Note that we do not obey list locking protocols here. We really don't 575 * need DDB to hang because somebody's got the lock held. We'll take the 576 * chance that the files list is inconsistant instead. 577 */ 578 579int 580linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym) 581{ 582 linker_file_t lf; 583 584 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 585 if (lf->ops->lookup_symbol(lf, symstr, sym) == 0) 586 return 0; 587 } 588 return ENOENT; 589} 590 591int 592linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 593{ 594 linker_file_t lf; 595 u_long off = (uintptr_t)value; 596 u_long diff, bestdiff; 597 c_linker_sym_t best; 598 c_linker_sym_t es; 599 600 best = 0; 601 bestdiff = off; 602 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 603 if (lf->ops->search_symbol(lf, value, &es, &diff) != 0) 604 continue; 605 if (es != 0 && diff < bestdiff) { 606 best = es; 607 bestdiff = diff; 608 } 609 if (bestdiff == 0) 610 break; 611 } 612 if (best) { 613 *sym = best; 614 *diffp = bestdiff; 615 return 0; 616 } else { 617 *sym = 0; 618 *diffp = off; 619 return ENOENT; 620 } 621} 622 623int 624linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 625{ 626 linker_file_t lf; 627 628 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 629 if (lf->ops->symbol_values(lf, sym, symval) == 0) 630 return 0; 631 } 632 return ENOENT; 633} 634 635#endif 636 637/* 638 * Syscalls. 639 */ 640 641int 642kldload(struct proc* p, struct kldload_args* uap) 643{ 644 char* filename = NULL, *modulename; 645 linker_file_t lf; 646 int error = 0; 647 648 p->p_retval[0] = -1; 649 650 if (securelevel > 0) 651 return EPERM; 652 653 if ((error = suser(p)) != 0) 654 return error; 655 656 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 657 if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0) 658 goto out; 659 660 /* Can't load more than one module with the same name */ 661 modulename = rindex(filename, '/'); 662 if (modulename == NULL) 663 modulename = filename; 664 else 665 modulename++; 666 if (linker_find_file_by_name(modulename)) { 667 error = EEXIST; 668 goto out; 669 } 670 671 if ((error = linker_load_file(filename, &lf)) != 0) 672 goto out; 673 674 lf->userrefs++; 675 p->p_retval[0] = lf->id; 676 677out: 678 if (filename) 679 free(filename, M_TEMP); 680 return error; 681} 682 683int 684kldunload(struct proc* p, struct kldunload_args* uap) 685{ 686 linker_file_t lf; 687 int error = 0; 688 689 if (securelevel > 0) 690 return EPERM; 691 692 if ((error = suser(p)) != 0) 693 return error; 694 695 lf = linker_find_file_by_id(SCARG(uap, fileid)); 696 if (lf) { 697 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 698 if (lf->userrefs == 0) { 699 printf("linkerunload: attempt to unload file that was loaded by the kernel\n"); 700 error = EBUSY; 701 goto out; 702 } 703 lf->userrefs--; 704 error = linker_file_unload(lf); 705 if (error) 706 lf->userrefs++; 707 } else 708 error = ENOENT; 709 710out: 711 return error; 712} 713 714int 715kldfind(struct proc* p, struct kldfind_args* uap) 716{ 717 char* filename = NULL, *modulename; 718 linker_file_t lf; 719 int error = 0; 720 721 p->p_retval[0] = -1; 722 723 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 724 if ((error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) != 0) 725 goto out; 726 727 modulename = rindex(filename, '/'); 728 if (modulename == NULL) 729 modulename = filename; 730 731 lf = linker_find_file_by_name(modulename); 732 if (lf) 733 p->p_retval[0] = lf->id; 734 else 735 error = ENOENT; 736 737out: 738 if (filename) 739 free(filename, M_TEMP); 740 return error; 741} 742 743int 744kldnext(struct proc* p, struct kldnext_args* uap) 745{ 746 linker_file_t lf; 747 int error = 0; 748 749 if (SCARG(uap, fileid) == 0) { 750 if (TAILQ_FIRST(&linker_files)) 751 p->p_retval[0] = TAILQ_FIRST(&linker_files)->id; 752 else 753 p->p_retval[0] = 0; 754 return 0; 755 } 756 757 lf = linker_find_file_by_id(SCARG(uap, fileid)); 758 if (lf) { 759 if (TAILQ_NEXT(lf, link)) 760 p->p_retval[0] = TAILQ_NEXT(lf, link)->id; 761 else 762 p->p_retval[0] = 0; 763 } else 764 error = ENOENT; 765 766 return error; 767} 768 769int 770kldstat(struct proc* p, struct kldstat_args* uap) 771{ 772 linker_file_t lf; 773 int error = 0; 774 int version; 775 struct kld_file_stat* stat; 776 int namelen; 777 778 lf = linker_find_file_by_id(SCARG(uap, fileid)); 779 if (!lf) { 780 error = ENOENT; 781 goto out; 782 } 783 784 stat = SCARG(uap, stat); 785 786 /* 787 * Check the version of the user's structure. 788 */ 789 if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) 790 goto out; 791 if (version != sizeof(struct kld_file_stat)) { 792 error = EINVAL; 793 goto out; 794 } 795 796 namelen = strlen(lf->filename) + 1; 797 if (namelen > MAXPATHLEN) 798 namelen = MAXPATHLEN; 799 if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0) 800 goto out; 801 if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0) 802 goto out; 803 if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0) 804 goto out; 805 if ((error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) != 0) 806 goto out; 807 if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0) 808 goto out; 809 810 p->p_retval[0] = 0; 811 812out: 813 return error; 814} 815 816int 817kldfirstmod(struct proc* p, struct kldfirstmod_args* uap) 818{ 819 linker_file_t lf; 820 int error = 0; 821 822 lf = linker_find_file_by_id(SCARG(uap, fileid)); 823 if (lf) { 824 if (TAILQ_FIRST(&lf->modules)) 825 p->p_retval[0] = module_getid(TAILQ_FIRST(&lf->modules)); 826 else 827 p->p_retval[0] = 0; 828 } else 829 error = ENOENT; 830 831 return error; 832} 833 834int 835kldsym(struct proc *p, struct kldsym_args *uap) 836{ 837 char *symstr = NULL; 838 c_linker_sym_t sym; 839 linker_symval_t symval; 840 linker_file_t lf; 841 struct kld_sym_lookup lookup; 842 int error = 0; 843 844 if ((error = copyin(SCARG(uap, data), &lookup, sizeof(lookup))) != 0) 845 goto out; 846 if (lookup.version != sizeof(lookup) || SCARG(uap, cmd) != KLDSYM_LOOKUP) { 847 error = EINVAL; 848 goto out; 849 } 850 851 symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 852 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0) 853 goto out; 854 855 if (SCARG(uap, fileid) != 0) { 856 lf = linker_find_file_by_id(SCARG(uap, fileid)); 857 if (lf == NULL) { 858 error = ENOENT; 859 goto out; 860 } 861 if (lf->ops->lookup_symbol(lf, symstr, &sym) == 0 && 862 lf->ops->symbol_values(lf, sym, &symval) == 0) { 863 lookup.symvalue = (uintptr_t)symval.value; 864 lookup.symsize = symval.size; 865 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup)); 866 } else 867 error = ENOENT; 868 } else { 869 for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { 870 if (lf->ops->lookup_symbol(lf, symstr, &sym) == 0 && 871 lf->ops->symbol_values(lf, sym, &symval) == 0) { 872 lookup.symvalue = (uintptr_t)symval.value; 873 lookup.symsize = symval.size; 874 error = copyout(&lookup, SCARG(uap, data), sizeof(lookup)); 875 break; 876 } 877 } 878 if (!lf) 879 error = ENOENT; 880 } 881out: 882 if (symstr) 883 free(symstr, M_TEMP); 884 return error; 885} 886 887/* 888 * Preloaded module support 889 */ 890 891static void 892linker_preload(void* arg) 893{ 894 caddr_t modptr; 895 char *modname; 896 char *modtype; 897 linker_file_t lf; 898 linker_class_t lc; 899 int error; 900 struct linker_set *sysinits; 901 struct sysinit **sipp; 902 const moduledata_t *moddata; 903 904 modptr = NULL; 905 while ((modptr = preload_search_next_name(modptr)) != NULL) { 906 modname = (char *)preload_search_info(modptr, MODINFO_NAME); 907 modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); 908 if (modname == NULL) { 909 printf("Preloaded module at %p does not have a name!\n", modptr); 910 continue; 911 } 912 if (modtype == NULL) { 913 printf("Preloaded module at %p does not have a type!\n", modptr); 914 continue; 915 } 916 printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr); 917 lf = linker_find_file_by_name(modname); 918 if (lf) { 919 lf->userrefs++; 920 continue; 921 } 922 lf = NULL; 923 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 924 error = lc->ops->load_file(modname, &lf); 925 if (error) { 926 lf = NULL; 927 break; 928 } 929 } 930 if (lf) { 931 lf->userrefs++; 932 933 sysinits = (struct linker_set*) 934 linker_file_lookup_symbol(lf, "sysinit_set", 0); 935 if (sysinits) { 936 /* HACK ALERT! 937 * This is to set the sysinit moduledata so that the module 938 * can attach itself to the correct containing file. 939 * The sysinit could be run at *any* time. 940 */ 941 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 942 if ((*sipp)->func == module_register_init) { 943 moddata = (*sipp)->udata; 944 error = module_register(moddata, lf); 945 if (error) 946 printf("Preloaded %s \"%s\" failed to register: %d\n", 947 modtype, modname, error); 948 } 949 } 950 sysinit_add((struct sysinit **)sysinits->ls_items); 951 } 952 linker_file_register_sysctls(lf); 953 } 954 } 955} 956 957SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); 958 959/* 960 * Search for a not-loaded module by name. 961 * 962 * Modules may be found in the following locations: 963 * 964 * - preloaded (result is just the module name) 965 * - on disk (result is full path to module) 966 * 967 * If the module name is qualified in any way (contains path, etc.) 968 * the we simply return a copy of it. 969 * 970 * The search path can be manipulated via sysctl. Note that we use the ';' 971 * character as a separator to be consistent with the bootloader. 972 */ 973 974static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/"; 975 976SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, 977 sizeof(linker_path), "module load search path"); 978 979static char * 980linker_strdup(const char *str) 981{ 982 char *result; 983 984 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL) 985 strcpy(result, str); 986 return(result); 987} 988 989char * 990linker_search_path(const char *name) 991{ 992 struct nameidata nd; 993 struct proc *p = curproc; /* XXX */ 994 char *cp, *ep, *result; 995 int error; 996 enum vtype type; 997 998 /* qualified at all? */ 999 if (index(name, '/')) 1000 return(linker_strdup(name)); 1001 1002 /* traverse the linker path */ 1003 cp = linker_path; 1004 for (;;) { 1005 1006 /* find the end of this component */ 1007 for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) 1008 ; 1009 result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); 1010 if (result == NULL) /* actually ENOMEM */ 1011 return(NULL); 1012 1013 strncpy(result, cp, ep - cp); 1014 strcpy(result + (ep - cp), name); 1015 1016 /* 1017 * Attempt to open the file, and return the path if we succeed and it's 1018 * a regular file. 1019 */ 1020 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p); 1021 error = vn_open(&nd, FREAD, 0); 1022 if (error == 0) { 1023 type = nd.ni_vp->v_type; 1024 VOP_UNLOCK(nd.ni_vp, 0, p); 1025 vn_close(nd.ni_vp, FREAD, p->p_ucred, p); 1026 if (type == VREG) 1027 return(result); 1028 } 1029 free(result, M_LINKER); 1030 1031 if (*ep == 0) 1032 break; 1033 cp = ep + 1; 1034 } 1035 return(NULL); 1036} 1037