create.c 4.25 KB
/*==============================================================================
     create.c
     	create elf sections.
==============================================================================*/
#include <elf.h>
#include <libelf.h>
#include <sys/fcntl.h>
#include <string.h>
#include <compact_reloc.h>
#include <time.h>
#include <sym.h>
#include <malloc.h>

#include "global.h"
#include "update.h"
#include "const.h"
#include "proc.h"

static Elf_Scn     *xlate_section = (Elf_Scn *) NULL;
static Elf32_Shdr  *xlate_shdr32 = (Elf32_Shdr *) NULL;
static Elf64_Shdr  *xlate_shdr64 = (Elf64_Shdr *) NULL;

/*------------------------------------------------------------------------------
  Find the highest offset in elf sections.
------------------------------------------------------------------------------*/
Uint32 find_end_of_elf(Elf *elf)
{
    Elf_Scn     *section;
    Uint32	end = 0;
    int		i;

    for(i=1; (section = elf_getscn(elf,i)) != NULL; i++)
    {
	if (IS_64BIT())
	{
    	    Elf64_Shdr 	*shdr;
	    shdr = elf64_getshdr(section);
	    end = MAX(end, (shdr->sh_offset + shdr->sh_size));
	}
	else
	{
    	    Elf32_Shdr 	*shdr;
	    shdr = elf32_getshdr(section);
	    end = MAX(end, (shdr->sh_offset + shdr->sh_size));
	}
    }

    return end;
}


/*------------------------------------------------------------------------------
  Add a new section name to the .shstrtab section
------------------------------------------------------------------------------*/
int add_section_name(Elf *elf, char *name)
{
    Elf_Scn     *section;
    Elf_Data    *data;
    int		str_offset;
    char	*s;
    Uint32	length = strlen(name)+1;
    int 	i;

    if (IS_64BIT())
    {
        Elf64_Ehdr	*ehdr64;
        Elf64_Shdr 	*shdr64;

        ehdr64 = elf64_getehdr(elf);
        section = elf_getscn(elf, ehdr64->e_shstrndx);
    	shdr64 = elf64_getshdr(section);
    	shdr64->sh_size += length;
    }
    else
    {
        Elf32_Ehdr	*ehdr32;
        Elf32_Shdr 	*shdr32;

        ehdr32 = elf32_getehdr(elf);
        section = elf_getscn(elf, ehdr32->e_shstrndx);
    	shdr32 = elf32_getshdr(section);
    	shdr32->sh_size += length;
    }
    data = elf_getdata(section,0);

    /*------------------
      expand .strtab section
    ------------------*/
    data->d_buf = realloc(data->d_buf, data->d_size + length);
    strcpy(data->d_buf + data->d_size, name);
    str_offset = data->d_size;

    expand_section(section, length);

    return (str_offset);
}

/*------------------------------------------------------------------------------
  Create Xlate section
------------------------------------------------------------------------------*/
void create_xlate_section(void)
{
    int		str_offset;
    Elf		*elf = bin.new_elf;
    Uint32	end_of_elf;

    str_offset = add_section_name(elf, MIPS_XLATE);
	/* note, this has to be called after the new section string is
	   added and before the new xlate section is created */
    end_of_elf = find_end_of_elf(elf);
    xlate_section = elf_newscn(elf);

    if (IS_64BIT())
    {
    	xlate_shdr64 = elf64_getshdr(xlate_section);
    	xlate_shdr64->sh_name = str_offset;
    	xlate_shdr64->sh_type = SHT_MIPS_XLATE;
    	xlate_shdr64->sh_flags = 0;
    	xlate_shdr64->sh_offset = end_of_elf;
    	xlate_shdr64->sh_size = 0;
    	xlate_shdr64->sh_link = SHN_UNDEF;
    	xlate_shdr64->sh_info = 0;
    	xlate_shdr64->sh_addralign = 0x01;
    	xlate_shdr64->sh_entsize = 0;
    }
    else
    {
    	xlate_shdr32 = elf32_getshdr(xlate_section);
    	xlate_shdr32->sh_name = str_offset;
    	xlate_shdr32->sh_type = SHT_MIPS_XLATE;
    	xlate_shdr32->sh_flags = 0;
    	xlate_shdr32->sh_offset = end_of_elf;
    	xlate_shdr32->sh_size = 0;
    	xlate_shdr32->sh_link = SHN_UNDEF;
    	xlate_shdr32->sh_info = 0;
    	xlate_shdr32->sh_addralign = 0x01;
    	xlate_shdr32->sh_entsize = 0;
    }
}

/*------------------------------------------------------------------------------
  Create Xlate section
------------------------------------------------------------------------------*/
void add_xlate_data(void *data_buf, Uint32 data_size)
{
    Elf_Data    *data;

    data = elf_newdata(xlate_section);
    data->d_buf = data_buf;
    data->d_size = data_size;
    if (IS_64BIT())
    {
	xlate_shdr64->sh_size += data_size;
    }
    else
    {
	xlate_shdr32->sh_size += data_size;
    }
}