elf_loader.c File Reference
`#include <elf.h>`
`#include <errno.h>`
`#include <fcntl.h>`
`#include <malloc.h>`
`#include <stdlib.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include <unistd.h>`
`#include <sys/mman.h>`
`#include <sys/types.h>`
`#include <sys/stat.h>`
`#include "elf_loader.h"`
`#include "spebase.h"`
Include dependency graph for elf_loader.c:

Go to the source code of this file.

## Macros

#define | __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); }
#define | DEBUG_PRINTF(fmt, args...)
#define | TAG

## Functions

int | _base_spe_verify_spe_elf_image (spe_program_handle_t *handle)
int | _base_spe_parse_isolated_elf (spe_program_handle_t *handle, uint64_t *addr, uint32_t *size)
int | _base_spe_load_spe_elf (spe_program_handle_t *handle, void *ld_buffer, struct spe_ld_info *ld_info)
int | _base_spe_toe_ear (spe_program_handle_t *speh)

## Macro Definition Documentation

#define __PRINTF | ( |  | fmt,
|  |  | args...
| ) |  | { fprintf(stderr,fmt , ## args); }

Definition at line 40 of file elf_loader.c.

#define DEBUG_PRINTF | ( |  | fmt,
|  |  | args...
| ) |  |

Definition at line 45 of file elf_loader.c.

Referenced by _base_spe_context_create(), _base_spe_context_run(), _base_spe_count_physical_cpus(), _base_spe_count_physical_spes(), _base_spe_gang_context_create(), _base_spe_handle_library_callback(), _base_spe_load_spe_elf(), _base_spe_out_mbox_read(), _base_spe_parse_isolated_elf(), _base_spe_program_load(), and _base_spe_program_load_complete().

#define TAG

Definition at line 46 of file elf_loader.c.

## Function Documentation

int _base_spe_load_spe_elf | ( | spe_program_handle_t * | handle,
|  | void * | ld_buffer,
|  | struct spe_ld_info * | ld_info
| ) |  |

Definition at line 201 of file elf_loader.c.

References DEBUG_PRINTF, spe_program_handle::elf_image, and spe_ld_info::entry.

Referenced by _base_spe_program_load().

{
Elf32_Ehdr *ehdr;
Elf32_Phdr *phdr;
Elf32_Phdr *ph, *prev_ph;
Elf32_Shdr *shdr;
Elf32_Shdr *sh;
Elf32_Off toe_addr = 0;
long toe_size = 0;
char* str_table = 0;
int num_load_seg = 0;
void *elf_start;
int ret;
DEBUG_PRINTF ("load_spe_elf(%p, %p)\n", handle, ld_buffer);
elf_start = handle->elf_image;
DEBUG_PRINTF ("load_spe_elf(%p, %p)\n", handle->elf_image, ld_buffer);
ehdr = (Elf32_Ehdr *)(handle->elf_image);
/* Check for a Valid SPE ELF Image (again) */
if ((ret=check_spe_elf(ehdr)))
return ret;
/* Start processing headers */
phdr = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff);
shdr = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
/* traverse the sections to locate the toe segment */
/* by specification, the toe sections are grouped together in a segment */
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 (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;
}
/* Disabled : Actually not needed, only good for testing
if (strcmp(".bss", str_table+sh->sh_name) == 0) {
DEBUG_PRINTF("zeroing .bss section:\n");
DEBUG_PRINTF("section offset: 0x%04x\n", sh->sh_offset);
DEBUG_PRINTF("section size: 0x%04x\n", sh->sh_size);
memset(ld_buffer + sh->sh_offset, 0, sh->sh_size);
} */
#ifdef DEBUG
if (strcmp(".note.spu_name", str_table+sh->sh_name) == 0)
display_debug_output(elf_start, sh);
#endif /*DEBUG*/
}
/*
* 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) {
switch (ph->p_type) {
case PT_LOAD:
if (!overlay(ph, prev_ph)) {
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);
DEBUG_PRINTF("length: 0x%04x\n", ph->p_memsz - ph->p_filesz);
memset(ld_buffer + ph->p_vaddr + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
}
copy_to_ld_buffer(handle, ld_buffer, ph,
toe_addr, toe_size);
num_load_seg++;
}
break;
case PT_NOTE:
DEBUG_PRINTF("SPE_LOAD found PT_NOTE\n");
break;
}
}
if (num_load_seg == 0)
{
DEBUG_PRINTF ("no segments to load");
errno = EINVAL;
return -errno;
}
/* Remember where the code wants to be started */
ld_info->entry = ehdr->e_entry;
DEBUG_PRINTF ("entry = 0x%x\n", ehdr->e_entry);
return 0;
}

