All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Macros | Functions
elf_loader.c File Reference
#include <elf.h>
#include <task.h>
#include <secure_api.h>
#include <sw_debug.h>
#include <otz_id.h>
#include <fat32.h>
#include <page_table.h>
#include <dispatcher_task.h>
#include <sw_string_functions.h>
#include <sw_mem_functions.h>
#include <mem_mng.h>
#include <sw_list.h>
#include <cpu_data.h>
#include <sw_types.h>
#include <elf_loader_app.h>
#include <elf_loader.h>
#include <sw_board.h>

Go to the source code of this file.

Macros

#define __KSYMTAB_ADDR   ((va_t *)&_SW_KSYMTAB)
 

Functions

int elf_loader_cleanup (void)
 clean up function to remove the mappings
 
int get_number_of_loadable_segments (int fp, Elf32_Ehdr *elf_header, Elf32_Phdr **phdr_tab)
 Gets the number of loadable segments, ie segments with type PT_LOAD.
 
int elf_load (struct sa_config_t *conf)
 the main elf loader function
 

Macro Definition Documentation

#define __KSYMTAB_ADDR   ((va_t *)&_SW_KSYMTAB)

Definition at line 48 of file elf_loader.c.

Function Documentation

int elf_load ( struct sa_config_t conf)

the main elf loader function

The main loader function which will be called by the __elf_load() syscall, has functionality for handling both relocatable files and executable files, although executable file support is not required as of now, so control doesn't go to the executable file part of the function.

Parameters
conf: configuration parameter for the task
Returns
0 on success, -1 on failure

Definition at line 678 of file elf_loader.c.

{
Elf32_Ehdr elf_header;
Elf32_Ehdr *tmp_ehdr;
u32 rel = 0;
u32 num_bytes = 0,va_offset,status;
int num_of_segments,fp = -1,ret = OTZ_OK,mode = FILE_READ;
u32 *flag = NULL,*base_va = NULL;
u32 offset,leftover_size, num_of_loadable_segments = 0;
Elf32_Phdr *phdr_table = NULL, *tmp_phdr = NULL;
char *leftover_data = NULL;
conf->elf_flag = -1;
ret = init_map_loader(conf);
if(ret != 0)
{
sw_printf("Mapping PA to VA failed\n");
ret = -1;
goto out;
}
fp = file_open(conf->file_path,mode);
if(fp == -1){
sw_printf("unable to open file\n");
ret =- 1;
goto out;
}
rel = validate_elf_header(fp,&elf_header);
tmp_ehdr = &elf_header;
if(rel == 1){
status = relocate_elf_loader(fp,tmp_ehdr,conf);
/* We dont care about whatever be the status here, because we need to clean up
* the elf_loader task irrespective of the result */
ret = status;
if(status == -1 || status == 0)
goto out;
}
if(rel == -1 ){
ret = -1;
goto out;
}
/* Here we are dealing with a executable...right now the executable
* support is not required.. */
goto out;
conf->entry_point = elf_header.e_entry;
num_of_loadable_segments = get_number_of_loadable_segments(fp,
&elf_header,&phdr_table);
if(num_of_loadable_segments == -1){
ret =- 1;
goto out;
}
tmp_phdr = phdr_table;
/* array of u32 entries whose total number equals number_of_loadable_segments */
flag = sw_malloc(num_of_loadable_segments * sizeof(u32) );
if(flag == NULL){
sw_printf("No memory available\n");
ret =- 1;
goto out;
}
sw_memset(flag,0x0,num_of_loadable_segments * sizeof(u32));
for(num_of_segments = 0;num_of_segments < elf_header.e_phnum;
num_of_segments++){
if(tmp_phdr->p_type == PT_LOAD)
{
/* we need to check if the segment contains the .bss section
* in which p_filesz < p_memsz */
if(tmp_phdr->p_filesz == tmp_phdr->p_memsz)
{
va_offset = tmp_phdr->p_vaddr;
offset = tmp_phdr->p_offset;
num_bytes = 0;
num_bytes = file_read(fp,((char *)base_va
+ va_offset ),
tmp_phdr->p_filesz);
if(num_bytes != tmp_phdr->p_filesz){
sw_printf("Reading segment failed\n");
ret = -1;
goto out;
}
}
else if (tmp_phdr->p_filesz < tmp_phdr->p_memsz){
va_offset = tmp_phdr->p_vaddr;
offset = tmp_phdr->p_offset;
num_bytes = 0;
num_bytes = file_read(fp,((char *)base_va +
va_offset),
tmp_phdr->p_filesz);
if(num_bytes != tmp_phdr->p_filesz){
sw_printf("Reading segment failed\n");
ret = -1;
goto out;
}
leftover_size = (tmp_phdr->p_memsz -
tmp_phdr->p_filesz + 1);
leftover_data = (char *)sw_malloc(
tmp_phdr->p_memsz -
tmp_phdr->p_filesz+ 1);
sw_memset(leftover_data,0x0,(tmp_phdr->p_memsz -
tmp_phdr->p_filesz + 1));
sw_memcpy(base_va,leftover_data,leftover_size);
sw_malloc_free(leftover_data);
}
}
tmp_phdr = ( Elf32_Phdr *)((char *)tmp_phdr +
elf_header.e_phentsize);
}
/* TODO:
1) Also, Add support for dynamic linking (Not needed for now )
*/
out:
/* Free the allocated memory and resources here */
if(phdr_table){
tmp_phdr = phdr_table;
for(num_of_segments = 0,num_of_loadable_segments = 0;
num_of_segments < elf_header.e_phnum;
num_of_segments++){
if(tmp_phdr->p_type == PT_LOAD){
if(!flag[num_of_loadable_segments]){
sw_vir_addr_free(((u32)base_va +
tmp_phdr->p_vaddr),
tmp_phdr->p_memsz );
}
num_of_loadable_segments++;
}
tmp_phdr = ( Elf32_Phdr *)((char *)tmp_phdr +
elf_header.e_phentsize);
}
sw_malloc_free(phdr_table);
}
if(fp != -1){
}
return ret;
}
int elf_loader_cleanup ( void  )

