libspe2 0.9a
Data Structures | Defines | Functions
elf_loader.h File Reference
#include "spebase.h"
#include <elf.h>
Include dependency graph for elf_loader.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  addr64
struct  spe_ld_info

Defines

#define LS_SIZE   0x40000
#define SPE_LDR_PROG_start   (LS_SIZE - 512)
#define SPE_LDR_PARAMS_start   (LS_SIZE - 128)

Functions

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

Define Documentation

#define LS_SIZE   0x40000
#define SPE_LDR_PARAMS_start   (LS_SIZE - 128)

Definition at line 26 of file elf_loader.h.

#define SPE_LDR_PROG_start   (LS_SIZE - 512)

Definition at line 25 of file elf_loader.h.


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);
}