int _base_spe_parse_isolated_elf | ( | spe_program_handle_t * | handle,
|  | uint64_t * | addr,
|  | uint32_t * | size
| ) |  |

Definition at line 111 of file elf_loader.c.

References DEBUG_PRINTF, and spe_program_handle::elf_image.

{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image;
Elf32_Phdr *phdr;
if (!ehdr) {
DEBUG_PRINTF("No ELF image has been loaded\n");
errno = EINVAL;
return -errno;
}
if (ehdr->e_phentsize != sizeof(*phdr)) {
DEBUG_PRINTF("Invalid program header format (phdr size=%d)\n",
ehdr->e_phentsize);
errno = EINVAL;
return -errno;
}
if (ehdr->e_phnum != 1) {
DEBUG_PRINTF("Invalid program header count (%d), expected 1\n",
ehdr->e_phnum);
errno = EINVAL;
return -errno;
}
phdr = (Elf32_Phdr *)(handle->elf_image + ehdr->e_phoff);
if (phdr->p_type != PT_LOAD || phdr->p_memsz == 0) {
DEBUG_PRINTF("SPE program segment is not loadable (type=%x)\n",
phdr->p_type);
errno = EINVAL;
return -errno;
}
if (addr)
*addr = (uint64_t)(unsigned long)
(handle->elf_image + phdr->p_offset);
if (size)
*size = phdr->p_memsz;
return 0;
}

int _base_spe_toe_ear | ( | spe_program_handle_t * | speh) |  |

Definition at line 354 of file elf_loader.c.

References spe_program_handle::elf_image, and spe_program_handle::toe_shadow.

Referenced by _base_spe_image_open().

{
Elf32_Ehdr *ehdr;
Elf32_Shdr *shdr, *sh;
char *str_table;
char **ch;
int ret;
long toe_size;
ehdr = (Elf32_Ehdr*) (speh->elf_image);
shdr = (Elf32_Shdr*) ((char*) ehdr + ehdr->e_shoff);
str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
toe_size = 0;
for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh)
if (strcmp(".toe", str_table + sh->sh_name) == 0)
toe_size += sh->sh_size;
ret = 0;
if (toe_size > 0) {
for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh)
if (sh->sh_type == SHT_SYMTAB || sh->sh_type ==
SHT_DYNSYM)
ret = toe_check_syms(ehdr, sh);
if (!ret && toe_size != 16) {
/* Paranoia */
fprintf(stderr, "Unexpected toe size of %ld\n",
toe_size);
errno = EINVAL;
ret = 1;
}
}
if (!ret && toe_size) {
/*
* Allocate toe_shadow, and fill it with elf_image.
*/
speh->toe_shadow = malloc(toe_size);
if (speh->toe_shadow) {
ch = (char**) speh->toe_shadow;
if (sizeof(char*) == 8) {
ch[0] = (char*) speh->elf_image;
ch[1] = 0;
} else {
ch[0] = 0;
ch[1] = (char*) speh->elf_image;
ch[2] = 0;
ch[3] = 0;
}
} else {
errno = ENOMEM;
ret = 1;
}
}
return ret;
}

int _base_spe_verify_spe_elf_image | ( | spe_program_handle_t * | handle) |  |

verifies integrity of an SPE image

Definition at line 99 of file elf_loader.c.

References spe_program_handle::elf_image.

Referenced by _base_spe_emulated_loader_present(), and _base_spe_image_open().

{
Elf32_Ehdr *ehdr;
void *elf_start;
elf_start = handle->elf_image;
ehdr = (Elf32_Ehdr *)(handle->elf_image);
return check_spe_elf(ehdr);
}