clean up function to remove the mappings

cleans up the reserved secure memory region

Parameters
psa_config
Returns
0 on success , -1 on failure

Definition at line 84 of file elf_loader.c.

{
int status = 0;
/* 0 indicates that the mapping is successful, so do the cleanup */
if (status == -1){
sw_printf("Unable to unmap secure memory of elf loader\n");
return -1;
}
return status;
}
int get_number_of_loadable_segments ( int  fp,
Elf32_Ehdr elf_header,
Elf32_Phdr **  phdr_tab 
)

Gets the number of loadable segments, ie segments with type PT_LOAD.

Parameters
fp
elf_header
phdr_tab: pointer to the program header table
Returns
number of loadable segments on success, -1 on failure

Definition at line 629 of file elf_loader.c.

{
int ph_num,num_bytes,num_of_segments,num_of_loadable_segments = 0;
Elf32_Phdr *phdr_table, *tmp_phdr;
ph_num = elf_header->e_phnum;
phdr_table = (Elf32_Phdr *)sw_malloc(ph_num * sizeof( Elf32_Phdr));
if(phdr_table == NULL){
sw_printf("No memory available\n");
return -1;
}
num_bytes = 0;
num_bytes = file_read(fp,(char *)phdr_table,
(ph_num * sizeof(Elf32_Phdr)));
if (num_bytes != (ph_num * sizeof( Elf32_Phdr))){
sw_printf("Reading Programheader table from ELF file failed\n");
return -1;
}
/* Get the number of PT_LOAD segments */
tmp_phdr = phdr_table;
for(num_of_segments = 0;num_of_segments < elf_header->e_phnum;
num_of_segments++) {
if(tmp_phdr->p_type == PT_LOAD)
num_of_loadable_segments++;
tmp_phdr = ( Elf32_Phdr *)((char *)tmp_phdr +
elf_header->e_phentsize);
}
*phdr_tab = phdr_table;
return num_of_loadable_segments;
}