return result;
}
-
/*********************************************************************
* This function clears out all references to the in-kernel linker,
* frees the list of startup extensions in extensionDict, and
*********************************************************************/
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.
*/
goto finish;
}
+ PE_parse_boot_arg("keepsyms", &keepsyms);
+
IOLog("Jettisoning kernel linker.\n");
kernelLinkerPresent = 0;
* 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";
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");