kern_linker.c (254810) | kern_linker.c (254811) |
---|---|
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 254810 2013-08-24 21:07:04Z markj $"); | 28__FBSDID("$FreeBSD: head/sys/kern/kern_linker.c 254811 2013-08-24 21:08:55Z markj $"); |
29 30#include "opt_ddb.h" 31#include "opt_kld.h" 32#include "opt_hwpmc_hooks.h" 33 34#include <sys/param.h> 35#include <sys/kernel.h> 36#include <sys/systm.h> --- 146 unchanged lines hidden (view full) --- 183static void 184linker_file_sysinit(linker_file_t lf) 185{ 186 struct sysinit **start, **stop, **sipp, **xipp, *save; 187 188 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 189 lf->filename)); 190 | 29 30#include "opt_ddb.h" 31#include "opt_kld.h" 32#include "opt_hwpmc_hooks.h" 33 34#include <sys/param.h> 35#include <sys/kernel.h> 36#include <sys/systm.h> --- 146 unchanged lines hidden (view full) --- 183static void 184linker_file_sysinit(linker_file_t lf) 185{ 186 struct sysinit **start, **stop, **sipp, **xipp, *save; 187 188 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 189 lf->filename)); 190 |
191 sx_assert(&kld_sx, SA_XLOCKED); 192 |
|
191 if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0) 192 return; 193 /* 194 * Perform a bubble sort of the system initialization objects by 195 * their subsystem (primary key) and order (secondary key). 196 * 197 * Since some things care about execution order, this is the operation 198 * which ensures continued function. --- 9 unchanged lines hidden (view full) --- 208 *xipp = save; 209 } 210 } 211 212 /* 213 * Traverse the (now) ordered list of system initialization tasks. 214 * Perform each task, and continue on to the next task. 215 */ | 193 if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0) 194 return; 195 /* 196 * Perform a bubble sort of the system initialization objects by 197 * their subsystem (primary key) and order (secondary key). 198 * 199 * Since some things care about execution order, this is the operation 200 * which ensures continued function. --- 9 unchanged lines hidden (view full) --- 210 *xipp = save; 211 } 212 } 213 214 /* 215 * Traverse the (now) ordered list of system initialization tasks. 216 * Perform each task, and continue on to the next task. 217 */ |
218 sx_xunlock(&kld_sx); |
|
216 mtx_lock(&Giant); 217 for (sipp = start; sipp < stop; sipp++) { 218 if ((*sipp)->subsystem == SI_SUB_DUMMY) 219 continue; /* skip dummy task(s) */ 220 221 /* Call function */ 222 (*((*sipp)->func)) ((*sipp)->udata); 223 } 224 mtx_unlock(&Giant); | 219 mtx_lock(&Giant); 220 for (sipp = start; sipp < stop; sipp++) { 221 if ((*sipp)->subsystem == SI_SUB_DUMMY) 222 continue; /* skip dummy task(s) */ 223 224 /* Call function */ 225 (*((*sipp)->func)) ((*sipp)->udata); 226 } 227 mtx_unlock(&Giant); |
228 sx_xlock(&kld_sx); |
|
225} 226 227static void 228linker_file_sysuninit(linker_file_t lf) 229{ 230 struct sysinit **start, **stop, **sipp, **xipp, *save; 231 232 KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", 233 lf->filename)); 234 | 229} 230 231static void 232linker_file_sysuninit(linker_file_t lf) 233{ 234 struct sysinit **start, **stop, **sipp, **xipp, *save; 235 236 KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", 237 lf->filename)); 238 |
239 sx_assert(&kld_sx, SA_XLOCKED); 240 |
|
235 if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, 236 NULL) != 0) 237 return; 238 239 /* 240 * Perform a reverse bubble sort of the system initialization objects 241 * by their subsystem (primary key) and order (secondary key). 242 * --- 11 unchanged lines hidden (view full) --- 254 *xipp = save; 255 } 256 } 257 258 /* 259 * Traverse the (now) ordered list of system initialization tasks. 260 * Perform each task, and continue on to the next task. 261 */ | 241 if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, 242 NULL) != 0) 243 return; 244 245 /* 246 * Perform a reverse bubble sort of the system initialization objects 247 * by their subsystem (primary key) and order (secondary key). 248 * --- 11 unchanged lines hidden (view full) --- 260 *xipp = save; 261 } 262 } 263 264 /* 265 * Traverse the (now) ordered list of system initialization tasks. 266 * Perform each task, and continue on to the next task. 267 */ |
268 sx_xunlock(&kld_sx); |
|
262 mtx_lock(&Giant); 263 for (sipp = start; sipp < stop; sipp++) { 264 if ((*sipp)->subsystem == SI_SUB_DUMMY) 265 continue; /* skip dummy task(s) */ 266 267 /* Call function */ 268 (*((*sipp)->func)) ((*sipp)->udata); 269 } 270 mtx_unlock(&Giant); | 269 mtx_lock(&Giant); 270 for (sipp = start; sipp < stop; sipp++) { 271 if ((*sipp)->subsystem == SI_SUB_DUMMY) 272 continue; /* skip dummy task(s) */ 273 274 /* Call function */ 275 (*((*sipp)->func)) ((*sipp)->udata); 276 } 277 mtx_unlock(&Giant); |
278 sx_xlock(&kld_sx); |
|
271} 272 273static void 274linker_file_register_sysctls(linker_file_t lf) 275{ 276 struct sysctl_oid **start, **stop, **oidp; 277 278 KLD_DPF(FILE, 279 ("linker_file_register_sysctls: registering SYSCTLs for %s\n", 280 lf->filename)); 281 | 279} 280 281static void 282linker_file_register_sysctls(linker_file_t lf) 283{ 284 struct sysctl_oid **start, **stop, **oidp; 285 286 KLD_DPF(FILE, 287 ("linker_file_register_sysctls: registering SYSCTLs for %s\n", 288 lf->filename)); 289 |
290 sx_assert(&kld_sx, SA_XLOCKED); 291 |
|
282 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 283 return; 284 | 292 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 293 return; 294 |
295 sx_xunlock(&kld_sx); |
|
285 sysctl_lock(); 286 for (oidp = start; oidp < stop; oidp++) 287 sysctl_register_oid(*oidp); 288 sysctl_unlock(); | 296 sysctl_lock(); 297 for (oidp = start; oidp < stop; oidp++) 298 sysctl_register_oid(*oidp); 299 sysctl_unlock(); |
300 sx_xlock(&kld_sx); |
|
289} 290 291static void 292linker_file_unregister_sysctls(linker_file_t lf) 293{ 294 struct sysctl_oid **start, **stop, **oidp; 295 296 KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs" 297 " for %s\n", lf->filename)); 298 | 301} 302 303static void 304linker_file_unregister_sysctls(linker_file_t lf) 305{ 306 struct sysctl_oid **start, **stop, **oidp; 307 308 KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs" 309 " for %s\n", lf->filename)); 310 |
311 sx_assert(&kld_sx, SA_XLOCKED); 312 |
|
299 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 300 return; 301 | 313 if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 314 return; 315 |
316 sx_xunlock(&kld_sx); |
|
302 sysctl_lock(); 303 for (oidp = start; oidp < stop; oidp++) 304 sysctl_unregister_oid(*oidp); 305 sysctl_unlock(); | 317 sysctl_lock(); 318 for (oidp = start; oidp < stop; oidp++) 319 sysctl_unregister_oid(*oidp); 320 sysctl_unlock(); |
321 sx_xlock(&kld_sx); |
|
306} 307 308static int 309linker_file_register_modules(linker_file_t lf) 310{ 311 struct mod_metadata **start, **stop, **mdp; 312 const moduledata_t *moddata; 313 int first_error, error; 314 315 KLD_DPF(FILE, ("linker_file_register_modules: registering modules" 316 " in %s\n", lf->filename)); 317 | 322} 323 324static int 325linker_file_register_modules(linker_file_t lf) 326{ 327 struct mod_metadata **start, **stop, **mdp; 328 const moduledata_t *moddata; 329 int first_error, error; 330 331 KLD_DPF(FILE, ("linker_file_register_modules: registering modules" 332 " in %s\n", lf->filename)); 333 |
334 sx_assert(&kld_sx, SA_XLOCKED); 335 |
|
318 if (linker_file_lookup_set(lf, "modmetadata_set", &start, 319 &stop, NULL) != 0) { 320 /* 321 * This fallback should be unnecessary, but if we get booted 322 * from boot2 instead of loader and we are missing our 323 * metadata then we have to try the best we can. 324 */ 325 if (lf == linker_kernel_file) { --- 72 unchanged lines hidden (view full) --- 398 foundfile = 1; 399 if (lf) { 400 error = linker_file_register_modules(lf); 401 if (error == EEXIST) { 402 linker_file_unload(lf, LINKER_UNLOAD_FORCE); 403 return (error); 404 } 405 modules = !TAILQ_EMPTY(&lf->modules); | 336 if (linker_file_lookup_set(lf, "modmetadata_set", &start, 337 &stop, NULL) != 0) { 338 /* 339 * This fallback should be unnecessary, but if we get booted 340 * from boot2 instead of loader and we are missing our 341 * metadata then we have to try the best we can. 342 */ 343 if (lf == linker_kernel_file) { --- 72 unchanged lines hidden (view full) --- 416 foundfile = 1; 417 if (lf) { 418 error = linker_file_register_modules(lf); 419 if (error == EEXIST) { 420 linker_file_unload(lf, LINKER_UNLOAD_FORCE); 421 return (error); 422 } 423 modules = !TAILQ_EMPTY(&lf->modules); |
406 sx_xunlock(&kld_sx); | |
407 linker_file_register_sysctls(lf); 408 linker_file_sysinit(lf); | 424 linker_file_register_sysctls(lf); 425 linker_file_sysinit(lf); |
409 sx_xlock(&kld_sx); | |
410 lf->flags |= LINKER_FILE_LINKED; 411 412 /* 413 * If all of the modules in this file failed 414 * to load, unload the file and return an 415 * error of ENOEXEC. 416 */ 417 if (modules && TAILQ_EMPTY(&lf->modules)) { --- 234 unchanged lines hidden (view full) --- 652 } 653 654 /* 655 * Don't try to run SYSUNINITs if we are unloaded due to a 656 * link error. 657 */ 658 if (file->flags & LINKER_FILE_LINKED) { 659 file->flags &= ~LINKER_FILE_LINKED; | 426 lf->flags |= LINKER_FILE_LINKED; 427 428 /* 429 * If all of the modules in this file failed 430 * to load, unload the file and return an 431 * error of ENOEXEC. 432 */ 433 if (modules && TAILQ_EMPTY(&lf->modules)) { --- 234 unchanged lines hidden (view full) --- 668 } 669 670 /* 671 * Don't try to run SYSUNINITs if we are unloaded due to a 672 * link error. 673 */ 674 if (file->flags & LINKER_FILE_LINKED) { 675 file->flags &= ~LINKER_FILE_LINKED; |
660 sx_xunlock(&kld_sx); | |
661 linker_file_sysuninit(file); 662 linker_file_unregister_sysctls(file); | 676 linker_file_sysuninit(file); 677 linker_file_unregister_sysctls(file); |
663 sx_xlock(&kld_sx); | |
664 } 665 TAILQ_REMOVE(&linker_files, file, link); 666 667 if (file->deps) { 668 for (i = 0; i < file->ndeps; i++) 669 linker_file_unload(file->deps[i], flags); 670 free(file->deps, M_LINKER); 671 file->deps = NULL; --- 52 unchanged lines hidden (view full) --- 724 * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **. 725 * This function is used in this file so we can avoid having lots of (void **) 726 * casts. 727 */ 728int 729linker_file_lookup_set(linker_file_t file, const char *name, 730 void *firstp, void *lastp, int *countp) 731{ | 678 } 679 TAILQ_REMOVE(&linker_files, file, link); 680 681 if (file->deps) { 682 for (i = 0; i < file->ndeps; i++) 683 linker_file_unload(file->deps[i], flags); 684 free(file->deps, M_LINKER); 685 file->deps = NULL; --- 52 unchanged lines hidden (view full) --- 738 * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **. 739 * This function is used in this file so we can avoid having lots of (void **) 740 * casts. 741 */ 742int 743linker_file_lookup_set(linker_file_t file, const char *name, 744 void *firstp, void *lastp, int *countp) 745{ |
732 int error, locked; | |
733 | 746 |
734 locked = sx_xlocked(&kld_sx); 735 if (!locked) 736 sx_xlock(&kld_sx); 737 error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp); 738 if (!locked) 739 sx_xunlock(&kld_sx); 740 return (error); | 747 sx_assert(&kld_sx, SA_LOCKED); 748 return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp)); |
741} 742 743/* 744 * List all functions in a file. 745 */ 746int 747linker_file_function_listall(linker_file_t lf, 748 linker_function_nameval_callback_t callback_func, void *arg) --- 1419 unchanged lines hidden --- | 749} 750 751/* 752 * List all functions in a file. 753 */ 754int 755linker_file_function_listall(linker_file_t lf, 756 linker_function_nameval_callback_t callback_func, void *arg) --- 1419 unchanged lines hidden --- |