-/*********************************************************************
-* This function clears out all references to the in-kernel linker,
-* frees the list of startup extensions in extensionDict, and
-* deallocates the kernel's __KLD segment to reclaim that memory.
-*
-* The segments it operates on are strictly 32 bit segments.
-*********************************************************************/
-kern_return_t IOCatalogue::removeKernelLinker(void) {
- kern_return_t result = KERN_SUCCESS;
- struct segment_command * segmentLE, *segmentKLD;
- boolean_t keepsyms = FALSE;
-#if __ppc__
- char * dt_segment_name;
- void * segment_paddress;
- int segment_size;
-#endif
-
- /* This must be the very first thing done by this function.
- */
- IOLockLock(kld_lock);
-
-
- /* If the kernel linker isn't here, that's automatically
- * a success.
- */
- if (!kernelLinkerPresent) {
- result = KERN_SUCCESS;
- goto finish;
- }
-
- PE_parse_boot_arg("keepsyms", &keepsyms);
-
- IOLog("Jettisoning kernel linker.\n");
-
- kernelLinkerPresent = 0;
-
- /* Set the kmod_load_extension function as the means for loading
- * a kernel extension.
- */
- kmod_load_function = &kmod_load_extension;
-
- record_startup_extensions_function = 0;
- add_from_mkext_function = 0;
- remove_startup_extension_function = 0;
-
-
- /* Invoke destructors for the __KLD and __LINKEDIT segments.
- * Do this for all segments before actually freeing their
- * memory so that any cross-dependencies (not that there
- * should be any) are handled.
- */
- segmentKLD = getsegbyname("__KLD");
- if (!segmentKLD) {
- IOLog("error removing kernel linker: can't find %s segment\n",
- "__KLD");
- result = KERN_FAILURE;
- goto finish;
- }
- OSRuntimeUnloadCPPForSegment(segmentKLD);
-
- segmentLE = getsegbyname("__LINKEDIT");
- if (!segmentLE) {
- IOLog("error removing kernel linker: can't find %s segment\n",
- "__LINKEDIT");
- result = KERN_FAILURE;
- goto finish;
- }
- OSRuntimeUnloadCPPForSegment(segmentLE);
-#if __ppc__
- /* Free the memory that was set up by bootx.
- */
- dt_segment_name = "Kernel-__KLD";
- if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
- IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
- (int)segment_size);
- }
-#elif __i386__
- /* On x86, use the mapping data from the segment load command to
- * unload KLD and LINKEDIT directly, unless the keepsyms boot-arg
- * was enabled. This may invalidate any assumptions about
- * "avail_start" defining the lower bound for valid physical addresses.
- */
- if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize)
- ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize);
-#else
-#error arch
-#endif
-#if __ppc__
- dt_segment_name = "Kernel-__LINKEDIT";
- if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
- IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
- (int)segment_size);
- }
-#elif __i386__
- if (!keepsyms && segmentLE->vmaddr && segmentLE->vmsize)
- ml_static_mfree(segmentLE->vmaddr, segmentLE->vmsize);
-#else
-#error arch
-#endif
+/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
+ * without taking the OSKext lock. We use this to avoid the problem
+ * where taking the IOCatalog lock then the OSKext lock will dealock when
+ * a kext load or unload is happening at the same time as IOCatalog changing.
+ *
+ * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
+ * key set to the kext bundle ID and value set to an OSKext object
+ * theModuleDict - is an IOKit personality dictionary for a given module (kext)
+ */
+static bool
+isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
+ OSDictionary *theModuleDict)
+{
+ bool myResult = false;
+ const OSString * myBundleID = NULL;// do not release
+ OSKext * myKext = NULL; // do not release