]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOCatalogue.cpp
xnu-792.10.96.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
index 9f0552193981dcc044f8823522d232222996092d..2d05a9b4ae315a7262c383cdc7d2b23c48f04a2c 100644 (file)
@@ -1162,7 +1162,6 @@ bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
     return result;
 }
 
-
 /*********************************************************************
 * This function clears out all references to the in-kernel linker,
 * frees the list of startup extensions in extensionDict, and
@@ -1172,10 +1171,13 @@ bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
 *********************************************************************/
 kern_return_t IOCatalogue::removeKernelLinker(void) {
     kern_return_t result = KERN_SUCCESS;
-    struct segment_command * segment;
+    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.
     */
@@ -1190,6 +1192,8 @@ kern_return_t IOCatalogue::removeKernelLinker(void) {
         goto finish;
     }
 
+    PE_parse_boot_arg("keepsyms", &keepsyms);
     IOLog("Jettisoning kernel linker.\n");
 
     kernelLinkerPresent = 0;
@@ -1209,25 +1213,24 @@ kern_return_t IOCatalogue::removeKernelLinker(void) {
     * memory so that any cross-dependencies (not that there
     * should be any) are handled.
     */
-    segment = getsegbyname("__KLD");
-    if (!segment) {
+    segmentKLD = getsegbyname("__KLD");
+    if (!segmentKLD) {
         IOLog("error removing kernel linker: can't find %s segment\n",
             "__KLD");
         result = KERN_FAILURE;
         goto finish;
     }
-    OSRuntimeUnloadCPPForSegment(segment);
+    OSRuntimeUnloadCPPForSegment(segmentKLD);
 
-    segment = getsegbyname("__LINKEDIT");
-    if (!segment) {
+    segmentLE = getsegbyname("__LINKEDIT");
+    if (!segmentLE) {
         IOLog("error removing kernel linker: can't find %s segment\n",
             "__LINKEDIT");
         result = KERN_FAILURE;
         goto finish;
     }
-    OSRuntimeUnloadCPPForSegment(segment);
-
-
+    OSRuntimeUnloadCPPForSegment(segmentLE);
+#if __ppc__
    /* Free the memory that was set up by bootx.
     */
     dt_segment_name = "Kernel-__KLD";
@@ -1235,12 +1238,29 @@ kern_return_t IOCatalogue::removeKernelLinker(void) {
         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
 
     struct section * sect;
     sect = getsectbyname("__PRELINK", "__symtab");