This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] SPU i-cache: Work around broken SPU ELF loader


Hello,

it turns out the SPU ELF loader in libspe2 completely ignores overlays.
It ignores the PF_OVERLAY flag, and while there is code attempting to
detect VMA overlap, this code is broken and never triggers.  The effect
is that the loader will always load all PT_LOAD segments, including overlays.
This happens to work with the old overlay scheme because nobody actually
cared about the contents of the overlay buffers on startup.   However, with
software icache, we rely on having the .ovl.init section present there.

Clearly, this needs to be fixed in libspe2.  And in fact, a patch to make
the ELF loader properly respect the PF_OVERLAY flag is already available
and should be upstream shortly.  However, the libspe2 in the existing
Linux distributions has the bug, so a work-around allowing use of icache
binaries without forcing an update of system package would be preferable.

The following patch implements such a work-around by simply ensuring that
all PF_OVERLAY segment are listed first amonst the program headers.  For a
(future) correct ELF loader, that doesn't matter either way, as the
PF_OVERLAY segments would be ignored no matter what.  But the current
broken loader will simply go though the program headers in order and
load segments; therefore, this change ensures the segment containing
.ovl.init will be loaded *last* and thus be present in local store on startup.

Tested on spu-elf with no regressions.
Approved off-line by Alan Modra; committed to mainline.

Bye,
Ulrich


ChangeLog:

bfd/
	* elf32-spu.c (spu_elf_modify_segment_map): Move all PF_OVERLAY
	segments first amongst the program headers.
ld/
	* testsuite/ld-spu/icache.d: Update file offsets.
	* testsuite/ld-spu/ovl.d: Likewise.
	* testsuite/ld-spu/ovl1.d: Likewise.

diff -urNp src.orig/bfd/elf32-spu.c src/bfd/elf32-spu.c
--- src.orig/bfd/elf32-spu.c	2009-05-13 15:07:51.000000000 +0200
+++ src/bfd/elf32-spu.c	2009-05-13 15:08:03.000000000 +0200
@@ -5045,7 +5045,8 @@ static bfd_boolean
 spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
 {
   asection *toe, *s;
-  struct elf_segment_map *m;
+  struct elf_segment_map *m, *m_overlay;
+  struct elf_segment_map **p, **p_overlay;
   unsigned int i;
 
   if (info == NULL)
@@ -5092,6 +5093,37 @@ spu_elf_modify_segment_map (bfd *abfd, s
 	    break;
 	  }
 
+
+  /* Some SPU ELF loaders ignore the PF_OVERLAY flag and just load all
+     PT_LOAD segments.  This can cause the .ovl.init section to be
+     overwritten with the contents of some overlay segment.  To work
+     around this issue, we ensure that all PF_OVERLAY segments are
+     sorted first amongst the program headers; this ensures that even
+     with a broken loader, the .ovl.init section (which is not marked
+     as PF_OVERLAY) will be placed into SPU local store on startup.  */
+
+  /* Move all overlay segments onto a separate list.  */
+  p = &elf_tdata (abfd)->segment_map;
+  p_overlay = &m_overlay;
+  while (*p != NULL)
+    {
+      if ((*p)->p_type == PT_LOAD && (*p)->count == 1
+	  && spu_elf_section_data ((*p)->sections[0])->u.o.ovl_index != 0)
+	{
+	  struct elf_segment_map *m = *p;
+	  *p = m->next;
+	  *p_overlay = m;
+	  p_overlay = &m->next;
+	  continue;
+	}
+
+      p = &((*p)->next);
+    }
+
+  /* Re-insert overlay segments at the head of the segment map.  */
+  *p_overlay = elf_tdata (abfd)->segment_map;
+  elf_tdata (abfd)->segment_map = m_overlay;
+
   return TRUE;
 }
 
diff -u -p -r1.4 icache1.d
--- src.orig/ld/testsuite/ld-spu/icache1.d	14 May 2009 04:30:02 -0000	1.4
+++ src/ld/testsuite/ld-spu/icache1.d	14 May 2009 14:54:24 -0000
@@ -8,7 +8,7 @@
 Disassembly of section .ovl.init:
 00000800 <__icache_fileoff>:
 .*	00 00 00 00.*
-.*	00 00 07 00.*
+.*	00 00 02 00.*
 	\.\.\.
 
 Disassembly of section \.ovly1:
diff -u -p -r1.10 ovl.d
--- src.orig/ld/testsuite/ld-spu/ovl.d	14 May 2009 04:30:03 -0000	1.10
+++ src/ld/testsuite/ld-spu/ovl.d	14 May 2009 14:54:24 -0000
@@ -151,12 +151,12 @@ Disassembly of section .data:
  450:	00 00 04 00 .*
  454:	00 00 00 20 .*
 # 458:	00 00 03 40 .*
- 458:	00 00 03 90 .*
+ 458:	00 00 01 00 .*
  45c:	00 00 00 01 .*
  460:	00 00 04 00 .*
  464:	00 00 00 40 .*
 # 468:	00 00 03 60 .*
- 468:	00 00 03 b0 .*
+ 468:	00 00 01 20 .*
  46c:	00 00 00 01 .*
 
 00000470 <_ovly_buf_table>:
diff -u -p -r1.12 ovl2.d
--- src.orig/ld/testsuite/ld-spu/ovl2.d	14 May 2009 04:30:03 -0000	1.12
+++ src/ld/testsuite/ld-spu/ovl2.d	14 May 2009 14:54:24 -0000
@@ -104,12 +104,12 @@ Disassembly of section \.data:
 .*00 00 04 00 .*
 .*00 00 00 20 .*
 #.*00 00 03 10 .*
-.*00 00 03 60 .*
+.*00 00 01 00 .*
 .*00 00 00 01 .*
 .*00 00 04 00 .*
 .*00 00 00 20 .*
 #.*00 00 03 20 .*
-.*00 00 03 80 .*
+.*00 00 01 20 .*
 .*00 00 00 01 .*
 
 00000450 <_ovly_buf_table>:
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]