Example #1
0
static int read_all(struct elf32_info *info, FILE *in)
{
	memset(info, 0, sizeof(info));

	if (read_ehdr(info, in) < 0)
		return -1;

	if (info->file_ehdr.e_machine != EM_MSP430)
		printc_err("elf32: warning: unknown machine type: 0x%x 0x%x\n",
			info->file_ehdr.e_machine, EM_MSP430);

	if (read_phdr(info, in) < 0)
		return -1;
	if (read_shdr(info, in) < 0)
		return -1;

	return 0;
}
Example #2
0
int read_elf(char *filename, struct _memory *memory, uint8_t *cpu_type, struct _symbols *symbols)
{
FILE *in;
uint8_t e_ident[16];
int e_shoff;
int e_shentsize;
int e_shnum;
int e_shstrndx;
int n;
int start, end;
struct _elf32_shdr elf32_shdr;
long strtab_offset = 0;
get_int16_t get_int16;
get_int32_t get_int32;

  memory_clear(memory);
  //memset(dirty, 0, memory->size);

  start = -1;
  end = -1;

  in = fopen(filename, "rb");
  if (in == 0)
  {
    return -1;
  }

  memset(e_ident, 0, 16);
  n = fread(e_ident, 1, 16, in);

  if (e_ident[0] != 0x7f || e_ident[1] != 'E' ||
      e_ident[2] != 'L' || e_ident[3] != 'F')
  {
    //printf("Not an ELF file.\n");
    fclose(in);
    return -2;
  }

  #define EI_CLASS 4   // 1=32 bit, 2=64 bit
  #define EI_DATA 5    // 1=little endian, 2=big endian
  #define EI_OSABI 7   // 0=SysV, 255=Embedded

  if (e_ident[EI_CLASS] != 1) // let's let other stuff in || e_ident[7]!=0xff)
  {
    printf("ELF Error: e_ident shows incorrect type\n");
    fclose(in);
    return -1;
  }

  // EI_DATA
  if (e_ident[EI_DATA] == 1)
  {
    memory->endian = ENDIAN_LITTLE;
    get_int16 = get_int16_le; 
    get_int32 = get_int32_le; 
  }
    else
  if (e_ident[EI_DATA] == 2)
  {
    memory->endian = ENDIAN_BIG;
    get_int16 = get_int16_be; 
    get_int32 = get_int32_be; 
  }
    else
  {
    printf("ELF Error: EI_DATA incorrect data encoding\n");
    fclose(in);
    return -1;
  }

  get_int16(in);
  n = get_int16(in);

  switch(n)
  {
    case 8:
    case 10:
      *cpu_type = CPU_TYPE_MIPS;
      break;
    case 40:
      *cpu_type = CPU_TYPE_ARM;
      break;
    case 83:
      *cpu_type = CPU_TYPE_AVR8;
      break;
    case 105:
      *cpu_type = CPU_TYPE_MSP430;
      break;
    case 118:
      *cpu_type = CPU_TYPE_DSPIC;
      break;
    default:
      printf("ELF Error: e_machine unknown\n");
      fclose(in);
      return -1;
  }

  fseek(in, 32, SEEK_SET);
  e_shoff = get_int32(in);
  fseek(in, 46, SEEK_SET);
  e_shentsize = get_int16(in);
  e_shnum = get_int16(in);
  e_shstrndx = get_int16(in);

  //printf("e_shoff=%d\n", e_shoff);
  //printf("e_shentsize=%d\n", e_shentsize);
  //printf("e_shnum=%d\n", e_shnum);
  //printf("e_shstrndx=%d\n", e_shstrndx);

  fseek(in, e_shoff + (e_shstrndx * e_shentsize) + 16, SEEK_SET);
  int stroffset = get_int32(in);
  char name[32];

  // Need to find .strtab so we can fill in symbol names
  for (n = 0; n < e_shnum; n++)
  {
    fseek(in, e_shoff + (n * e_shentsize), SEEK_SET);
    read_shdr(in, &elf32_shdr, get_int32);

    if (elf32_shdr.sh_type == SHT_STRTAB)
    {
      read_name(in, name, 32, stroffset + elf32_shdr.sh_name);
      if (strcmp(name, ".strtab") == 0)
      {
        strtab_offset = elf32_shdr.sh_offset;
        break;
      }
    }
  }

  for (n = 0; n < e_shnum; n++)
  {
    // FIXME - a little inefficient eh?
    fseek(in, e_shoff + (n * e_shentsize), SEEK_SET);
    read_shdr(in, &elf32_shdr, get_int32);

    read_name(in, name, 32, stroffset + elf32_shdr.sh_name);

    //printf("name=%s\n", name);
    //int is_text = strncmp(name, ".text", 5) == 0 ? 1 : 0;
    int is_text = (elf32_shdr.sh_flags & SHF_EXECINSTR) != 0 ? 1 : 0;
    if (is_text ||
        strncmp(name, ".data", 5) == 0 || strcmp(name, ".vectors") == 0)
    {
      if (is_text)
      {
        if (start == -1) { start = elf32_shdr.sh_addr; }
        else if (start > elf32_shdr.sh_addr) { start = elf32_shdr.sh_addr; }

        if (end == -1) { end = elf32_shdr.sh_addr + elf32_shdr.sh_size - 1; }
        else if (end < elf32_shdr.sh_addr + elf32_shdr.sh_size) { end = elf32_shdr.sh_addr+elf32_shdr.sh_size - 1; }
      }

      long marker = ftell(in);
      fseek(in, elf32_shdr.sh_offset, SEEK_SET);

      int n;
      for (n = 0; n < elf32_shdr.sh_size; n++)
      {
        if (elf32_shdr.sh_addr + n >= memory->size) break;
        memory_write_m(memory, elf32_shdr.sh_addr + n, getc(in)); 
      }

      fseek(in, marker, SEEK_SET);

      printf("Loaded %d %s bytes from 0x%04x\n", n, name, elf32_shdr.sh_addr);
    }
      else
    if (elf32_shdr.sh_type == SHT_SYMTAB && symbols != NULL)
    {
      long marker = ftell(in);
      fseek(in, elf32_shdr.sh_offset, SEEK_SET);

      for (n = 0; n < elf32_shdr.sh_size; n += 16)
      {
        char name[128];

        struct _elf32_sym elf32_sym;
        elf32_sym.st_name = get_int32(in);
        elf32_sym.st_value = get_int32(in);
        elf32_sym.st_size = get_int32(in);
        elf32_sym.st_info = getc(in);
        elf32_sym.st_other = getc(in);
        elf32_sym.st_shndx = get_int16(in);

        read_name(in, name, 128, strtab_offset + elf32_sym.st_name);

        printf("symbol %12s 0x%04x\n", name, elf32_sym.st_value);
        if (elf32_sym.st_info != STT_NOTYPE &&
            elf32_sym.st_info != STT_SECTION &&
            elf32_sym.st_info != STT_FILE)
        {
          symbols_append(symbols, name, elf32_sym.st_value);
        }
      }
      fseek(in, marker, SEEK_SET);
    }
  }

  memory->low_address = start;
  memory->high_address = end;

  fclose(in);

  return start;
}