libspe2: Respect PF_OVERLAY flag

Message ID 1241439888.3901.10.camel@localhost
State New
Headers show

Commit Message

D. Herrendoerfer May 4, 2009, 12:24 p.m.
There is a bug in the libspe2 elf loader that prevents it from correctly
loading overlay segments. This was brought up by Ulrich Weigand.
Here is the Bug description:

spebase/elf_loader.c contains a routine "overlay" that attempts to determine
whether a PT_LOAD segment represents an overlay that is not supposed to be
loader.  However, caller of overlay always passes in a prev_ph argument of
NULL, causing overlay to always return 0.

This causes all PT_LOAD segments to be loaded, regardless of whether or not
they are overlay segments.  This causes unnecessary loads to be performed.  In
addition, if the linker has designated one segment as "overlay init", i.e.
pre-loaded contents of the overlay buffer, the ELF loader does not reliably
ensure that the overlay init segment is the one that's present after load.

The proper identification of overlay segments should use the PF_OVERLAY p_flags
bit that the linker sets to indicate PT_LOAD segments that should not be

The following patch fixed this bug.

Signed-off-by: D.Herrendoerfer <herrend [at] de [dot] ibm [dot] com>


Index: libspe2/spebase/elf_loader.c
--- libspe2/spebase/elf_loader.c	(revision 136)
+++ libspe2/spebase/elf_loader.c	(working copy)
@@ -33,6 +33,10 @@ 
 #include "elf_loader.h"
 #include "spebase.h"
+#ifndef PF_OVERLAY
+#define PF_OVERLAY (1 << 27)
 #ifdef DEBUG
 static void display_debug_output(Elf32_Ehdr *elf_start, Elf32_Shdr *sh);
 #endif /*DEBUG*/
@@ -153,20 +157,6 @@  _base_spe_parse_isolated_elf(spe_program
 	return 0;
-static int
-overlay(Elf32_Phdr *ph, Elf32_Phdr *prev_ph)
-	/*
-	 * If our ph segment virtual address fits within that of the
-	 * previous ph, this is an overlay.
-	 */
-	if (prev_ph && (ph->p_vaddr >= prev_ph->p_vaddr) &&
-	    (ph->p_vaddr < (prev_ph->p_vaddr + prev_ph->p_memsz)))
-		return 1;
-	else
-		return 0;
 static void
 copy_to_ld_buffer(spe_program_handle_t *handle, void *buffer, Elf32_Phdr
 		  *ph, Elf32_Off toe_addr, long toe_size)
@@ -242,7 +232,7 @@  _base_spe_load_spe_elf (spe_program_hand
 	Elf32_Ehdr *ehdr;
 	Elf32_Phdr *phdr;
-	Elf32_Phdr *ph, *prev_ph;
+	Elf32_Phdr *ph;
 	Elf32_Shdr *shdr;
 	Elf32_Shdr *sh;
@@ -303,10 +293,10 @@  _base_spe_load_spe_elf (spe_program_hand
 	 * Load all PT_LOAD segments onto the SPE local store buffer.
 	DEBUG_PRINTF("Segments: 0x%x\n", ehdr->e_phnum);
-	for (ph = phdr, prev_ph = NULL; ph < &phdr[ehdr->e_phnum]; ++ph) {
+	for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph) {
 		switch (ph->p_type) {
 		case PT_LOAD:
-			if (!overlay(ph, prev_ph)) {
+			if (!(ph->p_flags & PF_OVERLAY)) {
 				if (ph->p_filesz < ph->p_memsz) {
 					DEBUG_PRINTF("padding loaded image with zeros:\n");
 					DEBUG_PRINTF("start: 0x%04x\n", ph->p_vaddr + ph->p_filesz);