[Cbe-oss-dev] [PATCH] libspe2: Tweak extended __ea support
Alan Modra
amodra at bigpond.net.au
Mon May 12 14:47:57 EST 2008
This patch delays libspe relocation processing until after the image
has been copied to ld_buffer. The benefit in doing so is that only
relocations applied to the ._ea section need to be applied directly to
the image. Others that apply to loaded spu segments can be applied
to ld_buffer, which potentially saves memory since their ppu image
pages are not dirtied.
I've also fixed a bug in casting that could affect a 32-bit libspe
handling an -mea64 spu object. (Elf64_Xword)(long)start might result
in the high 32 bits being set to 1's due to sign extension. I don't
know whether this is a problem in practice, but it seems better to be
safe by keeping the high 32 bits zero in this case.
Signed-off-by: Alan Modra <amodra at bigpond.net.au>
--
Alan Modra
Australia Development Lab, IBM
diff -urp libspe2-2.2.80.old/spebase/elf_loader.c libspe2-2.2.80/spebase/elf_loader.c
--- libspe2-2.2.80.old/spebase/elf_loader.c 2008-04-12 17:03:43.000000000 +0930
+++ libspe2-2.2.80/spebase/elf_loader.c 2008-05-12 07:53:27.000000000 +0930
@@ -201,17 +201,26 @@ copy_to_ld_buffer(spe_program_handle_t *
without a symbol, which are to locations within ._ea. */
static void
-apply_relocations(spe_program_handle_t *handle, Elf32_Shdr *rh, Elf32_Shdr *sh)
+apply_relocations (spe_program_handle_t *handle,
+ void *buf,
+ Elf32_Shdr *rh,
+ Elf32_Shdr *sh,
+ Elf32_Shdr *eah)
{
#define R_SPU_PPU32 15
#define R_SPU_PPU64 16
void *start = handle->elf_image;
Elf32_Rela *r, *r_end;
- /* Relocations in an executable specify r_offset as a virtual
- address, but we are applying the reloc in the image before
- the section has been copied to its destination sh_addr.
- Adjust so as to poke relative to the image base. */
- void *reloc_base = start + sh->sh_offset - sh->sh_addr;
+ void *reloc_base = buf;
+
+ if (sh == eah)
+ {
+ /* Relocations in an executable specify r_offset as a
+ virtual address, but if we are applying relocs for
+ ._ea then the location we want is in the image.
+ Adjust so as to poke relative to the image base. */
+ reloc_base = start + sh->sh_offset - sh->sh_addr;
+ }
r = start + rh->sh_offset;
r_end = (void *)r + rh->sh_size;
@@ -219,15 +228,17 @@ apply_relocations(spe_program_handle_t *
for (; r < r_end; ++r)
{
if (r->r_info == ELF32_R_INFO(0,R_SPU_PPU32)) {
+ /* v is in ._ea */
Elf32_Word *loc = reloc_base + r->r_offset;
- Elf32_Word v = (Elf32_Word)(long)start + r->r_addend;
+ Elf32_Word v = (unsigned long)start + r->r_addend;
/* Don't dirty pages unnecessarily. */
if (*loc != v)
*loc = v;
DEBUG_PRINTF("PPU32(%p) = %#x\n", loc, v);
} else if (r->r_info == ELF32_R_INFO(0,R_SPU_PPU64)) {
+ /* v is in ._ea */
Elf64_Xword *loc = reloc_base + r->r_offset;
- Elf64_Xword v = (Elf64_Xword)(long)start + r->r_addend;
+ Elf64_Xword v = (unsigned long)start + r->r_addend;
if (*loc != v)
*loc = v;
DEBUG_PRINTF("PPU64(%p) = %#llx\n", loc, v);
@@ -244,6 +255,7 @@ _base_spe_load_spe_elf (spe_program_hand
Elf32_Shdr *shdr;
Elf32_Shdr *sh;
+ Elf32_Shdr *eah;
Elf32_Off toe_addr = 0;
long toe_size = 0;
@@ -272,17 +284,18 @@ _base_spe_load_spe_elf (spe_program_hand
/* traverse the sections to locate the toe segment */
/* by specification, the toe sections are grouped together in a segment */
+ eah = 0;
for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh)
{
DEBUG_PRINTF("section name: %s ( start: 0x%04x, size: 0x%04x)\n", str_table+sh->sh_name, sh->sh_offset, sh->sh_size );
- if (sh->sh_type == SHT_RELA)
- apply_relocations(handle, sh, &shdr[sh->sh_info]);
if (strcmp(".toe", str_table+sh->sh_name) == 0) {
DEBUG_PRINTF("section offset: %d\n", sh->sh_offset);
toe_size += sh->sh_size;
if ((toe_addr == 0) || (toe_addr > sh->sh_addr))
toe_addr = sh->sh_addr;
}
+ else if (strcmp("._ea", str_table+sh->sh_name) == 0)
+ eah = sh;
/* Disabled : Actually not needed, only good for testing
if (strcmp(".bss", str_table+sh->sh_name) == 0) {
DEBUG_PRINTF("zeroing .bss section:\n");
@@ -328,6 +341,12 @@ _base_spe_load_spe_elf (spe_program_hand
return -errno;
}
+ if (eah)
+ for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh)
+ if (sh->sh_type == SHT_RELA)
+ apply_relocations (handle, ld_buffer,
+ sh, &shdr[sh->sh_info], eah);
+
/* Remember where the code wants to be started */
ld_info->entry = ehdr->e_entry;
DEBUG_PRINTF ("entry = 0x%x\n", ehdr->e_entry);
More information about the cbe-oss-dev
mailing list