read.c 5.3 KB
/*==============================================================================
    Module: read.c
    $Revision: 1.1.1.2 $
    $Date: 2002/10/29 08:07:15 $
    $Author: blythe $
    $Source: /root/leakn64/depot/rf/sw/bbplayer/tools/gcord/com/read.c,v $
==============================================================================*/
#include <libelf.h>
#include <stdlib.h>
#include <fcntl.h>

#include "global.h"
#include "option.h"
#include "mdebug.h"
#include "update.h"

/*------------------------------------------------------------------------------
    copy 32 bit elf header to 64 bit so that we can use the same 64 bit 
    header data format in the program
------------------------------------------------------------------------------*/
Elf64_Ehdr *copy_elf_header_to64(Elf32_Ehdr *ehdr32)
{
    Elf64_Ehdr  *ehdr64;
    int i;

    ehdr64 = (Elf64_Ehdr *) malloc(sizeof(Elf64_Ehdr));

    for (i =0 ; i< EI_NIDENT; i++)
        ehdr64->e_ident[i] = ehdr32->e_ident[i];
    ehdr64->e_type =    (Elf64_Half) ehdr32->e_type;
    ehdr64->e_machine = (Elf64_Half) ehdr32->e_machine;
    ehdr64->e_version = (Elf64_Word) ehdr32->e_version;
    ehdr64->e_entry =   (Elf64_Addr) ehdr32->e_entry;
    ehdr64->e_phoff =   (Elf64_Off) ehdr32->e_phoff;
    ehdr64->e_shoff =   (Elf64_Off) ehdr32->e_shoff;
    ehdr64->e_flags =   (Elf64_Word) ehdr32->e_flags;
    ehdr64->e_ehsize =  (Elf64_Half) ehdr32->e_ehsize;
    ehdr64->e_phentsize = (Elf64_Half) ehdr32->e_phentsize;
    ehdr64->e_phnum =   (Elf64_Half) ehdr32->e_phnum;
    ehdr64->e_shentsize = (Elf64_Half) ehdr32->e_shentsize;
    ehdr64->e_shnum =   (Elf64_Half) ehdr32->e_shnum;
    ehdr64->e_shstrndx = (Elf64_Half) ehdr32->e_shstrndx;

    return ehdr64;
}

/*------------------------------------------------------------------------------
    copy 32 bit elf section header to 64 bit so that we can use the same 64 bit 
    header data format in the program
------------------------------------------------------------------------------*/
void copy_section_header_to64(Elf32_Shdr *shdr32, Elf64_Shdr *shdr64)
{
    shdr64->sh_name = (Elf64_Word) shdr32->sh_name;
    shdr64->sh_type = (Elf64_Word) shdr32->sh_type;
    shdr64->sh_flags = (Elf64_Xword) shdr32->sh_flags;
    shdr64->sh_addr = (Elf64_Addr) shdr32->sh_addr;
    shdr64->sh_offset = (Elf64_Off) shdr32->sh_offset;
    shdr64->sh_size = (Elf64_Xword) shdr32->sh_size;
    shdr64->sh_link = (Elf64_Word) shdr32->sh_link;
    shdr64->sh_info = (Elf64_Word) shdr32->sh_info;
    shdr64->sh_addralign = (Elf64_Xword) shdr32->sh_addralign;
    shdr64->sh_entsize = (Elf64_Xword) shdr32->sh_entsize;
}

/*------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
void debug_interface(void)
{
    if (bin.debug_type == DWARF)
        dwarf_interface(bin.elf);
    else 
    if (bin.debug_type == MDEBUG)
	mdebug_interface(bin.elf);
    else
	error("%s stripped. No debug section", option.in_file);

    if (option.debug & DEBUG_PROC)
	dump_procs();
}

/*------------------------------------------------------------------------------
  read the binary using libelf
------------------------------------------------------------------------------*/
void read_orig_binary(void)
{
    Elf         *elf;
    Elf64_Ehdr  *ehdr64;
    Elf_Scn     *section;
    Elf_Data    *data;

    char        *shstrtab;
    int 	fd = -1;
    int 	i;

    /*------------------
	open binary
    ------------------*/
    if((fd = open(option.in_file, O_RDONLY)) <= 0)
	sysfatal("cannot open %s", option.in_file);

    bin.fd_in = fd;
    elf_version(EV_CURRENT);
    elf = bin.elf = elf_begin(fd, ELF_C_READ, (Elf *) NULL);
    

	/* check for errors */
    if (!elf) 
	error("cannot open %s", option.in_file);
    switch (elf_kind(elf))
    {
        case ELF_K_NONE:
            error("unknown object format in %s", option.in_file);
	    break;
        case ELF_K_COFF:
            error("coff object not handled %s", option.in_file);
	    break;
    }

    /*------------------
	check 32/64 bit, copy elf header to 64 bit.
    ------------------*/
    {
        Elf32_Ehdr  *ehdr32;

	if (ehdr64 = elf64_getehdr(elf))
	{
	    bin.bit = BIT64;
	}
	else if (ehdr32 = elf32_getehdr(elf))
	{
	    bin.bit = BIT32;
	    ehdr64 = copy_elf_header_to64(ehdr32);
	}
	else
	    error("unknown binary");
    }

    if (ehdr64->e_flags & EF_MIPS_ABI2)
	bin.abi = ABI2;
    else
	bin.abi = ABI1;

    /*------------------
        look at ELF Header
    ------------------*/
    if (ehdr64->e_flags & EF_MIPS_PIC)
        bin.type = PIC;
    else if (ehdr64->e_flags & EF_MIPS_CPIC)
        bin.type = CPIC;
    else
        bin.type = NON_SHARED;

    section = elf_getscn(elf, ehdr64->e_shstrndx);
    data =  elf_getdata(section, 0);
    shstrtab = data->d_buf;

    bin.pixie_addrs_base = ~0;
    bin.broad_text_lo = ~0;
    bin.broad_text_hi = 0;
    bin.gp_value = 0;
    bin.text_expand_size = 0; 
    bin.text_expand_offset = 0;

    bin.entry = ehdr64->e_entry;    /* program entry point */


    if (option.debug)
    {
	dump(".text[%#llx - %#llx] text[%#llx - %#llx]", 
	    (Uint64) bin.text_lo, (Uint64) bin.text_hi,
	    (Uint64) bin.broad_text_lo, (Uint64) bin.broad_text_hi);
	dump("gp_value %#llx",(Uint64) bin.gp_value);
    }

    bin.pixie_addrs_base = MIN(bin.pixie_addrs_base, bin.text_lo);

    mdebug_interface();
}