Author: bonefish Date: 2010-07-06 23:47:08 +0200 (Tue, 06 Jul 2010) New Revision: 37415 Changeset: http://dev.haiku-os.org/changeset/37415/haiku Modified: haiku/trunk/headers/private/system/elf32.h haiku/trunk/src/system/kernel/elf.cpp Log: Patch by Lucian Adrian Grijincu: Added support for loading kernel modules with only a single readable/writable/executable text+data segment. Modified: haiku/trunk/headers/private/system/elf32.h =================================================================== --- haiku/trunk/headers/private/system/elf32.h 2010-07-06 21:31:04 UTC (rev 37414) +++ haiku/trunk/headers/private/system/elf32.h 2010-07-06 21:47:08 UTC (rev 37415) @@ -367,7 +367,7 @@ inline bool Elf32_Phdr::IsExecutable() const { - return (p_flags & PF_PROTECTION_MASK) == (PF_READ | PF_EXECUTE); + return (p_flags & PF_EXECUTE) != 0; } Modified: haiku/trunk/src/system/kernel/elf.cpp =================================================================== --- haiku/trunk/src/system/kernel/elf.cpp 2010-07-06 21:31:04 UTC (rev 37414) +++ haiku/trunk/src/system/kernel/elf.cpp 2010-07-06 21:47:08 UTC (rev 37415) @@ -1965,6 +1965,8 @@ size_t reservedSize; status_t status; ssize_t length; + bool textSectionWritable = false; + int executableHeaderCount = 0; TRACE(("elf_load_kspace: entry path '%s'\n", path)); @@ -2066,6 +2068,9 @@ B_PAGE_SIZE); if (end > reservedSize) reservedSize = end; + + if (programHeaders[i].IsExecutable()) + executableHeaderCount++; } // Check whether the segments have an unreasonable amount of unused space @@ -2105,7 +2110,16 @@ } // we're here, so it must be a PT_LOAD segment - if (programHeaders[i].IsReadWrite()) { + + // Usually add-ons have two PT_LOAD headers: one for .data one or .text. + // x86 and PPC may differ in permission bits for .data's PT_LOAD header + // x86 is usually RW, PPC is RWE + + // Some add-ons may have .text and .data concatenated in a single + // PT_LOAD RWE header and we must map that to .text. + if (programHeaders[i].IsReadWrite() + && (!programHeaders[i].IsExecutable() + || executableHeaderCount > 1)) { // this is the writable segment if (image->data_region.size != 0) { // we've already created this segment @@ -2122,6 +2136,9 @@ } region = &image->text_region; + // some programs may have .text and .data concatenated in a + // single PT_LOAD section which is readable/writable/executable + textSectionWritable = programHeaders[i].IsReadWrite(); snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName); } else { dprintf("%s: weird program header flags 0x%lx\n", fileName, @@ -2191,9 +2208,12 @@ goto error5; // We needed to read in the contents of the "text" area, but - // now we can protect it read-only/execute + // now we can protect it read-only/execute, unless this is a + // special image with concatenated .text and .data, when it + // will also need write access. set_area_protection(image->text_region.id, - B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA); + B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA + | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0)); // There might be a hole between the two segments, and we don't need to // reserve this any longer